diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:45 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:41:45 -0500 |
commit | 1109132f09d75da9a28b649c7677bb6ce07c40c0 (patch) | |
tree | 0dd8b084480983cf9f9680e8aedb92782a921b13 /files/es/learn | |
parent | 4b1a9203c547c019fc5398082ae19a3f3d4c3efe (diff) | |
download | translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.tar.gz translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.tar.bz2 translated-content-1109132f09d75da9a28b649c7677bb6ce07c40c0.zip |
initial commit
Diffstat (limited to 'files/es/learn')
189 files changed, 54268 insertions, 0 deletions
diff --git a/files/es/learn/accessibility/accessibility_troubleshooting/index.html b/files/es/learn/accessibility/accessibility_troubleshooting/index.html new file mode 100644 index 0000000000..2509ef8aa5 --- /dev/null +++ b/files/es/learn/accessibility/accessibility_troubleshooting/index.html @@ -0,0 +1,144 @@ +--- +title: 'Evaluación: Solución de problemas de accesibilidad' +slug: Learn/Accessibility/Accessibility_troubleshooting +tags: + - Accesibilidad + - Aprender + - CSS + - Evaluación + - HTML + - JavaScript + - Principiante + - WAI-ARIA +translation_of: Learn/Accessibility/Accessibility_troubleshooting +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/Accessibility/Mobile", "Learn/Accessibility")}}</div> + +<p class="summary">En la evaluación de este módulo, le presentamos un sitio simple con una serie de problemas de accesibilidad que necesita diagnosticar y corregir.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Conocimiento de informática básica, una comprensión básica de HTML, CSS y JavaScript, una comprensión de los artículos anteriores del curso.</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Probar los conocimientos básicos de los fundamentos de accesibilidad.</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Para iniciar esta evaluación, debe ir y tomar el <a href="https://github.com/mdn/learning-area/blob/master/accessibility/assessment-start/assessment-files.zip?raw=true">archivo ZIP que contiene los archivos que componen el ejemplo.</a> Descomprima el contenido en un nuevo directorio en algún lugar del equipo local.</p> + +<p>Alternativamente, podría usar un sitio como <a href="http://jsbin.com/">JSBin</a> o <a href="https://glitch.com/">Glitch</a> para hacer su evaluación. Puede pegar el HTML, CSS y JavaScript en uno de estos editores en línea. Si el editor en línea que está utilizando no tiene un panel CSS/JS independiente, no dude en colocarlos en elementos apropiados <code><style></code> / <code><script>.</code> </p> + +<p>El sitio de evaluación terminado debe tener este aspecto:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14555/assessment-site-finished.png" style="border-style: solid; border-width: 1px; display: block; height: 457px; margin: 0px auto; width: 800px;"></p> + +<p>Verá algunas diferencias/problemas con la visualización del estado inicial de la evaluación — esto se debe principalmente a las diferencias en el marcado, que a su vez causan algunos problemas de estilo, ya que el CSS no se aplica correctamente. No se preocupe, ¡estará solucionando estos problemas en las próximas secciones!</p> + +<div class="blockIndicator note"> +<table style="height: 73px; width: 535px;"> + <tbody> + <tr> + <td style="width: 555px; height: 63px;"> + <p><strong>Nota: </strong>Si se queda atorado, pídanos ayuda — consulta la sección <a href="https://developer.mozilla.org/es/docs/Learn/Accessibility/Accessibility_troubleshooting#Assessment_or_further_help">Evaluación o más ayuda</a> en la parte inferior de esta página.</p> + </td> + </tr> + </tbody> +</table> +</div> + +<h2 id="Resumen_del_proyecto">Resumen del proyecto</h2> + +<p>Para este proyecto, se le presenta un sitio ficticio de la naturaleza que muestra un artículo "fáctico" sobre los osos. Tal como está, tiene una serie de problemas de accesibilidad: su tarea es explorar el sitio existente y solucionarlos lo mejor de sus capacidades, respondiendo a las preguntas que se indican a continuación.</p> + +<h3 id="Color">Color</h3> + +<p>El texto es difícil de leer debido al esquema de color actual. ¿Puede realizar una prueba del contraste de color actual (texto/fondo), notificar los resultados de la prueba y, a continuación, corregirla cambiando los colores asignados?</p> + +<h3 id="HTML_Semántico">HTML Semántico</h3> + +<ol> + <li>El contenido todavía no es muy accesible: informe sobre lo que sucede cuando intenta navegar por él mediante un lector de pantalla.</li> + <li>¿Puede actualizar el texto del artículo para facilitar la navegación de los usuarios del lector de pantalla?</li> + <li>La parte del menú de navegación del sitio (limitada por <code><div class="nav"></div></code>) podría ser más accesible poniéndolo en un elemento semántico HTML5 adecuado. ¿A cuál debería actualizarse? Realice la actualización.</li> +</ol> + +<div class="note"> +<table style="height: 117px; width: 535px;"> + <tbody> + <tr> + <td style="width: 555px; height: 63px;"> + <p><strong>Nota: </strong>Tendrá que actualizar los selectores de reglas CSS que estilan las etiquetas a sus equivalentes adecuados para los encabezados semánticos. Una vez que agregue elementos de párrafo, notará que el estilo se ve mejor.</p> + </td> + </tr> + </tbody> +</table> +</div> + +<h3 id="Las_imágenes"><font>Las imágenes</font></h3> + +<p>Las imágenes son actualmente inaccesibles para los usuarios del lector de pantalla. ¿Puede arreglarlo?</p> + +<h3 id="El_reproductor_de_audio">El reproductor de audio</h3> + +<ol> + <li>El reproductor de <code><audio></code> no es accesible para personas con discapacidad auditiva (sordos) - ¿podría añadir algún tipo de alternativa accesible para estos usuarios?</li> + <li>El reproductor de <code><audio></code> no es accesible para aquellos que utilizan navegadores más antiguos que no admiten audio HTML5. ¿Cómo podrías permitir que sigan accediendo al audio?</li> +</ol> + +<h3 id="Los_formularios"><font>Los formularios</font></h3> + +<ol> + <li>El elemento <code><input></code> en el formulario de búsqueda en la parte superior se podría hacer con una etiqueta, pero no queremos agregar una etiqueta de texto visible que potencialmente estropearía el diseño y realmente no es necesaria para los usuarios sin discapacidad visual. ¿Cómo podría agregar una etiqueta a la que solo puedan acceder los lectores de pantalla?</li> + <li>Los dos elementos <code><input></code> del formulario en el comentario tienen etiquetas de texto visibles, pero no están inequívocamente asociados con sus etiquetas, ¿cómo lograría esto? Tenga en cuenta que también tendrá que actualizar parte de la regla CSS.</li> +</ol> + +<h3 id="El_control_de_mostrarocultar_comentarios"><font>El control de mostrar/ocultar comentarios</font></h3> + +<p>El botón de control de mostrar/ocultar comentarios no es accesible por teclado actualmente. ¿Puede hacerlo accesible al teclado, tanto en términos de enfocarlo usando la tecla de tabulación como de activarlo usando la tecla de retorno?</p> + +<h3 id="La_tabla"><font>La tabla</font></h3> + +<p>La tabla de datos no es muy accesible actualmente: es difícil para los usuarios del lector de pantalla asociar filas y columnas de datos, y la tabla tampoco tiene ningún tipo de resumen para dejar claro lo que muestra. ¿Puede agregar algunas características a su HTML para solucionar este problema?</p> + +<h3 id="¿Otras_consideraciones"><font>¿Otras consideraciones?</font></h3> + +<p>¿Puede enumerar dos ideas más para mejoras que podrían hacer que el sitio web sea más accesible?</p> + +<h2 id="Evaluación_o_más_ayuda">Evaluación o más ayuda</h2> + +<p>Si desea que se evalúe su trabajo, o si está atorado y desea pedir ayuda:</p> + +<ol> + <li>Ponga su trabajo en un editor compartible en línea como <a href="https://codepen.io/">CodePen,</a> <a href="https://jsfiddle.net/">jsFiddle</a>o <a href="https://glitch.com/">Glitch</a>.</li> + <li>Escribe una publicación pidiendo evaluación y/o ayuda en la categoría Aprendizaje del <a href="https://discourse.mozilla.org/c/mdn/learn">foro de discurso mdn</a>. Su publicación debe incluir:Un título descriptivo como "Evaluación deseada para la solución de problemas de accesibilidad".</li> + <li> + <ul> + <li>Detalles de lo que ya ha intentado, y lo que le gustaría que hagamos, por ejemplo, si está atascado y necesita ayuda, o quiere una evaluación.</li> + <li>Un enlace al ejemplo con el que desea evaluar o necesita ayuda, en un editor de compartición en línea (como se mencionó en el paso 1 anterior). Esta es una buena práctica a adquirir - es muy difícil ayudar a alguien con un problema de codificación si no se puede ver su código.</li> + <li>Un enlace a la tarea actual o página de evaluación, para que podamos encontrar la pregunta con la que desea ayuda.</li> + </ul> + </li> +</ol> + +<p><font>{{PreviousMenu("Learn/Accessibility/Mobile", "Learn/Accessibility")}}</font></p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Accessibility/What_is_accessibility">¿Qué es la accesibilidad?</a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Accessibility/HTML">HTML: Una buena base para la accesibilidad</a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">Prácticas recomendadas de accesibilidad CSS y JavaScript</a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">Conceptos básicos de WAI-ARIA</a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Accessibility/Mobile">Accesibilidad móvil</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Mobile">Mobile accessibility</a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Solución de problemas de accesibilidad</a></li> +</ul> diff --git a/files/es/learn/accessibility/css_and_javascript/index.html b/files/es/learn/accessibility/css_and_javascript/index.html new file mode 100644 index 0000000000..5f12f39466 --- /dev/null +++ b/files/es/learn/accessibility/css_and_javascript/index.html @@ -0,0 +1,359 @@ +--- +title: Buenas prácticas de accesibilidad CSS y JavaScript +slug: Learn/Accessibility/CSS_and_JavaScript +translation_of: Learn/Accessibility/CSS_and_JavaScript +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Accessibility/HTML","Learn/Accessibility/WAI-ARIA_basics", "Learn/Accessibility")}}</div> + +<p class="summary">CSS y JavaScript, cuando se usan correctamente, también tienen el potencial de permitir experiencias web accesibles... o pueden dañar significativamente la accesibilidad si se usan incorrectamente. Este artículo describe algunas de las mejores prácticas de CSS y JavaScript que deben tenerse en cuenta para garantizar que incluso el contenido complejo sea lo más accesible posible.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, conocimientos básicos de HTML, CSS y JavaScript, y comprensión de <a href="/es/docs/Learn/Accessibility/Qué_es_la_accesibilidad">qué es la accesibilidad</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Familiarizarse con el uso apropiado de CSS y JavaScript en documentos web para maximizar la accesibilidad y no restarle valor.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="¿CSS_y_JavaScript_son_accesibles">¿CSS y JavaScript son accesibles?</h2> + +<p>CSS y JavaScript no tienen la misma importancia inmediata para la accesibilidad que HTML, pero aún así pueden ayudar o dañar la accesibilidad, dependiendo de cómo se usen. Para decirlo de otra manera, es importante considerar algunos consejos de buenas prácticas para asegurarse de que el uso de CSS y JavaScript no arruina la accesibilidad de tus documentos.</p> + +<h2 id="CSS">CSS</h2> + +<p>Comencemos estudiando CSS.</p> + +<h3 id="Semántica_correcta_y_expectativas_del_usuario">Semántica correcta y expectativas del usuario</h3> + +<p><span class="tlid-translation translation" lang="es">Es posible usar CSS para hacer que cualquier elemento HTML se vea como <em>cualquier cosa</em>, pero esto no significa que deba hacerse. Como mencionamos con frecuencia en nuestro artículo <a href="/es/docs/Learn/Accessibility/HTML">HTML: Una buena base para la accesibilidad</a>, debes usar el elemento semántico apropiado para cada cosa, siempre que sea posible. Si no lo haces, puede causar confusión y problemas de usabilidad para todos, pero especialmente para los usuarios con discapacidades. El uso de la semántica correcta tiene mucho que ver con las expectativas del usuario: los elementos se ven y se comportan de cierta manera, de acuerdo con su funcionalidad, y los usuarios esperan estas convenciones comunes.</span></p> + +<p>Por ejemplo, un usuario de lector de pantalla no puede navegar por una página a través de elementos de encabezado si el desarrollador no ha utilizado adecuadamente los elementos de encabezado para marcar el contenido. Del mismo modo, un encabezado pierde su propósito visual si se le aplica un estilo para que no parezca un encabezado.</p> + +<p>La regla general es que puede actualizar el estilo de una característica de la página para que se ajuste a tu diseño, pero no cambiarlo tanto como para que ya no se vea ni se comporte como se esperaba. Las siguientes secciones resumen las principales características de HTML a considerar.</p> + +<h4 id="Estructura_de_contenido_de_texto_estándar">Estructura de contenido de texto "estándar"</h4> + +<p>Encabezados, párrafos, listas: el contenido de texto central de su página:</p> + +<pre class="brush: html notranslate"><h1>Cabecera</h1> + +<p>Párrafo</p> + +<ul> + <li>Mi lista</li> + <li>tiene dos ítems.</li> +</ul></pre> + +<p>Un CSS típico podría tener este aspecto:</p> + +<pre class="brush: css notranslate">h1 { + font-size: 5rem; +} + +p, li { + line-height: 1.5; + font-size: 1.6rem; +}</pre> + +<p>Deberías:</p> + +<ul> + <li>Seleccionar tamaños de fuente razonables, alturas de línea, espaciado entre letras, etc. para que el texto sea lógico, legible y cómodo de leer.</li> + <li>Asegurarte de que los títulos destaquen del texto del cuerpo, generalmente grandes y en negrita como estilo predeterminado. Tus listas deben parecer</li> + <li>El color del texto debe contrastar bien con el color de fondo.</li> +</ul> + +<p>Consulte <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/texto">Fundamentos del texto HTML</a> y <a href="/es/docs/Learn/CSS/Styling_text">Estilo de texto</a> para obtener más información.</p> + +<h4 id="Texto_enfatizado">Texto enfatizado</h4> + +<p>Marcado en línea que confiere un énfasis específico al texto que rodea:</p> + +<pre class="brush: html notranslate"><p>El agua está <em>muy caliente</em>.</p> + +<p>Las gotas de agua que se acumulan en las superficies se denominan <strong>condensación</strong>.</p></pre> + +<p>Es posible que desees agregar algunos colores simples a su texto enfatizado:</p> + +<pre class="brush: css notranslate">strong, em { + color: #a60000; +}</pre> + +<p>Sin embargo, rara vez necesitarás dar estilo a elementos de énfasis de manera significativa. Las convenciones estándar de texto en negrita y cursiva son muy reconocibles y cambiar el estilo puede causar confusión. Para obtener más información sobre el énfasis, consulte <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/texto#%C3%89nfasis_e_importancia">Énfasis e importancia</a>.</p> + +<h4 id="Abreviaciones">Abreviaciones</h4> + +<p>Un elemento que permite asociar una abreviatura, un acrónimo o una inicialización a su expansión:</p> + +<pre class="brush: html notranslate"><p>El contenido web se marca usando <abbr title="Hypertext Markup Language">HTML</abbr>.</p></pre> + +<p>Nuevamente, es posible que desees darle estilo de una manera simple:</p> + +<pre class="brush: css notranslate">abbr { + color: #a60000; +}</pre> + +<p>La convención de estilo reconocida para las abreviaturas es un subrayado punteado, y no es aconsejable desviarse significativamente de esto. Para obtener más información sobre abreviaturas, consulte <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/Advanced_text_formatting#Abreviaturas">Abreviaturas</a>.</p> + +<h4 id="Enlaces">Enlaces</h4> + +<p>Hipervínculos: la forma de llegar a nuevos lugares en la web:</p> + +<pre class="brush: html notranslate"><p>Visita la <a href="https://www.mozilla.org">página de inicio de Mozilla</a>.</p></pre> + +<p>A continuación se muestra un estilo de enlace muy simple:</p> + +<pre class="brush: css notranslate">a { + color: #ff0000; +} + +a:hover, a:visited, a:focus { + color: #a60000; + text-decoration: none; +} + +a:active { + color: #000000; + background-color: #a60000; +}</pre> + +<p>Las convenciones de enlace estándar son subrayado y un color diferente (predeterminado: azul) en su estado estándar, otra variación de color cuando el enlace ha sido visitado anteriormente (predeterminado: púrpura) y otro color más cuando el enlace está activado (predeterminado: rojo) . Además, el puntero del ratón cambia a un ícono de puntero cuando se pasa el ratón sobre los enlaces, y el enlace recibe un resaltado cuando se enfoca (por ejemplo, mediante tabulación) o se activa. La siguiente imagen muestra el resaltado tanto en Firefox (contorno punteado) como en Chrome (contorno azul):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14371/focus-highlight-firefox.png" style="display: block; height: 173px; margin: 0px auto; width: 319px;"></p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14369/focus-highlight-chrome.png" style="display: block; height: 169px; margin: 0px auto; width: 309px;"></p> + +<p>Puedes ser creativo con los estilos de enlaces, siempre y cuando sigas dando información a los usuarios cuando interactúan con los enlaces. Definitivamente, algo debería suceder cuando los estados cambian, y no debes deshacerte del cursor del puntero o del contorno; ambos son ayudas de accesibilidad muy importantes para quienes usan los controles del teclado.</p> + +<h4 id="Elementos_de_formulario">Elementos de formulario</h4> + +<p>Elementos que permiten a los usuarios introducir datos en sitios web:</p> + +<pre class="brush: html notranslate"><div> + <label for="nombre">Entra tu nombre</label> + <input type="text" id="nombre" name="nombre"> +</div></pre> + +<p>Puedes ver algunos buenos ejemplos de CSS en nuestro ejemplo de <a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/form-css.html">form-css.html</a> (<a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/form-css.html">pruébalo en vivo</a> también).</p> + +<p>La mayor parte del CSS que escribirás para los formularios será para dimensionar los elementos, alinear las etiquetas y las entradas y hacer que se vean limpios y ordenados.</p> + +<p>Sin embargo, no debes desviarse demasiado de la retroalimentación visual esperada que reciben los elementos del formulario cuando están enfocados, que es básicamente la mismo que con los enlaces (ver más arriba). Puedes aplicar estilos a los estados de enfoque / desplazamiento del formulario para que este comportamiento sea más coherente en todos los navegadores o se adapte mejor al diseño de tu página, pero no te deshagas de él por completo; de nuevo, las personas confían en estas pistas para ayudarles a saber qué está pasando.</p> + +<h4 id="Tablas">Tablas</h4> + +<p>Tablas para presentar datos tabulares.</p> + +<p>Puedes ver un buen y simple ejemplo de tabla HTML y CSS en nuestro ejemplo <a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/table-css.html">table-css.html</a> (<a href="http://mdn.github.io/learning-area/accessibility/css/table-css.html">pruébalo en vivo</a> también).</p> + +<p>El CSS de tablas generalmente sirve para hacer que la tabla se adapte mejor a su diseño y se vea menos fea. Es una buena idea asegurarse de que los encabezados de la tabla se destaquen (normalmente en negrita) y usar rayas de cebra para que las diferentes filas sean más fáciles de analizar.</p> + +<h3 id="Color_y_contraste_de_color">Color y contraste de color</h3> + +<p>Al elegir un esquema de color para tu sitio web, asegúrate de que el color del texto (primer plano) contrasta bien con el color de fondo. Tu diseño puede verse bien, pero no es bueno si las personas con discapacidades visuales como daltonismo no pueden leer tu contenido.</p> + +<p>Existe una manera fácil de verificar si el contraste es lo suficientemente grande como para no causar problemas. Hay una serie de herramientas de verificación de contraste en línea en las que puede introduci los colores de primer plano y de fondo para verificarlos. Por ejemplo, el <a href="http://webaim.org/resources/contrastchecker/">Comprobador de contraste de color</a> de WebAIM es fácil de usar y proporciona una explicación de lo que necesitas para cumplir con los criterios WCAG sobre el contraste de color.</p> + +<div class="note"> +<p><strong>Nota</strong>: una relación de contraste alta también permitirá que cualquier persona que utilice un teléfono inteligente o una tableta con una pantalla brillante lea mejor las páginas cuando se encuentre en un entorno brillante, como a la luz del sol.</p> +</div> + +<p>Otro consejo es no confiar solo en el color para las señales / información, ya que esto no será bueno para aquellos que no pueden ver el color. En lugar de marcar los campos de formulario obligatorios en rojo, por ejemplo, márcalos con un asterisco y en rojo.</p> + +<h3 id="Esconder_cosas">Esconder cosas</h3> + +<p>Hay muchos casos en los que un diseño visual requerirá que no se muestre todo el contenido a la vez. Por ejemplo, en nuestro ejemplo de <a href="http://mdn.github.io/learning-area/css/css-layout/practical-positioning-examples/info-box.html">cuadro de información con pestañas</a> (ver <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/practical-positioning-examples/info-box.html">código fuente</a>) tenemos tres paneles de información, pero los colocamos uno encima del otro y proporcionamos pestañas en las que se puede hacer clic para mostrar cada uno (también es accesible desde el teclado - pues usar alternativamente Tab y Enter / Return para seleccionarlos).</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13368/tabbed-info-box.png" style="display: block; height: 400px; margin: 0px auto; width: 450px;"></p> + +<p>A los usuarios de lectores de pantalla no les importa nada de esto: están contentos con el contenido siempre que el orden del código fuente tenga sentido y puedan acceder a todo. El posicionamiento absoluto (como se usa en este ejemplo) generalmente se considera uno de los mejores mecanismos para ocultar contenido para lograr un efecto visual, porque no impide que los lectores de pantalla accedan a él.</p> + +<p>Por otro lado, no debes usar {{cssxref ("visibility")}}<code>: hidden</code> o {{cssxref ("display")}}<code>: none</code>, porque ocultan el contenido de los lectores de pantalla. A menos que, por supuesto, exista una buena razón por la que desees ocultar este contenido a los lectores de pantalla.</p> + +<div class="note"> +<p><strong>Nota</strong>: <span class="subtitle"><a href="http://webaim.org/techniques/css/invisiblecontent/">Invisible Content Just for Screen Reader Users</a> </span>tiene muchos más detalles útiles sobre este tema.</p> +</div> + +<h3 id="Acepta_que_los_usuarios_pueden_saltarse_tus_estilos">Acepta que los usuarios pueden saltarse tus estilos</h3> + +<p>Es posible que los usuarios anulen tus estilos con sus propios estilos personalizados, por ejemplo:</p> + +<ul> + <li>Consulte <a class="external external-icon" href="https://www.itsupportguides.com/knowledge-base/computer-accessibility/how-to-use-a-custom-style-sheet-css-with-firefox/" rel="noopener">How to use a custom style sheet (CSS) with Firefox</a>, de Sarah Maddox, una útil guía que cubre cómo hacer esto manualmente en Firefox.</li> + <li>Probablemente sea más fácil hacerlo usando una extensión; por ejemplo, la extensión Stylish está disponible para <a href="https://addons.mozilla.org/en-US/firefox/addon/stylish/">Firefox</a>, <a href="https://safari-extensions.apple.com/details/?id=com.sobolev.stylish-5555L95H45">Safari</a>, <a href="https://addons.opera.com/en/extensions/details/stylish/">Opera</a> y <a href="https://chrome.google.com/webstore/detail/stylish/fjnbnpbmkenffdnngjfgmeleoegfcffe">Chrome</a>.</li> +</ul> + +<p><span class="tlid-translation translation" lang="es">Los usuarios pueden hacerlo por diversas razones. Un usuario con discapacidad visual puede querer agrandar el texto en todos los sitios web que visita, o un usuario con una deficiencia de color severa puede querer poner todos los sitios web en colores de alto contraste que sean fáciles de ver. Cualquiera que sea la necesidad, debes sentirse cómodo con esto y hacer que tus diseños sean lo suficientemente flexibles para que dichos cambios funcionen en tu diseño. Como ejemplo, es posible que desees asegurarte de que tu área de contenido principal pueda manejar texto más grande (tal vez comience a desplazarse para permitir que se vea todo), y no solo lo ocultará o romperá por completo.</span></p> + +<h2 id="JavaScript">JavaScript</h2> + +<p>JavaScript también puede romper la accesibilidad, dependiendo de cómo se use.</p> + +<p>El JavaScript moderno es un lenguaje poderoso, y podemos hacer mucho con él actualmente, desde contenido simple y actualizaciones de la interfaz de usuario hasta juegos 2D y 3D completos. No existe una regla que diga que todo el contenido debe ser 100% accesible para todas las personas; solo debe hacer lo que pueda y hacer que sus aplicaciones sean lo más accesibles posible.</p> + +<p>Se puede decir que el contenido y la funcionalidad simples son fáciles de hacer accesibles; por ejemplo, texto, imágenes, tablas, formularios y botones que activan funciones. Como vimos en nuestro artículo <a href="https://developer.mozilla.org/es/docs/Learn/Accessibility/HTML">HTML: Una buena base para la accesibilidad</a>, las consideraciones clave son:</p> + +<ul> + <li>Buena semántica: usar el elemento correcto para el trabajo correcto. Por ejemplo, asegúrate de usar encabezados y párrafos, y elementos {{htmlelement ("button")}} y {{htmlelement ("a")}}</li> + <li>Asegurarse de que el contenido esté disponible como texto, ya sea directamente como contenido de texto, buenas etiquetas de texto para los elementos de formulario o alternativas de texto, p.ej. texto alternativo para imágenes.</li> +</ul> + +<p>También vimos un ejemplo de cómo usar JavaScript para incorporar la funcionalidad donde faltaba; consulta <a href="/es/docs/Learn/Accessibility/HTML#Volver_a_añadir_la_accesibilidad_del_teclado">Volver a añadir la accesibilidad del teclado</a>. Esto no es ideal; en realidad, deberías usar el elemento correcto para el trabajo correcto, pero demuestra que es posible en situaciones en las que, por alguna razón, no puedes controlar el marcado que se utiliza. Otra forma de mejorar la accesibilidad de los widgets no semánticos que funcionan con JavaScript es utilizar WAI-ARIA para proporcionar semántica adicional para los usuarios de lectores de pantalla. El próximo artículo también cubrirá esto en detalle.</p> + +<p>Las funcionalidades complejas como los juegos en 3D no son tan fáciles de hacer accesibles: un juego en 3D complejo creado con <a href="/es/docs/Web/API/WebGL_API">WebGL</a> se renderizará en un elemento {{htmlelement ("canvas")}}, que en este momento no tiene la capacidad de proporcionar alternativas de texto u otros información que pueden utilizar los usuarios con discapacidad visual grave. Se puede argumentar que un juego de este tipo no tiene realmente a este grupo de personas como parte de su público objetivo principal, y no sería razonable esperar que lo hicieras 100% accesible para las personas ciegas; sin embargo, podrías implementar controles de teclado para que sea utilizable por usuarios que no utilizan el ratóny hacer que el esquema de color sea lo suficientemente contrastante como para que lo puedan usar aquellos con deficiencias de color.</p> + +<h3 id="El_problema_de_demasiado_JavaScript">El problema de demasiado JavaScript</h3> + +<p>El problema a menudo surge cuando la gente confía demasiado en JavaScript. A veces verás un sitio web donde todo se ha hecho con JavaScript: el HTML ha sido generado por JavaScript, el CSS ha sido generado por JavaScript, etc. Esto tiene todo tipo de problemas de accesibilidad y otros asociados, por lo que no es aconsejado.</p> + +<p>Además de utilizar el elemento correcto para el trabajo correcto, ¡también debes asegurarte de utilizar la tecnología adecuada para el trabajo correcto! Piensa detenidamente si necesitas ese brillante cuadro de información en 3D con JavaScript o si bastaría con texto antiguo sin formato. Piensa detenidamente si necesitas un widget de formulario no estándar complejo o si una entrada de texto sería suficiente. Y no generes todo tu contenido HTML usando JavaScript si es posible.</p> + +<h3 id="Hacerlo_no_intrusivo">Hacerlo no intrusivo</h3> + +<p>Deberías hacer tu <strong>JavaScript no intrusivo</strong> al crear tu contenido. La idea de JavaScript no intrusivo es que debe usarse siempre que sea posible para mejorar la funcionalidad, no para construirlo todo; las funciones básicas deberían funcionar idealmente sin JavaScript, aunque sabemos que esto no siempre es una opción. Pero, de nuevo, una gran parte es usar las funcionalidades integradas del navegador siempre que sea posible.</p> + +<p>Entre los buenos ejemplos de usos de JavaScript no intrusivo se incluyen:</p> + +<ul> + <li>Proporcionar validación de formularios del lado del cliente, que alerta a los usuarios sobre problemas con las entradas de sus formularios rápidamente, sin tener que esperar a que el servidor verifique los datos. Si no está disponible, el formulario seguirá funcionando, pero la validación puede ser más lenta.</li> + <li>Proporcionar controles personalizados para <code><video></code> HTML5 a los que pueden acceder los usuarios que solo utilizan el teclado, junto con un enlace directo al video que se puede usar para acceder a él si JavaScript no está disponible (los controles del navegador predeterminados para <code><video></code> no son acccesibles por teclado en la mayoría de los navegadores).</li> +</ul> + +<p><span class="tlid-translation translation" lang="es">Como ejemplo, hemos escrito un ejemplo rápido y sucio de validación de formulario del lado del cliente: consulta <a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/form-validation.html">form-validation.html</a> (y también la <a href="http://mdn.github.io/learning-area/accessibility/css/form-validation.html">demostración en vivo</a>). Aquí verás un formulario simple; al intentar enviar el formulario con uno o ambos campos vacíos, el envío falla y aparece un cuadro de mensaje de error para indicar cuál es el problema.<br> + <br> + Este tipo de validación de formulario es no intrusiva: se puede usar el formulario perfectamente aunque JavaScript no esté disponible, y cualquier implementación de formulario razonable también tendrá activa la validación del lado del servidor, porque es demasiado fácil para los usuarios malintencionados eludir la validación del lado del cliente (por ejemplo, desactivando JavaScript en el navegador). La validación del lado del cliente sigue siendo realmente útil para informar de errores: los usuarios pueden saber los errores que cometen al instante, en lugar de tener que esperar un viaje de ida y vuelta al servidor y la recarga de la página. Esta es una clara ventaja de usabilidad.</span></p> + +<div class="note"> +<p><strong>Nota</strong>: la validación del lado del servidor no se ha implementado en esta simple demostración.</p> +</div> + +<p>También hemos hecho que esta validación de formulario sea bastante accesible. Hemos utilizado elementos {{htmlelement ("label")}} para asegurarnos de que las etiquetas del formulario estén vinculadas de forma inequívoca a sus entradas, de modo que los lectores de pantalla puedan leerlas junto con ellas:</p> + +<pre class="brush: html notranslate"><label for="name">Entra tu nombre:</label> +<input type="text" name="name" id="name"></pre> + +<p>Solo realizamos la validación cuando se envía el formulario; esto es para no actualizar la IU con demasiada frecuencia y confundir potencialmente a los lectores de pantalla (y posiblemente a otros) usuarios:</p> + +<pre class="brush: js notranslate">form.onsubmit = validate; + +function validate(e) { + errorList.innerHTML = ''; + for(let i = 0; i < formItems.length; i++) { + const testItem = formItems[i]; + if(testItem.input.value === '') { + errorField.style.left = '360px'; + createLink(testItem); + } + } + + if(errorList.innerHTML !== '') { + e.preventDefault(); + } +}</pre> + +<div class="note"> +<p><strong>Nota</strong>: En este ejemplo estamos ocultando y mostrando el cuadro de mensaje de error utilizando posicionamiento absoluto en lugar de otro método como la visibilidad o la visualización, porque no interfiere con que el lector de pantalla pueda leer su contenido.</p> +</div> + +<p>La validación real del formulario sería mucho más compleja que esto: querría verificar que el nombre entrado realmente parezca un nombre, la edad entrada sea realmente un número y sea realista (por ejemplo, no negativa y menor de 4 dígitos). Aquí acabamos de implementar una verificación simple de que se haya completado un valor en cada campo de entrada (<code>if(testItem.input.value === '')</code>).</p> + +<p>Cuando se ha realizado la validación, si las pruebas pasan, se envía el formulario. Si hay errores (<code>if (errorList.innerHTML! == '')</code>), detenemos el envío del formulario (usando <code>preventDefault()</code>) y mostramos los mensajes de error que se hayan creado (ver más abajo). Este mecanismo significa que los errores solo se mostrarán si hay errores, lo que es mejor para la usabilidad.</p> + +<p>Para cada entrada sin un valor completado cuando se envía el formulario, creamos un elemento de lista con un enlace y lo insertamos en <code>errorList</code>.</p> + +<pre class="brush: js notranslate">function createLink(testItem) { + const listItem = document.createElement('li'); + const anchor = document.createElement('a'); + + anchor.textContent = 'El campo ' + testItem.input.name + ' está vacío. Entra tu ' + testItem.input.name + '.'; + anchor.href = '#' + testItem.input.name; + anchor.onclick = function() { + testItem.input.focus(); + }; + listItem.appendChild(anchor); + errorList.appendChild(listItem); +}</pre> + +<p>Cada enlace tiene un doble propósito: te dice cuál es el error, y además puedes hacer clic en él / activarlo para ir directamente al elemento de entrada en cuestión y corregir la entrada.</p> + +<div class="note"> +<p><strong>Nota</strong>: La parte <code>focus()</code> de este ejemplo es un poco complicada. Chrome y Edge darán foco al elemento al hacer clic en el enlace, sin necesidad del bloque <code>onclick</code> / <code>focus()</code>. Safari solo resaltará el elemento de formulario con el enlace por sí solo, por lo que necesita el bloque <code>onclick</code> / <code>focus()</code> para darle foco. Firefox no da foco a las entradas correctamente en este contexto, por lo que los usuarios de Firefox no pueden aprovechar esto en este momento (aunque todo lo demás funciona bien). El problema de Firefox debería solucionarse pronto; se está trabajando para que el comportamiento de Firefox sea igual al de otros navegadores (consulte {{bug (277178)}}).</p> +</div> + +<p>Además, el <code>errorField</code> se coloca en la parte superior del orden de código (aunque se coloca de manera diferente en la interfaz de usuario usando CSS), lo que significa que los usuarios pueden averiguar exactamente qué está mal con los envíos de sus formularios y acceder a los elementos de entrada en cuestión retrocediendo hasta el inicio de la página.</p> + +<p>Como nota final, hemos utilizado algunos atributos WAI-ARIA en nuestra demostración para ayudar a resolver los problemas de accesibilidad causados por áreas de contenido que se actualizan constantemente sin recargar la página (los lectores de pantalla no captan esto ni alertan a los usuarios de forma predeterminada):</p> + +<pre class="notranslate"><div class="errors" role="alert" aria-relevant="all"> + <ul> + </ul> +</div></pre> + +<p>Explicaremos estos atributos en nuestro próximo artículo, que cubre <a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA</a> con mucho más detalle.</p> + +<div class="note"> +<p><strong>Nota</strong>: Algunos de vosotros probablemente estaréis pensando en el hecho de que los formularios HTML5 tienen mecanismos de validación integrados como los atributos <code>required</code>, <code>min</code> / <code>minlength</code> y <code>max</code> / <code>maxlength</code> (consultad la referencia del elemento {{htmlelement("input")}} para más información). No los hemos usado en la demostración porque la compatibilidad entre navegadores es irregular (por ejemplo, solo funciona en IE10 y versiones superiores).</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: <a href="http://webaim.org/techniques/formvalidation/">Usable and Accessible Form Validation and Error Recovery</a>, de WebAIM, proporciona más información útil sobre la validación de formularios accesibles.</p> +</div> + +<h3 id="Otros_potenciales_problemas_de_accesibilidad_de_JavaScript">Otros potenciales problemas de accesibilidad de JavaScript</h3> + +<p>Hay otras cosas que debes tener en cuenta al implementar JavaScript y pensar en la accesibilidad. Agregaremos más a medida que los encontremos.</p> + +<h4 id="Eventos_específicos_del_ratón">Eventos específicos del ratón</h4> + +<p>Como sabrás, la mayoría de las interacciones de los usuarios se implementan en JavaScript del lado del cliente mediante controladores de eventos, que nos permiten ejecutar funciones en respuesta a ciertos eventos que suceden. Algunos eventos pueden tener problemas de accesibilidad. El ejemplo principal con el que se encontrará son los eventos específicos del ratón, como <code>mouseover</code>, <code>mouseout</code>, <code>dblclick</code>, etc. La funcionalidad que se ejecuta en respuesta a estos eventos no será accesible mediante otros mecanismos, como los controles del teclado.</p> + +<p>Para mitigar estos problemas, debes duplicar estos eventos con eventos similares que se pueden activar por otros medios (los llamados controladores de eventos independientes de dispositivo); <code>focus</code> y <code>blur</code> proporcionarían accesibilidad para los usuarios del teclado.</p> + +<p>Veamos un ejemplo que destaca cuándo esto podría ser útil. Tal vez queramos proporcionar una imagen en miniatura que muestre una versión más grande de la imagen cuando al colocar el ratón sobre ella o darle foco (como pasaría en un catálogo de productos de comercio electrónico).</p> + +<p>Hemos creado un ejemplo muy simple, que puedes encontrar en <a href="http://mdn.github.io/learning-area/accessibility/css/mouse-and-keyboard-events.html">mouse-and-keyboard-events.html</a> (consulta también el <a href="https://github.com/mdn/learning-area/blob/master/accessibility/css/mouse-and-keyboard-events.html">código fuente</a>). El código presenta dos funciones que muestran y ocultan la imagen ampliada; estas se ejecutan mediante las siguientes líneas que las configuran como controladores de eventos:</p> + +<pre class="brush: js notranslate">imgThumb.onmouseover = showImg; +imgThumb.onmouseout = hideImg; + +imgThumb.onfocus = showImg; +imgThumb.onblur = hideImg;</pre> + +<p>Las dos primeras líneas ejecutan las funciones cuando el puntero del ratón se desplaza sobre la miniatura y deja de hacerlo, respectivamente. Sin embargo, esto no nos permite acceder a la vista ampliada con el teclado; para hacerlo hemos incluido las dos últimas líneas, que ejecutan las funciones cuando la imagen toma y pierde el foco. Esto se puede hacer presionando el tabulador hasta llegar a la imagen, porque le hemos dado <code>tabindex="0"</code>.</p> + +<p>El evento de <code>click</code> es interesante: parce dependiente del ratón, pero la mayoría de los navegadores activan los controladores de eventos <code>onclick</code> al presionar Enter / Return en un enlace o elemento de formulario que tenga foco, o cuando dicho elemento se toca en un dispositivo de pantalla táctil. Sin embargo, esto no funciona por defecto cuando permites que un evento no enfocable por defecto adquiera el foco usando tabindex; en tales casos, debe detectar específicamente cuándo se presiona esa tecla exacta (consulte <a href="/es/docs/Learn/Accessibility/HTML#Volver_a_añadir_la_accesibilidad_del_teclado">Volver a añadir la accesibilidad del teclado</a>).</p> + +<h2 id="¡Pon_a_prueba_tus_habilidades">¡Pon a prueba tus habilidades</h2> + +<p>Has llegado al final de este artículo. ¿Recuerdas la información más importante? Encontrar pruebas para verificar que has retenido esta información antes de continuar en <a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript/Test_your_skills:_CSS_and_JavaScript_accessibility">Test your skills: CSS and JavaScript accessibility</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Esperamos que este artículo te haya brindado una buena cantidad de detalles y comprensión sobre los problemas de accesibilidad relacionados con el uso de CSS y JavaScript en las páginas web.</p> + +<p>¡Siguiente parada, WAI-ARIA!</p> + +<div>{{PreviousMenuNext("Learn/Accessibility/HTML","Learn/Accessibility/WAI-ARIA_basics", "Learn/Accessibility")}}</div> + +<div> +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">What is accessibility?</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/HTML">HTML: A good basis for accessibility</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">CSS and JavaScript accessibility best practices</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA basics</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Multimedia">Accessible multimedia</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Mobile">Mobile accessibility</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Accessibility troubleshooting</a></li> +</ul> +</div> diff --git a/files/es/learn/accessibility/html/index.html b/files/es/learn/accessibility/html/index.html new file mode 100644 index 0000000000..1b2fb1af25 --- /dev/null +++ b/files/es/learn/accessibility/html/index.html @@ -0,0 +1,588 @@ +--- +title: 'HTML: Una buena base para la accesibilidad' +slug: Learn/Accessibility/HTML +translation_of: Learn/Accessibility/HTML +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Accessibility/What_is_Accessibility","Learn/Accessibility/CSS_and_JavaScript", "Learn/Accessibility")}}</div> + +<p class="summary">Se puede hacer accesible una gran cantidad de contenido web solo asegurándose de que se utilizan los elementos HTML con el propósito correcto todo el tiempo. Este artículo muestra en detalle como HTML puede ser usado para asegurar máxima accesibilidad.</p> + +<table class="learn-box standard-table" style="height: 214px; width: 741px;"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimiento básico de informática, entendimiento básico de HTML (ver <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introducción a HTML</a>), y entendimiento de <a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">¿Qué es accesibilidad?</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarse con las características de HTML que tiene beneficios de accesibilidad, y como usarla apropiadamente en tus documentos web.</td> + </tr> + </tbody> +</table> + +<h2 id="HTML_y_accesibilidad">HTML y accesibilidad</h2> + +<p>Cuando aprendas más de HTML — leas más recursos, mires más ejemplos, etc.— vas a seguir viendo un tema en común: la importancia del uso de HTML semántico (a veces llamado POSH, o <em lang="en">Plain Old Semantic HTML</em>). Esto significa usar los elementos correctos de HTML para su propósito tanto como sea posible.</p> + +<p>Puedes estarte preguntando ¿por qué es esto tan importante?. Después de todo, puedes usar una combinación de CSS y JavaScript para hacer que casi cualquier elemento HTML se comporte en la forma que tú quieras. Por ejemplo, un botón que reproduzca un vídeo en tu sitio puede estar hecho así:</p> + +<pre class="brush: html notranslate"><div>Reproducir vídeo</div></pre> + +<p>Pero como verás más adelante, tiene sentido utilizar el elemento correcto para este trabajo:</p> + +<pre class="brush: html notranslate"><button>Reproducir vídeo</button></pre> + +<p>No solo la etiqueta <code><button></code> de HTML ya tiene estilos adecuados por defecto (que probablemente quieras sobrescribir), también están construidos para ser accesibles con el teclado —el usuario puede navegar entre botones usando <kbd>Tab</kbd> y activando su selección usando <kbd>Return</kbd> o <kbd>Enter</kbd>.</p> + +<p>No cuesta más tiempo escribir HTML semántico que (mal) marcado no semántico si lo haces consistentemente desde el comienzo de tu proyecto. Y aun mejor, el marcado semántico tiene otros beneficios más allá de la accesibilidad:</p> + +<ol> + <li><strong>Fácil desarrollo</strong> — como mencionamos, obtienes algunas funcionalidades gratis, y podría decirse que es más fácil de entender.</li> + <li><strong>Mejor en móviles</strong> — el HTML semántico es probablemente más liviano en tamaño de archivo que el código espagueti no semántico y más fácil de hacer responsivo.</li> + <li><strong>Bueno para SEO</strong> — Los motores de búsqueda dan más importancia a palabras claves dentro de cabeceras, links, etc., que palabras claves en elementos no semánticos como los <code><div></code>, etc., tus documentos serán más fáciles de encontrar por tus clientes.</li> +</ol> + +<p>Continuemos y veamos el HTML accesible en más detalle.</p> + +<div class="note"> +<p><strong>Nota</strong>: Es buena idea tener configurado un lector de pantalla en tu computador, para que puedas hacer algunas pruebas de los siguientes ejemplos. Mira nuestra <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Screenreaders">Guía de lectores de pantalla </a>para más detalles.</p> +</div> + +<h2 id="Buena_semántica">Buena semántica</h2> + +<p>Ya hemos hablado de la importancia de la buena semántica, y por qué deberíamos usar el elemento HTML adecuado para cada caso. Esto no puede ignorarse, ya que es uno de los principales lugares donde la accesibilidad se rompe si no se maneja correctamente.</p> + +<p>En la web, la verdad es que las personas hacen cosas muy extrañas con marcado HTML. Algunos abusos de HTML se deben a prácticas de antaño que no han sido completamente olvidadas y algunas son simplemente ignorancia. Cualquiera que sea el caso, deberías reemplazar ese mal código donde sea que lo veas.</p> + +<p>A veces, no estás en disposición de deshacerte del mal marcado — tus páginas pueden estar generadas por algún tipo de <em lang="en">framework</em> del lado del servidor del cual no tienes control total, o puedes tener contenido de terceros en tu página (como banners) sobre los que no tienes control.</p> + +<p>El objetivo no es "todo o nada", pero cada mejora que hagas va a ayudar a la causa de la accesibilidad.</p> + +<h3 id="Contenido_textual">Contenido textual</h3> + +<p>Una de las mejores ayudas de accesibilidad que un usuario lector de pantalla puede tener es una buena estructura de contenido de cabeceras, párrafos, listas, etc. Un ejemplo de buena semántica puede lucir como el de a continuación:</p> + +<pre class="brush: html example-good line-numbers language-html notranslate"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>h1</span><span class="punctuation token">></span></span>Mi cabecera<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>h1</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">>Esta es la primera sección de mi documento</span></span>.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">>Voy a agregar también otro párrafo aquí</span></span>.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">> + +<ol> + <li>Aquí esta</li> + <li>una lista para</li> + <li>que la leas</li> +</ol></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>h2</span><span class="punctuation token">></span></span>Mi subtítulo<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>h2</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span>Esta es la primera subsección de mi documento. ¡Me encantaría que la gente pudiera leer este contenido!<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>h2</span><span class="punctuation token">></span></span>Mi 2º <span class="tag token"><span class="tag token"><span class="punctuation token">subtitulo</</span>h2</span><span class="punctuation token">></span></span> + +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>p</span><span class="punctuation token">></span></span>Esta es la segunda subsección de mi documento. Creo que es más interesante que la primera.<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>p</span><span class="punctuation token">></span></span></code></pre> + +<p>Hemos preparado una versión más larga para que pruebes con un lector de pantalla (ver <a href="http://mdn.github.io/learning-area/accessibility/html/good-semantics.html">good-semantics.html</a>). Si tratas de navegar por ella, notaras que es muy fácil:</p> + +<ol> + <li>El lector de pantalla lee cada cabecera a medida que progresas a través del contenido, notificándote qué es una cabecera, qué es un párrafo, etc.</li> + <li>Se detiene después de cada elemento, dejándote ir a un ritmo que sea cómodo para ti.</li> + <li>Puedes saltar al siguiente/anterior encabezado en muchos lectores de pantalla.</li> + <li>También puedes tener una lista de todos los encabezados en muchos lectores de pantalla, permitiéndote usarlos como una tabla de contenidos para encontrar contenido específico.</li> +</ol> + +<p>Las personas a veces escriben encabezados, párrafos, etc. usando HTML presentacional y saltos de línea, algo como lo siguiente:</p> + +<pre class="brush: html example-bad line-numbers language-html notranslate"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>font</span> <span class="attr-name token">size</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>7<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Mi cabecera<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>font</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +Esta es la primera sección del documento. +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +Voy a agregar otro párrafo aquí también. +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">> +1. Aquí esta +</span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">> +2. una lista para +</span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">> +3. que la leas +</span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>font</span> <span class="attr-name token">size</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>5<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Mi subtitulo<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>font</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +Esta es la primera subsección de mi documento. ¡Me encantaría que la gente pudiera leer este contenido! +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>font</span> <span class="attr-name token">size</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>5<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>Mi 2º subtitulo<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>font</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>br</span><span class="punctuation token">></span></span> +Esta es la segunda subsección de mi documento. Creo que es más interesante que la primera.</code></pre> + +<p>Si pruebas nuestra versión extendida con un lector de pantalla (ver <a href="http://mdn.github.io/learning-area/accessibility/html/bad-semantics.html">bad-semantics.html</a>), no vas a tener una buena experiencia: el lector de pantalla no tiene nada que usar como señal, por lo que no podrás tener una tabla de contenidos útil y toda la página se ve como un solo bloque gigante, así que solo se lee de una vez, todo de una vez.</p> + +<p>Hay otros problemas más allá de la accesibilidad: es más difícil aplicar estilo al contenido con CSS o manipularlo con JavaScript, por ejemplo, porque no hay elementos para usarlos como selectores.</p> + +<h4 id="Usar_lenguaje_claro">Usar lenguaje claro</h4> + +<p>El lenguaje que usas también puede afectar la accesibilidad. En general deberías usar lenguaje claro que no sea demasiado complejo y no usar innecesariamente jerga o palabras extrañas. Esto no solo beneficia a las personas con discapacidades cognitivas u otras: beneficia a los lectores para quienes el texto no está escrito en su lengua materna, personas más jóvenes... ¡todo el mundo, de hecho! Aparte de esto, deberías evitar usar lenguaje y caracteres que no se puede leen claramente por un lector de pantalla. Por ejemplo:</p> + +<ul> + <li>No uses guiones si puedes evitarlos.en lugar de escribir 5–7, escribe "5 a 7".</li> + <li>Expande las abreviaciones — en lugar de escribir Ene, escribe Enero.</li> + <li>Expande los acrónimos, por lo menos una o dos veces. En lugar de escribir HTML en la primera instancia, escribe Hypertext Markup Language.</li> +</ul> + +<h3 id="Disposiciones_de_página">Disposiciones de página</h3> + +<p>Antiguamente la gente solía crear diseños de página usando tablas HTML, usando diferentes celdas de tabla para contener el encabezado, pie de página, barra lateral, columna de contenido principal, etc. Esto no es una buena idea porque un lector de pantalla probablemente dará como resultado lecturas confusas, especialmente si el diseño es complejo y tiene muchas tablas anidadas.</p> + +<p>Prueba nuestro ejemplo <a href="http://mdn.github.io/learning-area/accessibility/html/table-layout.html">table-layout.html</a>, que tiene este código:</p> + +<pre class="brush: html notranslate"><table width="1200"> + <!-- main heading row --> + <tr id="heading"> + <td colspan="6"> + + <h1 align="center">Header</h1> + + </td> + </tr> + <!-- nav menu row --> + <tr id="nav" bgcolor="#ffffff"> + <td width="200"> + <a href="#" align="center">Home</a> + </td> + <td width="200"> + <a href="#" align="center">Our team</a> + </td> + <td width="200"> + <a href="#" align="center">Projects</a> + </td> + <td width="200"> + <a href="#" align="center">Contact</a> + </td> + <td width="300"> + <form width="300"> + <input type="search" name="q" placeholder="Search query" width="300"> + </form> + </td> + <td width="100"> + <button width="100">Go!</button> + </td> + </tr> + <!-- spacer row --> + <tr id="spacer" height="10"> + <td> + + </td> + </tr> + <!-- main content and aside row --> + <tr id="main"> + <td id="content" colspan="4" bgcolor="#ffffff"> + + <!-- main content goes here --> + </td> + <td id="aside" colspan="2" bgcolor="#ff80ff" valign="top"> + <h2>Related</h2> + + <!-- aside content goes here --> + + </td> + </tr> + <!-- spacer row --> + <tr id="spacer" height="10"> + <td> + + </td> + </tr> + <!-- footer row --> + <tr id="footer" bgcolor="#ffffff"> + <td colspan="6"> + <p>©Copyright 2050 by nobody. All rights reversed.</p> + </td> + </tr> + </table></pre> + +<p>Si intentas navegar por él con un lector de pantalla, probablemente te dirá que hay una tabla para mirar (aunque algunos lectores de pantalla pueden adivinar la diferencia entre diseños con tablas y tablas de datos). Luego, probablemente (dependiendo del lector de pantalla que estés usando) tendrás que entrar en la tabla como objeto y mirar sus características por separado, y luego salir de la tabla nuevamente para continuar navegando por el contenido.</p> + +<p>Los diseños con tablas son una reliquia del pasado: tenían sentido cuando la compatibilidad con CSS no estaba muy extendida en los navegadores, pero ahora solo crean confusión para los usuarios de lectores de pantalla. Además, su código fuente requiere más marcado, lo que los hace menos flexibles y más difíciles de mantener. Puedes verificar estas afirmaciones comparando tu experiencia anterior con un ejemplo de <a href="http://mdn.github.io/learning-area/html/introduction-to-html/document_and_website_structure/">estructura de sitio web más moderno</a>, que podría verse así:</p> + +<pre class="brush: html notranslate"><header> + <h1>Header</h1> +</header> + +<nav> + <!-- main navigation in here --> +</nav> + +<!-- Here is our page's main content --> +<main> + + <!-- It contains an article --> + <article> + <h2>Article heading</h2> + + <!-- article content in here --> + </article> + + <aside> + <h2>Related</h2> + + <!-- aside content in here --> + </aside> + +</main> + +<!-- And here is our main footer that is used across all the pages of our website --> + +<footer> + <!-- footer content in here --> +</footer></pre> + +<p>Si pruebas nuestro ejemplo de estructura más moderna con un lector de pantalla, verás que el marcado de diseño ya no se interpone ni confunde la lectura del contenido. También es mucho más ágil y más pequeño en términos de tamaño de código, lo que significa que el código es más fácil de mantener y menos ancho de banda para que el usuario lo descargue (especialmente para aquellos con conexiones lentas).</p> + +<p>Otra consideración al crear diseños es usar elementos semánticos HTML5 como se ve en el ejemplo anterior (ver <a href="/es/docs/Web/HTML/Elemento#Seccionamiento_del_contenido">secciónado de contenido</a>): puedes crear un diseño usando solo elementos {{htmlelement ("div")}} anidados, pero es mejor usar los elementos de seccionado adecuados para marcar la navegación principal ({{htmlelement ("nav")}}), el pie de página ({{htmlelement ("footer")}}), los bloques de contenido ({{htmlelement ("article")}}), etc. Estos proporcionan semántica adicional para lectores de pantalla (y otras herramientas) para brindar al usuario pistas adicionales sobre el contenido por el que están navegando (consulta <a href="http://www.weba11y.com/blog/2016/04/22/screen-reader-support-for-new-html5-section-elements/">Screen Reader Support for new HTML5 Section Elements</a> para hacerte una idea de cómo es el soporte de lectores de pantalla).</p> + +<div class="note"> +<p><strong>Nota</strong>: Además de tener una buena semántica y un diseño atractivo, tu contenido debería tener sentido lógico en su orden en el código; siempre puedes colocarlo donde desees usando CSS más adelante, pero deberías tener el orden en el código correcto para empezar, para que lo que se lee a los usuarios de lectores de pantalla tenga sentido.</p> +</div> + +<h3 id="Controles_de_interfaz_de_usuario">Controles de interfaz de usuario</h3> + +<p>Por controles de interfaz de usuario nos referimos a las partes principales de los documentos web con las que los usuarios interactúan, habitualmente botones, enlaces y controles de formulario. En esta sección, veremos los aspectos básicos de accesibilidad a tener en cuenta al crear dichos controles. Los artículos posteriores sobre WAI-ARIA y multimedia analizarán otros aspectos de la accesibilidad de la interfaz de usuario.</p> + +<p>Un aspecto clave de la accesibilidad de los controles de interfaz de usuario es que, de forma predeterminada, los navegadores permiten que sean manipulados por el teclado. Puedes probar esto usando nuestro ejemplo <a href="https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html">native-keyboard-accessibility.html</a> (<a href="https://github.com/mdn/learning-area/blob/master/tools-testing/cross-browser-testing/accessibility/native-keyboard-accessibility.html">código fuente</a>). Ábrelo en una nueva pestaña y prueba a pulsar la tecla de tabulación; después de algunas pulsaciones, deberías ver que el foco de la pestaña comienza a moverse a través de los diferentes elementos enfocables. Los elementos enfocados reciben un estilo predeterminado resaltado en cada navegador (difiere ligeramente entre diferentes navegadores) para que puedas saber qué elemento está enfocado.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14215/button-focused-unfocused.png" style="border-style: solid; border-width: 1px; display: block; height: 39px; margin: 0px auto; width: 288px;"></p> + +<p>Después puedes pulsar <kbd>Enter</kbd> / <kbd>Return</kbd> para seguir un enlace enfocado o pulsar un botón (hemos incluido algo de JavaScript para que los botones lancen un mensaje), o comenzar a escribir para introducir texto en un campo de texto. Otros elementos de formulario tienen diferentes controles; por ejemplo, el elemento {{htmlelement ("select")}} puede mostrar sus opciones y alternar entre usar las teclas de flecha arriba y abajo.</p> + +<div class="note"> +<p><strong>Note</strong>: Diferentes navegadores pueden tener diferentes opciones de control de teclado disponibles. Consulta <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Using_native_keyboard_accessibility">Using native keyboard accessibility</a> para obtener más detalles.</p> +</div> + +<p>Básicamente, obtienes este comportamiento gratis, solo con el uso de los elementos apropiados. Por ejemplo:</p> + +<pre class="brush: html example-good notranslate"><h1>Enlaces</h1> + +<p>Esto es un enlace a <a href="https://www.mozilla.org">Mozilla</a>.</p> + +<p>Otro enlace, a la <a href="https://developer.mozilla.org">Mozilla Developer Network</a>.</p> + +<h2>Botones</h2> + +<p> + <button data-message="Esto es del primer botón">¡Haz clic!</button> + <button data-message="Esto es del segundo botón">¡Haz clic aquí también!</button> + <button data-message="Esto es del tercer botón">Y aquí!</button> +</p> + +<h2>Formulario</h2> + +<form> + <div> + <label for="nombre">Entra tu nombre:</label> + <input type="text" id="nombre" name="nombre"> + </div> + <div> + <label for="edad">Entra tu edad:</label> + <input type="text" id="edad" name="edad"> + </div> + <div> + <label for="humor">Elige tu humor:</label> + <select id="humor" name="humor"> + <option>Feliz</option> + <option>Triste</option> + <option>Enfadado/a</option> + <option>Preocupado/a</option> + </select> + </div> +</form></pre> + +<p>Esto significa usar enlaces, botones, elementos y etiquetas de formulario de manera adecuada (incluido el elemento {{htmlelement ("label")}} para los controles de formulario).</p> + +<p>Sin embargo, nuevamente se da el caso de que la gente a veces hace cosas extrañas con HTML. Por ejemplo, a veces ves botones marcados con {{htmlelement ("div")}}s, por ejemplo:</p> + +<pre class="brush: html example-bad notranslate"><div data-message="Esto es del primer botón">¡Haz clic aquí!</div> +<div data-message="Esto es del segundo botón">¡Haz clic aquñi también!</div> +<div data-message="Esto es del tercer botón">¡Y aquí!</div></pre> + +<p>Pero no se recomienda el uso de código como este: pierdes inmediatamente la accesibilidad nativa del teclado que habrías tenido si hubieras usado elementos {{htmlelement ("button")}}, y además no obtienes ninguno de los estilos CSS predeterminados que tienen los botones.</p> + +<h4 id="Volver_a_añadir_la_accesibilidad_del_teclado">Volver a añadir la accesibilidad del teclado</h4> + +<p>Volver a agregar estas ventajas requiere un poco de trabajo (puedes ver un ejemplo en nuestro ejemplo <a class="external external-icon" href="https://mdn.github.io/learning-area/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html">fake-div-buttons.html</a>; consulta también el <a href="https://github.com/mdn/learning-area/blob/master/tools-testing/cross-browser-testing/accessibility/fake-div-buttons.html">código fuente</a>). Aquí le hemos dado a nuestros botones <code><div></code> falsos la capacidad de enfocarse (incluso a través de la tecla de tabulación) dándole a cada uno el atributo <code>tabindex="0"</code>:</p> + +<pre class="brush: html notranslate"><div data-message="Esto es del primer botón" tabindex="0">¡Haz clic aquí!</div> +<div data-message="Esto es del segundo botón" tabindex="0">¡Haz clic aquí también!</div> +<div data-message="Esto es del tercer botón" tabindex="0">¡Y aquí!</div></pre> + +<p>Básicamente, el atributo {{htmlattrxref("tabindex")}} está destinado principalmente a permitir que los elementos tabulables tengan un orden de tabulación personalizado (especificado en orden numérico positivo), en lugar de simplemente tabularlos en su orden de origen predeterminado. Casi siempre es una mala idea, ya que puede causar una gran confusión. Úsalo solo si realmente lo necesitas; por ejemplo, si el diseño muestra las cosas en un orden visual muy diferente al código fuente, y deseas que las cosas funcionen de manera más lógica. Hay otras dos opciones para <code>tabindex</code>:</p> + +<ul> + <li><code>tabindex = "0"</code>: como se indicó anteriormente, este valor permite que los elementos que normalmente no se pueden tabular se conviertan en tabulables. Este es el valor más útil de <code>tabindex</code>.</li> + <li><code>tabindex = "- 1"</code>: esto permite que los elementos que normalmente no se pueden tabular reciban el foco mediante programación, p. ej. a través de JavaScript o como destino de enlaces.</li> +</ul> + +<p>Si bien la adición anterior nos permite tabular los botones, no nos permite activarlos a través de la tecla <kbd>Enter</kbd> / <kbd>Return</kbd>. Para hacer eso, hemos tenido que agregar el siguiente truco en JavaScript:</p> + +<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">document<span class="punctuation token">.</span>onkeydown <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span>e<span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="keyword token">if</span><span class="punctuation token">(</span>e<span class="punctuation token">.</span>keyCode <span class="operator token">===</span> <span class="number token">13</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> <span class="comment token">// La tecla Enter/Return</span> + document<span class="punctuation token">.</span>activeElement<span class="punctuation token">.</span><span class="function token">click</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> +<span class="punctuation token">}</span><span class="punctuation token">;</span></code></pre> + +<p>Aquí agregamos un "listener" (oyente) al objeto <code>document</code> para detectar cuándo se ha presionado una tecla en el teclado. Comprobamos qué botón se presionó mediante la propiedad <a href="/en-US/docs/Web/API/KeyboardEvent/keyCode">keyCode</a> del objeto de evento; si es el código clave que coincide con <kbd>Return</kbd> / <kbd>Enter</kbd>, ejecutamos la función almacenada en el manejador <code>onclick</code> del botón usando <code>document.activeElement.click()</code>. <a href="/en-US/docs/Web/API/Document/activeElement">activeElement</a> nos da el elemento que está actualmente enfocado en la página.</p> + +<p>Esta es mucho trabajo extra para volver a incorporar la funcionalidad. Y seguramente surgirán problemas con ella. Es mejor usar el elemento correcto para el trabajo correcto en primer lugar.</p> + +<h4 id="Etiquetas_de_texto_significativas">Etiquetas de texto significativas</h4> + +<p>Las etiquetas textuales de los controles de la interfaz de usuario son muy útiles para todos los usuarios, pero hacerlas bien es particularmente importante para los usuarios con discapacidades.</p> + +<p>Deberías asegurarte de que las etiquetas de texto de tus botones y enlaces sean comprensibles y distintivas. No uses simplemente "Haz clic aquí" para tus etiquetas, ya que los usuarios de lectores de pantalla a veces obtienen una lista de botones y controles de formulario. La siguiente captura de pantalla muestra nuestros controles enumerados por VoiceOver en Mac.</p> + +<p><img alt="Form controls. Click me! button. Click me too! button. And me! button. Fill me in: edit text. Fill me in: edit text. Happy collapsed pop up button. Happy menu item. Sad menu item. Angry menu item. Worried menu item." src="https://mdn.mozillademos.org/files/14335/voiceover-formcontrols.png" style="display: block; height: 604px; margin: 0px auto; width: 802px;"></p> + +<p>Asegúrate de que tus etiquetas tienen sentido sin su contexto, leídas solas, así como en el contexto del párrafo en que están. Por ejemplo, lo siguiente muestra un buen ejemplo de enlace de texto:</p> + +<pre class="brush: html example-good notranslate"><p>Las ballenas son criaturas realmente impresionantes. <a href="whales.html">Aprende más sobre las ballenas</a>.</p></pre> + +<p>y esto es un mal texto de enlace:</p> + +<pre class="brush: html example-bad notranslate"><p>Las ballenas son criaturas realmente impresionantes. Para aprender más sobre las ballenas, <a href="whales.html">haz clic aquí</a>.</p></pre> + +<div class="note"> +<p><strong>Note</strong>: Encontrarás mucho más sobre la implementación de enlaces y buenas prácticas en nuestro artículo <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/Creating_hyperlinks">Crear hipervínculos</a>. También encontrarás buenos y malos ejemplos en <a href="http://mdn.github.io/learning-area/accessibility/html/good-links.html">good-links.html</a> y <a href="http://mdn.github.io/learning-area/accessibility/html/bad-links.html">bad-links.html</a>.</p> +</div> + +<p>Las etiquetas de formulario también son importantes, para darte una pista sobre lo que necesita introducir en cada campo de formulario. El siguiente parece un ejemplo bastante razonable:</p> + +<pre class="brush: html example-bad notranslate">Entra tu nombre: <input type="text" id="nombre" name="nombre"></pre> + +<p>Sin embargo, esto no es tan útil para usuarios con discapacidad. No hay nada en el ejemplo anterior para asociar la etiqueta de forma inequívoca con la entrada del formulario y dejar claro cómo rellenarlo si no puede verlo. Si accedes con algunos lectores de pantalla, es posible que solo se te proporcione una descripción en la línea de "editar texto".</p> + +<p>El siguiente es un ejemplo mucho mejor:</p> + +<pre class="brush: html example-good notranslate"><div> + <label for="combre">Entra tu nombre:</label> + <input type="text" id="combre" name="nombre"> +</div></pre> + +<p>Con código como este, la etiqueta estará claramente asociada con la entrada; la descripción se parecerá más a "Entra tu nombre: editar texto".</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14337/voiceover-good-form-label.png" style="display: block; margin: 0 auto;"></p> + +<p>Como ventaja adicional, en la mayoría de los navegadores asociar una etiqueta con una entrada de formulario significa que puedes hacer clic en la etiqueta para seleccionar / activar el elemento del formulario. Esto le da a la entrada un área de impacto más grande, lo que facilita la selección.</p> + +<div class="note"> +<p><strong>Nota</strong>: puedes ver algunos ejemplos de buenos y malos formularios en <a href="http://mdn.github.io/learning-area/accessibility/html/good-form.html">good-form.html</a> y <a href="http://mdn.github.io/learning-area/accessibility/html/bad-form.html">bad-form.html</a>.</p> +</div> + +<h2 id="Tablas_de_datos_accesibles">Tablas de datos accesibles</h2> + +<p>Se puede escribir una tabla de datos básica con un marcado muy simple, por ejemplo:</p> + +<pre class="brush: html notranslate"><table> + <tr> + <td>Nombre</td> + <td>Edad</td> + <td>Género</td> + </tr> + <tr> + <td>Gabriel</td> + <td>13</td> + <td>Masculino</td> + </tr> + <tr> + <td>Elva</td> + <td>8</td> + <td>Femenino</td> + </tr> + <tr> + <td>Freida</td> + <td>5</td> + <td>Femenino</td> + </tr> +</table></pre> + +<p>Pero esto tiene problemas: no hay forma de que un usuario de lector de pantalla asocie filas o columnas como agrupaciones de datos. Para hacer esto, necesita saber cuáles son las filas de encabezado, y si están encabezando filas, columnas, etc. Esto solo se puede hacer visualmente para la tabla anterior (ve a <a href="https://mdn.github.io/learning-area/accessibility/html/bad-table.html">bad-table.html</a> y prueba tú mismo el ejemplo).</p> + +<p>Ahora echa un vistazo a nuestro <a href="https://github.com/mdn/learning-area/blob/master/css/styling-boxes/styling-tables/punk-bands-complete.html">ejemplo de tabla de bandas punk</a>: aquí puedes ver algunas ayudas de accesibilidad en funcionamiento:</p> + +<ul> + <li>Los encabezados de las tablas se definen utilizando elementos {{htmlelement("th")}}; también se puede especificar si son encabezados de filas o columnas mediante el atributo <code>scope</code>. Esto te da grupos completos de datos que los lectores de pantalla pueden consumir como unidades individuales.</li> + <li>El elemento {{htmlelement ("caption")}} y el atributo <code>summary</code> de <code><table></code> realizan trabajos similares: actúan como texto alternativo para una tabla, lo que brinda al usuario de lector de pantalla un resumen rápido y útil del contenido de la tabla. Por lo general, se prefiere <code><caption></code>, ya que también hace que su contenido sea accesible para los usuarios videntes, quienes también pueden encontrarlo útil. Realmente no necesitas usar ambos.</li> +</ul> + +<p>Consulte nuestro artículo sobre funciones avanzadas y accesibilidad de tablas HTML para obtener más detalles sobre las tablas de datos accesibles.</p> + +<div class="note"> +<p><strong>Note</strong>: Consulta nuestro artículo <a href="/es/docs/Learn/HTML/Tablas/Funciones_avanzadas_de_las_tablas_HTML_y_accesibilidad">Funciones avanzadas de tablas y accesibilidad</a> para ver más detalles sobre tablas de datos accesibles.</p> +</div> + +<h2 id="Alternativas_de_texto">Alternativas de texto</h2> + +<p>Mientras que el contenido textual es inherentemente accesible, lo mismo no se puede decir del contenido multimedia — el contenido de imagen/video no puede ser visto por personas con discapacidad visual, y el contenido de audio no puede ser escuchado por personas sordas. Cubriremos el contenido de video y audio en detalle en el artículo <a href="/en-US/docs/Learn/Accessibility/Multimedia">multimedia accesible</a> más adelante, pero para este artículo veremos la accesibilidad del humilde elemento {{htmlelement("img")}}.</p> + +<p>Tenemos un ejemplo simple, <a href="http://mdn.github.io/learning-area/accessibility/html/accessible-image.html">access-image.html</a>, que presenta cuatro copias de la misma imagen:</p> + +<pre class="notranslate"><img src="dinosaur.png"> + +<img src="dinosaur.png" + alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth."> + +<img src="dinosaur.png" + alt="A red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth." + title="The Mozilla red dinosaur"> + + +<img src="dinosaur.png" aria-labelledby="dino-label"> + +<p id="dino-label">The Mozilla red Tyrannosaurus Rex: A two legged dinosaur standing upright like a human, with small arms, and a large head with lots of sharp teeth.</p> +</pre> + +<p>La primera imagen, cuando la ve un lector de pantalla, realmente no ofrece mucha ayuda al usuario; VoiceOver, por ejemplo, lee "/dinosaur.png, imagen". Lee el nombre del archivo para intentar proporcionar ayuda. En este ejemplo, el usuario al menos sabrá que es un dinosaurio de algún tipo, pero a menudo los archivos pueden cargarse con nombres de archivo generados por la máquina (por ejemplo, de una cámara digital) y estos nombres de archivo probablemente no proporcionarían contexto al contenido de la imagen.</p> + +<div class="note"> +<p><strong>Nota</strong>: Es por eso que nunca debes incluir contenido de texto dentro de una imagen: los lectores de pantalla simplemente no pueden acceder a él. También hay otras desventajas: no puedes seleccionarlo y copiarlo / pegarlo. ¡No lo hagas!</p> +</div> + +<p>Cuando un lector de pantalla encuentra la segunda imagen, lee el atributo alt completo: "Un tiranosaurio rex rojo: un dinosaurio de dos patas erguido como un humano, con brazos pequeños y una cabeza grande con muchos dientes afilados".</p> + +<p>Esto resalta la importancia de no solo usar nombres de archivo significativos en caso de que el <strong>texto alternativo</strong> no esté disponible, sino también de asegurarse de que el texto alternativo se proporcione en los atributos <code>alt</code> siempre que sea posible. Ten en cuenta que el contenido del atributo <code>alt</code> siempre debe proporcionar una representación directa de la imagen y lo que transmite visualmente. Aquí no se debe incluir ningún conocimiento personal o descripción adicional, ya que no es útil para personas que no se han encontrado con la imagen antes.</p> + +<p>Una cosa a considerar es si tus imágenes tienen significado dentro del contenido, o si son puramente para decoración visual, por lo que no tienen significado. Si son decorativas, es mejor incluirlas en la página como imágenes de fondo CSS.</p> + +<div class="note"> +<p><strong>Note</strong>: Lee <a href="/es/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imágenes en HTML</a> y <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Responsive images</a> para obtener mucha más información sobre la implementación de imágenes y buenas prácticas asociadas.</p> +</div> + +<p>Si deseas proporcionar información contextual adicional, deberías colocarla en el texto que rodea la imagen o dentro de un atributo <code>title</code>, como se muestra a continuación. En este caso, la mayoría de los lectores de pantalla leerán el texto alternativo, el atributo del título y el nombre del archivo. Además, los navegadores muestran el texto del título como información cuando se pasa por encima con el ratón.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14333/title-attribute.png" style="display: block; margin: 0 auto;"></p> + +<p>Echemos otro vistazo al cuarto método:</p> + +<pre class="brush: html notranslate"><img src="dinosaur.png" aria-labelledby="dino-label"> + +<p id="dino-label">The Mozilla red Tyrannosaurus ... </p></pre> + +<p>En este caso, no estamos usando el atributo <code>alt</code> en absoluto; en cambio, hemos presentado nuestra descripción de la imagen como un párrafo de texto normal, le hemos dado un <code>id</code> y luego usamos el atributo <code>aria-labelledby</code> para referirnos a ese <code>id</code>, que hace que los lectores de pantalla usen ese párrafo como texto alternativo o etiqueta para esa imagen. Esto es especialmente útil si desea utilizar el mismo texto como etiqueta para varias imágenes, algo que no es posible con <code>alt</code>.</p> + +<div class="note"> +<p><strong>Note</strong>: <code>aria-labelledby</code> es parte de la especificación <a href="https://www.w3.org/TR/wai-aria-1.1/">WAI-ARIA</a>, que permite a los desarrolladores añadir semántica extra a su marcado para mejorar su accesibilidad para lectores de pantalla cuando sea necesario. Para aprender más sobre cómo funciona, lee nuestro artículo <a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA Basics</a>.</p> +</div> + +<h3 id="Otros_mecanismos_de_texto_alternativo">Otros mecanismos de texto alternativo</h3> + +<p>Las imágenes también tienen otros mecanismos disponibles para proporcionar texto descriptivo. Por ejemplo, hay un atributo <code>longdesc</code> que apunta a un documento web separado que contiene una descripción ampliada de la imagen, por ejemplo:</p> + +<pre class="brush: html notranslate"><img src="dinosaur.png" longdesc="dino-info.html"></pre> + +<p>Parece una buena idea, especialmente para infografías como gráficos grandes con mucha información que tal vez podría representarse como una tabla de datos accesible (consulte la sección anterior). Sin embargo, <code>longdesc</code> no es compatible de forma consistente con lectores de pantalla, y el contenido es completamente inaccesible para los usuarios que no usan lectores de pantalla. Podría decirse que es mucho mejor incluir la descripción larga en la misma página que la imagen, o vincularla con un enlace normal.</p> + +<p>HTML5 incluye dos elementos nuevos, {{htmlelement("figure")}} y {{htmlelement("figcaption")}}, que se supone que asocian una figura de algún tipo (podría ser cualquier cosa, no necesariamente una imagen) con un pie de figura:</p> + +<pre class="brush: html notranslate"><figure> + <img src="dinosaur.png" alt="El Tyrannosaurus de Mozilla"> + <figcaption>Un Tyrannosaurus Rex rojo: Un dinosaurio de dos piernas, de pie como un humano, con brazos pequeños y una cabeza grande con un montón de dientes afilados.</figcaption> +</figure></pre> + +<p>Desafortunadamente, la mayoría de lectores de pantalla aún no parecen asociar los títulos de las figuras con sus figuras, pero la estructura del elemento es útil para dar estilo con CSS, y además proporciona una manera de colocar una descripción de la imagen junto a ella en el código.</p> + +<h3 id="Atributos_alt_vacíos">Atributos alt vacíos</h3> + +<pre class="brush: html notranslate"><h3> + <img src="article-icon.png" alt=""> + Tyrannosaurus Rex: el rey de los dinosaurios +</h3></pre> + +<p>Puede haber ocasiones en las que se incluya una imagen en el diseño de una página, pero su propósito principal sea la decoración visual. Observarás en el ejemplo de código anterior que el atributo <code>alt</code> de la imagen está vacío; esto es para que los lectores de pantalla reconozcan la imagen, pero no intenten describirla imagen (en su lugar, solo dirían "imagen" o algo similar).</p> + +<p>La razón para usar un <code>alt</code> vacío en lugar de no incluirlo es porque muchos lectores de pantalla anuncian la URL completa de la imagen si no se proporciona un alt. En el ejemplo anterior, la imagen actúa como decoración visual del encabezado al que está asociada. En casos como este, y en los casos en los que una imagen es solo decoración y no tiene valor de contenido, debes poner un alt vacío en tus imágenes. Otra alternativa es usar el atributo de rol aria <code>role = "presentation"</code> - esto también evita que los lectores de pantalla lean el texto alternativo.</p> + +<div class="note"> +<p><strong>Note</strong>: si es posible, deberías usar CSS para mostrar imágenes que son solo decoración.</p> +</div> + +<h2 id="Más_sobre_enlaces">Más sobre enlaces</h2> + +<p>Los enlaces (el elemento <code><a></code> con un atributo <code>href</code>), según cómo se utilicen, pueden ayudar o perjudicar la accesibilidad. De forma predeterminada, los enlaces son accesibles en apariencia. Pueden mejorar la accesibilidad al ayudar a un usuario a navegar rápidamente a diferentes secciones de un documento. También pueden dañar la accesibilidad si se elimina su estilo accesible o si JavaScript hace que se comporten de manera inesperada.</p> + +<h3 id="Estilo_de_enlace">Estilo de enlace</h3> + +<p>De forma predeterminada, los enlaces son visualmente diferentes de otros textos tanto en el color como en la decoración del texto, con enlaces azules y subrayados de forma predeterminada, morados y subrayados si se visitan, y con un anillo de enfoque cuando reciben el foco del teclado.</p> + +<p>El color no debe usarse como el único método para distinguir los enlaces del contenido que no enlaza. El color del texto del enlace, como todo el texto, debe ser significativamente diferente del color de fondo (<a href="/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable/Color_contrast">un contraste de 4.5:1</a>). Además, los enlaces deben ser visualmente significativamente diferentes del texto sin enlaces. Con un requisito de contraste mínimo de 3:1 entre el texto del enlace y el texto circundante y entre los estados predeterminado, visitado y de enfoque / activo, y un contraste de 4:5 entre todos esos colores de estado y el color de fondo.</p> + +<h3 id="Eventos_onclick">Eventos onclick</h3> + +<p>A menudo se abusa de las etiquetas de anclaje con el evento <code>onclick</code> para crear pseudo-botones configurando href a <code>"#"</code> o<code> "javascript:void(0)"</code> para evitar que la página se actualice.</p> + +<p>Estos valores provocan un comportamiento inesperado al copiar o arrastrar enlaces, abrir enlaces en una nueva pestaña o ventana, marcar como favoritos y cuando JavaScript todavía se está descargando aparecen errores o está deshabilitado. Esto también transmite una semántica incorrecta a las tecnologías de asistencia (por ejemplo, lectores de pantalla). En estos casos, se recomienda utilizar un {{HTMLElement("button")}} en su lugar. En general, solo debe usar un ancla para la navegación utilizando una URL adecuada.</p> + +<h3 id="Enlaces_externos_y_enlaces_a_recursos_que_no_son_HTML">Enlaces externos y enlaces a recursos que no son HTML</h3> + +<p>Los enlaces que se abren en una nueva pestaña o ventana mediante la declaración <code>target="_blank"</code> y los enlaces cuyo valor <code>href</code> apunta a un recurso de archivo deben incluir un indicador sobre el comportamiento que se producirá cuando se active el enlace.</p> + +<p>Las personas con problemas de baja visión, que navegan con la ayuda de tecnología de lectura de pantalla o que tienen problemas cognitivos pueden confundirse cuando la nueva pestaña, ventana o aplicación se abre inesperadamente. Es posible que versiones antiguas del software de lectura de pantalla ni siquiera anuncien el comportamiento.</p> + +<h4 id="Enlace_que_abre_una_nueva_pestaña_o_ventana">Enlace que abre una nueva pestaña o ventana</h4> + +<pre class="brush: html notranslate"><a target="_blank" href="https://www.wikipedia.org/">Wikipedia (se abre en una nueva ventana)</a></pre> + +<h4 id="Enlace_a_un_recurso_que_no_es_HTML">Enlace a un recurso que no es HTML</h4> + +<pre class="brush: html notranslate"><a target="_blank" href="2017-annual-report.ppt">Informe anual de 2017 (PowerPoint)</a></pre> + +<p>Si se utiliza un icono en lugar de texto para indicar este tipo de comportamiento de enlaces, asegúrate de que incluya una {{HTMLAttrxRef("alt", "img", "descripción alternativa", "true")}}.</p> + +<ul> + <li><a href="https://webaim.org/techniques/hypertext/hypertext_links">WebAIM: Links and Hypertext - Hypertext Links</a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Understandable#Guideline_3.2_—_Predictable_Make_Web_pages_appear_and_operate_in_predictable_ways">MDN Understanding WCAG, Guideline 3.2 explanations</a></li> + <li><a href="https://www.w3.org/TR/WCAG20-TECHS/G200.html">G200: Opening new windows and tabs from a link only when necessary | W3C Techniques for WCAG 2.0</a></li> + <li><a href="https://www.w3.org/TR/WCAG20-TECHS/G201.html">G201: Giving users advanced warning when opening a new window | W3C Techniques for WCAG 2.0</a></li> +</ul> + +<h4 id="Enlaces_de_salto">Enlaces de salto</h4> + +<p>Un enlace de salto, también conocido como "skipnav", es un elemento que se coloca lo más cerca posible del elemento de apertura {{HTMLElement("body")}} que enlaza con el comienzo del contenido principal de la página. Este enlace permite a las personas evitar el contenido repetido en varias páginas de un sitio web, como el encabezado y la navegación principal.</p> + +<p>Los enlaces de salto son especialmente útiles para las personas que navegan con la ayuda de tecnología de asistencia, como controles de interruptores, comandos de voz o varitas bucales o para la cabeza, con las que el acto de moverse a través de enlaces repetitivos puede ser una tarea laboriosa.</p> + +<ul> + <li><a href="https://webaim.org/techniques/skipnav/">WebAIM: "Skip Navigation" Links</a></li> + <li><a href="https://www.a11yproject.com/posts/2013-05-11-skip-nav-links/">How–to: Use Skip Navigation links - The A11Y Project</a></li> + <li><a href="https://wiki.developer.mozilla.org/en-US/docs/Web/Accessibility/Understanding_WCAG/Operable#Guideline_2.4_%E2%80%94_Navigable_Provide_ways_to_help_users_navigate_find_content_and_determine_where_they_are">MDN Understanding WCAG, Guideline 2.4 explanations</a></li> + <li><a href="https://www.w3.org/TR/UNDERSTANDING-WCAG20/navigation-mechanisms-skip.html">Understanding Success Criterion 2.4.1 | W3C Understanding WCAG 2.0</a></li> +</ul> + +<h4 id="Proximidad">Proximidad</h4> + +<p>Si tenemos grandes cantidades de contenido interactivo, incluidas anclas, colocadas muy cerca visualmente entre sí, deben tener espacio insertado para separarlas. Este espaciado es beneficioso para las personas que sufren problemas de control de la motricidad fina y pueden activar accidentalmente el contenido interactivo incorrecto mientras navegan.</p> + +<p>El espaciado se puede crear usando propiedades CSS como {{CSSxRef("margin")}}.</p> + +<ul> + <li><a href="https://axesslab.com/hand-tremors/">Hand tremors and the giant-button-problem - Axess Lab</a></li> +</ul> + +<h2 id="¡Pon_a_prueba_tus_habilidades!">¡Pon a prueba tus habilidades!</h2> + +<p>Ha llegado al final de este artículo, pero ¿recuerdas la información más importante? Consulta <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Accessibility/Test_your_skills:_HTML_accessibility">Test your skills: HTML Accessibility</a> para verificar que has retenido esta información antes de continuar.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahora ya deberías conocer bien la escritura de HTML accesible para la mayoría de las ocasiones. Nuestro artículo de conceptos básicos de WAI-ARIA también llenará algunos vacíos en este conocimiento, pero este artículo se ha ocupado de los conceptos básicos. A continuación, exploraremos CSS y JavaScript, y cómo la accesibilidad se ve afectada por su buen o mal uso.</p> + +<p>{{PreviousMenuNext("Learn/Accessibility/What_is_Accessibility","Learn/Accessibility/CSS_and_JavaScript", "Learn/Accessibility")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">What is accessibility?</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/HTML">HTML: A good basis for accessibility</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">CSS and JavaScript accessibility best practices</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA basics</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Multimedia">Accessible multimedia</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Mobile">Mobile accessibility</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Accessibility troubleshooting</a></li> +</ul> diff --git a/files/es/learn/accessibility/index.html b/files/es/learn/accessibility/index.html new file mode 100644 index 0000000000..fc7cdeeb3c --- /dev/null +++ b/files/es/learn/accessibility/index.html @@ -0,0 +1,60 @@ +--- +title: Accesibilidad +slug: Learn/Accessibility +tags: + - ARIA + - Accesibilidad + - Aprender + - Artículos + - Aterrizaje + - CSS + - CodificaciónDeSecuenciasDeComandos + - HTML + - JavaScript + - Principiantes + - modulo +translation_of: Learn/Accessibility +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Aprender algo de HTML, CSS y JavaScript es útil si deseas convertirte en un desarrollador web, pero tu conocimiento debe ir más allá de simplemente usar esas tecnologías, debes usarlas de manera responsable para maximizar la audiencia de tus sitios web y evitar impedir su uso a nadie. Para lograr esto, debes adherirte a las mejores prácticas generales (que se muestran en los temas de <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML">HTML</a>, <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS">CSS</a> y <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript">JavaScript</a>), <a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing">pruebas cruzadas del navegador</a> y considerar la accesibilidad desde el principio. En este módulo, cubriremos este último en detalle.</p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Para aprovechar al máximo este módulo, sería una buena idea trabajar al menos en los dos primeros módulos de los temas de <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML">HTML</a>, <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS">CSS</a>, y <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript">JavaScript</a> o quizás mejor, trabajar en las partes relevantes del módulo de accesibilidad como tu trabajas a través de los temas relacionados con la tecnología.</p> + +<div class="note"> +<p>Nota: si está trabajando en una computadora / tableta / otro dispositivo donde no tiene la capacidad de crear sus propios archivos, puede probar la mayoría de los ejemplos de código en un programa de codificación en línea como <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">¿Qué es la accesibilidad?</a></dt> + <dd>Este artículo inicia el módulo con un buen vistazo a lo que realmente es la accesibilidad: esto incluye qué grupos de personas debemos considerar y por qué, qué herramientas utilizan las diferentes personas para interactuar con la web y cómo podemos hacer que la accesibilidad sea parte de nuestro flujo de trabajo de desarrollo web.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/HTML">HTML:Una buena base para la accesibilidad</a></dt> + <dd>Se puede hacer accesible una gran cantidad de contenido web simplemente asegurándose de que los elementos HTML concretos se utilizan para un propósito correcto en todo momento. Este artículo analiza en detalle cómo se puede usar HTML para garantizar la máxima accesibilidad.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">Mejores prácticas en accesibilidad en CSS y JavaScript </a></dt> + <dd>CSS y JavaScript, cuando se usan correctamente, también tienen el potencial de permitir experiencias web accesibles, pero si se usan mal pueden dañar significativamente la accesibilidad. Este artículo describe algunas de las mejores prácticas de CSS y JavaScript que deben considerarse para garantizar que incluso el contenido complejo sea lo más accesible posible.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA básico</a></dt> + <dd>Siguiendo con el artículo anterior, a veces puede ser difícil realizar controles complejos de IU que involucren HTML no semántico y contenido dinámico actualizado con JavaScript. WAI-ARIA es una tecnología que puede ayudar a resolver estos problemas agregando más semántica que los navegadores y las tecnologías de asistencia pueden reconocer y utilizar para que los usuarios sepan lo que está sucediendo. Aquí mostraremos cómo usarlo a un nivel básico para mejorar la accesibilidad.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/Multimedia">Multimedia accesible</a></dt> + <dd>Otra categoría de contenido que puede crear problemas de accesibilidad es multimedia: el contenido de video, audio e imagen debe contar con alternativas textuales adecuadas para que las tecnologías de asistencia y sus usuarios puedan entenderlos. Este artículo muestra cómo.</dd> + <dt><a href="/en-US/docs/Learn/Accessibility/Mobile">Accesibilidad móvil</a></dt> + <dd>Dado que el acceso a la web en dispositivos móviles es tan popular, y que las plataformas populares como iOS y Android tienen herramientas de accesibilidad completas, es importante considerar la accesibilidad de su contenido web en estas plataformas. Este artículo analiza las consideraciones de accesibilidad específicas para dispositivos móviles.</dd> +</dl> + +<h2 id="Valoraciones">Valoraciones</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Resolución de problemas de accesibilidad</a></dt> + <dd>En la evaluación de este módulo, te presentamos un sitio simple con una serie de problemas de accesibilidad que necesitas diagnosticar y corregir.</dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://egghead.io/courses/start-building-accessible-web-applications-today">Empieza hoy a desarrollar aplicaciones web accesibles</a>— Una excelente serie de videos tutoriales por Marcy Sutton.</li> + <li><a href="https://dequeuniversity.com/resources/">Recursos de la Universidad Deque </a>— incluye ejemplos de códigos, referencias de lectores de pantalla y otros recursos útiles.</li> + <li><a href="http://webaim.org/resources/">Recursos de WebAIM </a>— incluye guías, listas de verificación, herramientas, y más.</li> +</ul> diff --git a/files/es/learn/accessibility/mobile/index.html b/files/es/learn/accessibility/mobile/index.html new file mode 100644 index 0000000000..4762e5220c --- /dev/null +++ b/files/es/learn/accessibility/mobile/index.html @@ -0,0 +1,346 @@ +--- +title: Mobile accessibility +slug: Learn/Accessibility/Mobile +translation_of: Learn/Accessibility/Mobile +--- +<div> +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Accessibility/Multimedia","Learn/Accessibility/Accessibility_troubleshooting", "Learn/Accessibility")}}</div> + +<p class="summary">Dado que el acceso a la web en dispositivos móviles es tan popular, y las plataformas populares como iOS y Android tienen herramientas de accesibilidad completas, es importante considerar la accesibilidad de su contenido web en estas plataformas. Este artículo analiza las consideraciones de accesibilidad específicas para dispositivos móviles.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de computación, una comprensión básica de HTML, CSS y JavaScript, y una comprensión de los <a href="/en-US/docs/Learn/Accessibility">artículos previos del curso</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para comprender qué problemas existen con la accesibilidad en dispositivos móviles y cómo superarlos.</td> + </tr> + </tbody> +</table> + +<h2 id="Accessibility_on_mobile_devices">Accessibility on mobile devices</h2> + +<p> </p> + +<p>El estado de accesibilidad, y el soporte para los estándares web en general, es bueno en los dispositivos móviles modernos. Atrás quedaron los días en que los dispositivos móviles utilizaban tecnologías web completamente diferentes para los navegadores de escritorio, lo que obligaba a los desarrolladores a utilizar el rastreo de los navegadores y les servía sitios completamente separados (aunque muchas empresas aún detectan el uso de dispositivos móviles y les ofrecen un dominio móvil separado).</p> + +<p>En estos días, los dispositivos móviles en general pueden manejar sitios web "completos", y las plataformas principales incluso tienen lectores de pantalla incorporados para permitir que los usuarios con discapacidades visuales los utilicen con éxito. Los navegadores móviles modernos tienden a tener un buen soporte para <a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA</a>, también.</p> + +<p> </p> + +<p> </p> + +<p>Para hacer que un sitio web sea accesible y utilizable en dispositivos móviles, solo debe seguir las buenas prácticas generales de diseño web y accesibilidad.</p> + +<p>Hay algunas excepciones que requieren una consideración especial para el móvil; Los principales son:</p> + +<p> </p> + +<ul> + <li>Mecanismos de control: asegúrese de que los controles de la interfaz, como los botones, estén accesibles en los móviles (es decir, principalmente en la pantalla táctil), así como en las computadoras de escritorio / portátiles (principalmente en el mouse / teclado).</li> + <li>Entrada del usuario: haga que los requisitos de entrada del usuario sean lo más fáciles posible en el móvil (por ejemplo, en formularios, siga escribiendo al mínimo).</li> + <li>Diseño receptivo: asegúrese de que los diseños funcionen en dispositivos móviles, conserve los tamaños de descarga de imágenes y piense en la provisión de imágenes para pantallas de alta resolución.</li> +</ul> + +<h2 id="Resumen_de_las_pruebas_del_lector_de_pantalla_en_Android_e_iOS">Resumen de las pruebas del lector de pantalla en Android e iOS</h2> + +<p> </p> + +<p>Las plataformas móviles más comunes tienen lectores de pantalla completamente funcionales. Estos funcionan de la misma manera que los lectores de pantalla de escritorio, excepto que se operan en gran parte mediante gestos táctiles en lugar de combinaciones de teclas.</p> + +<p>Veamos los dos principales: TalkBack en Android y VoiceOver en iOS.</p> + +<p> </p> + +<h3 id="Android_TalkBack">Android TalkBack</h3> + +<p> </p> + +<p>El lector de pantalla TalkBack está integrado en el sistema operativo Android.</p> + +<p>Para activarlo, seleccione Configuración> Accesibilidad> TalkBack, y luego presione el interruptor deslizante para activarlo. Siga las indicaciones adicionales en pantalla que le presenten.</p> + +<p><strong>Nota</strong>: las versiones anteriores de TalkBack están activadas de formas <a href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">formas ligeramente distintas.</a></p> + +<p>Cuando TalkBack esté activado, los controles básicos de su dispositivo Android serán un poco diferentes. Por ejemplo:</p> + +<ol> + <li>Pulsar una aplicación solo lo seleccionará, y el dispositivo leerá qué es la aplicación.</li> + <li>Al deslizar hacia la izquierda y hacia la derecha, se moverá entre las aplicaciones o los botones / controles si se encuentra en una barra de control. El dispositivo leerá cada opción.</li> + <li>Si toca dos veces en cualquier lugar, se abrirá la aplicación / seleccione la opción.</li> + <li>También puede "explorar con un toque": mantenga el dedo presionado sobre la pantalla y arrástrelo, y su dispositivo leerá las diferentes aplicaciones / elementos con los que se mueve.</li> +</ol> + +<p>Si desea desactivar TalkBack:</p> + +<ol> + <li>Navega a tu aplicación de configuración utilizando los gestos anteriores.</li> + <li>Vaya a Accesibilidad> TalkBack.</li> + <li>Navegue hasta el interruptor deslizante y actívelo para apagarlo.</li> +</ol> + +<p>Nota: Puede acceder a la pantalla de inicio en cualquier momento deslizando hacia arriba y hacia la izquierda con un movimiento suave. Si tiene más de una pantalla de inicio, puede moverse entre ellos deslizando dos dedos hacia la izquierda y hacia la derecha.</p> + +<p>Para obtener una lista más completa de los gestos de TalkBack, consulte <a href="https://support.google.com/accessibility/android/answer/6151827">Usar gestos TalkBack. </a></p> + +<h4 id="Desbloqueo_del_telefono">Desbloqueo del telefono</h4> + +<p> </p> + +<p>Cuando TalkBack está activado, desbloquear el teléfono es un poco diferente.</p> + +<p>Puede hacer un deslizamiento con dos dedos hacia arriba desde la parte inferior de la pantalla de bloqueo. Si ha establecido un código de acceso o un patrón para desbloquear su dispositivo, se lo dirigirá a la pantalla de entrada correspondiente para ingresarlo.</p> + +<p>También puede explorar tocando para encontrar el botón Desbloquear en la parte inferior central de la pantalla y luego toque dos veces.</p> + +<p> </p> + +<h4 id="Menús_globales_y_locales">Menús globales y locales</h4> + +<p> </p> + +<p>TalkBack le permite acceder a los menús de contexto global y local, donde quiera que haya navegado en el dispositivo. El primero proporciona opciones globales relacionadas con el dispositivo en su conjunto, y el segundo proporciona opciones relacionadas con la aplicación / pantalla actual en la que se encuentra.</p> + +<p>Para llegar a estos menús:</p> + +<p> </p> + +<ol> + <li>Acceda al menú global deslizando rápidamente hacia abajo y luego a la</li> + <li>Acceda al menú local deslizando rápidamente hacia arriba y luego a la</li> + <li>Desliza el dedo hacia la izquierda y hacia la derecha para alternar entre las diferentes opciones.</li> + <li>Una vez que haya seleccionado la opción que desea, haga doble clic para elegir esa opción.</li> +</ol> + +<p>Para obtener detalles sobre todas las opciones disponibles en los menús de contexto global y local, consulte <a href="https://support.google.com/accessibility/android/answer/6007066">Uso global y local contextual de menús</a>.</p> + +<p> </p> + +<h4 id="Navegando_por_páginas_web">Navegando por páginas web</h4> + +<p> </p> + +<p>Puede usar el menú contextual local mientras está en un navegador web para encontrar opciones para navegar por páginas web usando solo los encabezados, controles de formulario o enlaces, o navegar línea por línea, etc.</p> + +<p>Por ejemplo, con TalkBack activado:</p> + +<ol> + <li> Abra su navegador web.</li> + <li> Activar la barra de URL.</li> + <li> Ingrese una página web que tenga muchos encabezados, como la página principal de bbc.co.uk. Para ingresar el texto de la URL: + <ul> + <li>Seleccione la barra de URL deslizando hacia la izquierda / derecha hasta que llegue a ella, y luego toque dos veces.</li> + <li>Mantenga presionado el teclado virtual hasta que obtenga el carácter que desea y luego suelte el dedo para escribirlo. Repita para cada personaje.</li> + <li>Una vez que hayas terminado, encuentra la tecla Intro y presiónala.</li> + </ul> + </li> + <li> Desliza el dedo hacia la izquierda y hacia la derecha para moverte entre los diferentes elementos de la página.</li> + <li> Deslice hacia arriba y hacia la derecha con un movimiento suave para ingresar al menú de contenido local.</li> + <li> Deslízate hacia la derecha hasta que encuentres la opción "Encabezados y puntos de referencia".</li> + <li> Pulse dos veces para seleccionarlo. Ahora podrá desplazarse hacia la izquierda y hacia la derecha para moverse entre encabezados y puntos de referencia de ARIA.</li> + <li> Para volver al modo predeterminado, ingrese nuevamente al menú de contexto local deslizando hacia arriba y a la derecha, seleccione "Predeterminado", y luego toque dos veces para activar.</li> +</ol> + +<p><strong>Nota</strong>: consulte <a href="https://support.google.com/accessibility/android/answer/6283677?hl=en&ref_topic=3529932">Empezar en Android con TalkBack</a> para obtener una documentación más completa.</p> + +<p> </p> + +<h3 id="iOS_VoiceOver">iOS VoiceOver</h3> + +<p> </p> + +<p>Una versión móvil de VoiceOver está integrada en el sistema operativo iOS.</p> + +<p>Para activarlo, vaya a la aplicación de configuración y seleccione General> Accesibilidad> VoiceOver. Presione el control deslizante VoiceOver para habilitarlo (también verá otras opciones relacionadas con VoiceOver en esta página).</p> + +<p>Una vez que VoiceOver esté habilitado, los gestos de control básico de iOS serán un poco diferentes:</p> + +<ol> + <li> Un solo toque hará que se seleccione el elemento que tocas; su dispositivo dirá el elemento que ha tocado.</li> + <li> También puede navegar por los elementos en la pantalla deslizando hacia la izquierda y hacia la derecha para moverse entre ellos, o deslizando el dedo por la pantalla para moverse entre diferentes elementos (cuando encuentra el elemento que desea, puede quitar el dedo para seleccionarlo). ).</li> + <li> Para activar el elemento seleccionado (por ejemplo, abrir una aplicación seleccionada), toque dos veces en cualquier lugar de la pantalla.</li> + <li> Desliza tres dedos para desplazarte por una página.</li> + <li> Toque con dos dedos para realizar una acción relevante para el contexto, por ejemplo, tomar una foto mientras está en la aplicación de la cámara.</li> +</ol> + +<p>Para apagarlo nuevamente, navegue de nuevo a Configuración> General> Accesibilidad> VoiceOver usando los gestos anteriores, y active el control deslizante VoiceOver para desactivarlo.</p> + +<p> </p> + +<h4 id="Desbloquear_el_teléfono">Desbloquear el teléfono</h4> + +<p>Para desbloquear el teléfono, debe presionar el botón de inicio (o deslizar) de manera normal. Si tiene un código de acceso configurado, puede seleccionar cada número deslizando / deslizando (como se explicó anteriormente) y luego toque dos veces para ingresar cada número cuando haya encontrado el correcto.</p> + +<h4 id="Usando_el_rotor">Usando el rotor</h4> + +<p> </p> + +<p>Cuando VoiceOver está activado, tiene una función de navegación llamada Rotor disponible para usted, que le permite elegir rápidamente entre una serie de opciones útiles comunes. Para usarlo:</p> + +<ol> + <li>Gira dos dedos alrededor de la pantalla como si estuvieras girando un dial. Cada opción se leerá en voz alta a medida que gire más. Puede ir hacia adelante y hacia atrás para recorrer las opciones.</li> + <li>Una vez que hayas encontrado la opción que + <ul> + <li>Suelte los dedos para seleccionarlo.</li> + <li>Si es una opción que puede repetir el valor de (como Volumen o Velocidad de voz), puede deslizar hacia arriba o hacia abajo para aumentar o disminuir el valor del elemento seleccionado.</li> + </ul> + </li> +</ol> + +<p>Las opciones disponibles en el Rotor son sensibles al contexto; serán diferentes según la aplicación o la vista en la que se encuentre (consulte a continuación un ejemplo).</p> + +<p> </p> + +<h4 id="Navegando_por_páginas_web_2">Navegando por páginas web</h4> + +<p>Vamos a hacer una prueba a navegar con VoiceOver:</p> + +<ol> + <li><span class="tlid-translation translation">Abra su navegador web.</span></li> + <li><span class="tlid-translation translation">Activar la barra de URL.</span></li> + <li><span class="tlid-translation translation">Ingrese una página web que tenga muchos encabezados, como la página principal de bbc.co.uk. Para ingresar el texto de la URL:</span> + <ul> + <li><span class="tlid-translation translation">Seleccione la barra de URL deslizando hacia la izquierda / derecha hasta que llegue a ella, y luego toque dos veces.</span></li> + <li><span class="tlid-translation translation">Para cada personaje, mantenga presionado el teclado virtual hasta que obtenga el carácter que desea y luego suelte el dedo para seleccionarlo. </span><span class="tlid-translation translation">Pulse dos veces para escribirlo.</span></li> + <li><span class="tlid-translation translation">Una vez que hayas terminado, encuentra la tecla Intro y presiónala.</span></li> + </ul> + </li> + <li><span class="tlid-translation translation">Desliza el dedo hacia la izquierda y hacia la derecha para moverte entre los elementos de la página. Puede tocar dos veces un elemento para seleccionarlo (por ejemplo, siga un enlace).</span></li> + <li><span class="tlid-translation translation">Por defecto, la opción de Rotor seleccionada será Speaking Rate; actualmente puede deslizar hacia arriba y hacia abajo para aumentar o disminuir la frecuencia de habla.</span></li> + <li><span class="tlid-translation translation">Ahora gire dos dedos alrededor de la pantalla como un cuadrante para mostrar el rotor y muévase entre sus opciones. Aquí hay algunos ejemplos de las opciones disponibles:</span> + <ul> + <li><span class="tlid-translation translation">Tasa de habla: Cambia la tasa de habla.</span></li> + <li><span class="tlid-translation translation">Contenedores: muévete entre los diferentes contenedores semánticos de la página.</span></li> + <li><span class="tlid-translation translation">Encabezados: muévete entre los encabezados de la página.</span></li> + <li><span class="tlid-translation translation">Enlaces: Mover entre enlaces en la página.</span></li> + <li><span class="tlid-translation translation">Controles de formulario: muévase entre los controles de formulario en la página.</span></li> + <li><span class="tlid-translation translation">Idioma: Mover entre diferentes traducciones, si están disponibles.</span></li> + </ul> + </li> + <li><span class="tlid-translation translation">Seleccionar encabezados. Ahora podrá desplazarse hacia arriba y hacia abajo para moverse entre los encabezados de la página.</span></li> +</ol> + +<p><span class="tlid-translation translation"><strong>Nota</strong>: Para obtener una referencia más completa que cubra los gestos de VoiceOver disponibles y otros consejos sobre las pruebas de accesibilidad en iOS, consulte </span><a href="https://developer.apple.com/library/content/technotes/TestingAccessibilityOfiOSApps/TestAccessibilityonYourDevicewithVoiceOver/TestAccessibilityonYourDevicewithVoiceOver.html#//apple_ref/doc/uid/TP40012619-CH3"> Probar la accesibilidad en su dispositivo con VoiceOver</a><span class="tlid-translation translation">.</span></p> + +<p> </p> + +<h2 id="Mecanismos_de_control">Mecanismos de control</h2> + +<p>En nuestro artículo de accesibilidad de CSS y JavaScript, examinamos la idea de eventos que son específicos de un determinado tipo de mecanismo de control (<a href="https://developer.mozilla.org/en-US/docs/Learn/Accessibility/CSS_and_JavaScript#mouse-specific_events">eventos ratón-específicos</a>). Para resumir, esto causa problemas de accesibilidad porque otros mecanismos de control no pueden activar la funcionalidad asociada.</p> + +<p>Como ejemplo, el evento de clic es bueno en términos de accesibilidad: se puede invocar un controlador de eventos asociado haciendo clic en el elemento en el que está configurado el controlador, haciendo tabulaciones en él y presionando Intro / Retorno, o tocándolo en un dispositivo de pantalla táctil. Pruebe nuestro ejemplo <a href="https://github.com/mdn/learning-area/blob/master/accessibility/mobile/simple-button-example.html">simple-button-example.html</a> (<a href="http://mdn.github.io/learning-area/accessibility/mobile/simple-button-example.html">véalo en vivo</a>) para ver lo que queremos decir.</p> + +<p>Alternativamente, los eventos específicos del mouse como <a href="https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onmousedown">mousedown</a> y <a href="https://developer.mozilla.org/en-US/docs/Web/API/GlobalEventHandlers/onmouseup">mouseup</a> crean problemas: sus controladores de eventos no pueden invocarse usando controles que no sean del mouse.</p> + +<p>Si intenta controlar nuestro ejemplo de <a href="https://github.com/mdn/learning-area/blob/master/accessibility/mobile/simple-box-drag.html">simple-box-drag.html</a> (<a href="http://mdn.github.io/learning-area/accessibility/mobile/simple-box-drag.html">ver ejemplo en vivo</a>) con el teclado o el toque, verá el problema. Esto ocurre porque estamos usando un código como el siguiente:</p> + +<pre><code>div.onmousedown = function() { + initialBoxX = div.offsetLeft; + initialBoxY = div.offsetTop; + movePanel(); +} + +document.onmouseup = stopMove;</code></pre> + +<p>Para habilitar otras formas de control, debe usar eventos diferentes pero equivalentes; por ejemplo, los eventos táctiles funcionan en dispositivos con pantalla táctil:</p> + +<pre><code>div.ontouchstart = function(e) { + initialBoxX = div.offsetLeft; + initialBoxY = div.offsetTop; + positionHandler(e); + movePanel(); +} + +panel.ontouchend = stopMove;</code></pre> + +<p>Hemos proporcionado un ejemplo sencillo que muestra cómo usar el mouse y los eventos táctiles juntos <a href="https://github.com/mdn/learning-area/blob/master/accessibility/mobile/multi-control-box-drag.html">multi-control-box-drag.html</a> (<a href="http://mdn.github.io/learning-area/accessibility/mobile/multi-control-box-drag.html">ver ejemplo en vivo</a>).</p> + +<p><strong>Nota:</strong> También puede ver ejemplos totalmente funcionales que muestran cómo implementar diferentes mecanismos de control en <a href="https://developer.mozilla.org/en-US/docs/Games/Techniques/Control_mechanisms">Implementando mecanismos de control de juego.</a></p> + +<h2 id="Diseño_de_respuesta">Diseño de respuesta</h2> + +<p><a href="https://developer.mozilla.org/en-US/docs/Web/Apps/Progressive/Responsive">El diseño de respuesta</a> es la práctica de hacer que sus diseños y otras características de sus aplicaciones cambien dinámicamente dependiendo de factores como el tamaño de la pantalla y la resolución, para que sean utilizables y accesibles para usuarios de diferentes tipos de dispositivos.</p> + +<p>En particular, los problemas más comunes que deben abordarse para dispositivos móviles son:</p> + +<p> </p> + +<ul> + <li>Adecuación de diseños para dispositivos móviles. Un diseño de varias columnas no funcionará tan bien en una pantalla estrecha, por ejemplo, y es posible que deba aumentar el tamaño del texto para que sea legible. Dichos problemas se pueden resolver creando un diseño sensible utilizando tecnologías tales como <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/Media_Queries">mconsultas de medios, </a><a href="https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag">vista</a> and <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox">flexbox</a>. .</li> + <li>Conservando tamaños de imagen descargados. En general, los dispositivos de pantalla pequeña no necesitarán imágenes tan grandes como sus contrapartes de escritorio, y es más probable que estén en conexiones de red lentas. Por lo tanto, es aconsejable servir imágenes más pequeñas para dispositivos de pantalla estrecha, según corresponda. Puede manejar esto <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images"> técnicas de imagenes de respuesta</a>.</li> + <li>Pensando en altas resoluciones. Muchos dispositivos móviles tienen pantallas de alta resolución y, por lo tanto, necesitan imágenes de mayor resolución para que la pantalla pueda seguir luciendo nítida y nítida. Nuevamente, puede servir imágenes según corresponda utilizando técnicas de imágenes sensibles. Además, muchos requisitos de imagen se pueden cumplir con el formato de imágenes vectoriales SVG, que es compatible con todos los navegadores actuales. SVG tiene un tamaño de archivo pequeño y se mantendrá nítido independientemente del tamaño que se muestre (consulte <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Agregar gráficos vectoriales a la web</a> para obtener más detalles).</li> +</ul> + +<p><strong>Nota</strong>: No proporcionaremos una discusión completa de las técnicas de diseño receptivo aquí, ya que están cubiertas en otros lugares alrededor de MDN (vea los enlaces anteriores).</p> + +<h3 id="Consideraciones_específicas_para_móviles">Consideraciones específicas para móviles</h3> + +<p>Hay otros aspectos importantes a tener en cuenta al hacer que los sitios sean más accesibles en dispositivos móviles. Hemos enumerado un par aquí, pero agregaremos más cuando pensemos en ellos.</p> + +<h4 id="No_deshabilitar_el_zoom">No deshabilitar el zoom</h4> + +<p>Usando viewport, es posible deshabilitar el zoom, usando un código como este en su {{htmlelement("head")}}:</p> + +<pre><code><meta name="viewport" content="user-scalable=no"></code></pre> + +<p>Nunca debe hacer esto si es posible: muchas personas confían en el zoom para poder ver el contenido de su sitio web, por lo que eliminar esta funcionalidad es una muy mala idea. Hay ciertas situaciones en las que el zoom podría romper la interfaz de usuario; en tales casos, si cree que necesita deshabilitar el zoom, debe proporcionar algún otro tipo de equivalente, como un control para aumentar el tamaño del texto de una manera que no rompa su interfaz de usuario.</p> + +<h4 id="Mantener_los_menús_accesibles.">Mantener los menús accesibles.</h4> + +<p> </p> + +<p>Debido a que la pantalla es mucho más estrecha en los dispositivos móviles, es muy común utilizar consultas de medios y otras tecnologías para hacer que el menú de navegación se reduzca a un pequeño icono en la parte superior de la pantalla, que se puede presionar para mostrar el menú solo si es necesario - cuando el sitio se ve en el móvil. Esto suele representarse mediante un icono de "tres líneas horizontales" y, por lo tanto, el patrón de diseño se conoce como "menú de hamburguesas".</p> + +<p>Al implementar un menú de este tipo, debe asegurarse de que el control para revelarlo sea accesible mediante los mecanismos de control apropiados (normalmente, toque para dispositivos móviles), como se explica en {{ anch("Control mechanisms" )}}, y que el resto La página se aleja o se oculta de alguna manera mientras se accede al menú, para evitar confusiones al navegar.</p> + +<p>Haga clic aquí para un buen<a href="http://fritz-weisshart.de/meg_men/"> ejemplo de menú de hamburguesa.</a></p> + +<h2 id="Entrada_de_usuario">Entrada de usuario</h2> + +<p> </p> + +<p>En los dispositivos móviles, el ingreso de datos tiende a ser más molesto para los usuarios que la experiencia equivalente en computadoras de escritorio. Es más conveniente escribir texto en las entradas de formulario utilizando un teclado de computadora de escritorio o portátil que un teclado virtual de pantalla táctil o un pequeño teclado físico móvil.</p> + +<p>Por esta razón, vale la pena intentar minimizar la cantidad de escritura necesaria. Como ejemplo, en lugar de hacer que los usuarios completen el título de su trabajo cada vez que usan una entrada de texto regular, podría ofrecer un menú {{htmlelement ("select")}} que contenga las opciones más comunes (que también ayuda a mantener la coherencia en entrada de datos), y ofrece una opción "Otro" que muestra un campo de texto para escribir cualquier valor atípico. Puedes ver un ejemplo simple de esta idea en acción en <a href="https://github.com/mdn/learning-area/blob/master/accessibility/mobile/common-job-types.html">common-job-types.html</a> (ver el <a href="http://mdn.github.io/learning-area/accessibility/mobile/common-job-types.html">common jobs ejemplo en vivo</a>).</p> + +<p>También vale la pena considerar el uso de los tipos de entrada de formulario HTML5, así como la fecha en las plataformas móviles, ya que ambos los manejan bien: tanto Android como iOS, por ejemplo, muestran widgets utilizables que se adaptan bien a la experiencia del dispositivo. Ver <a href="https://github.com/mdn/learning-area/blob/master/accessibility/mobile/html5-form-examples.html">html5-form-examples.html</a> para algunos ejemplos (ver el <a href="http://mdn.github.io/learning-area/accessibility/mobile/html5-form-examples.html">ejemplo de formulario en vivo en HTML5</a>) — intenta cargarlos y manipularlos en dispositivos móviles. Por ejemplo:</p> + +<ul> + <li>Los tipos de <code>number</code>, <code>tel</code>, <code>y email</code> muestran teclados virtuales adecuados para ingresar números / números de teléfono.</li> + <li>Los tipos de <code>time</code> and <code>date</code> muestran selectores adecuados para seleccionar horas y fechas.</li> +</ul> + +<p>If you want to provide a different solution for desktops, you could always serve different markup to your mobile devices using feature detection. See <a href="http://diveinto.html5doctor.com/detect.html#input-types">input types</a> for raw information on detecting different input types, and also check out our <a href="https://developer.mozilla.org/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection">feature detection article</a> for much more information.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En este artículo, le proporcionamos algunos detalles sobre problemas comunes comunes relacionados con la accesibilidad móvil y cómo superarlos. También lo llevamos a través del uso de los lectores de pantalla más comunes para ayudarlo en las pruebas de accesibilidad.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://www.smashingmagazine.com/guidelines-for-mobile-web-development/">Directrices para desarrollo web en móviles</a> — Una lista de artículos en Smashing Magazine que cubren diferentes técnicas para el diseño web móvil.</li> + <li><a href="http://www.creativebloq.com/javascript/make-your-site-work-touch-devices-51411644">Haz funcionar tu web en dispositivos táctiles</a> — Artículo útil sobre el uso de eventos táctiles para que las interacciones funcionen en dispositivos móviles.</li> +</ul> + +<div>{{PreviousMenuNext("Learn/Accessibility/Multimedia","Learn/Accessibility/Accessibility_troubleshooting", "Learn/Accessibility")}}</div> + +<div> +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">¿Qué es la accesibilidad?</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/HTML">HTML: Una buena base para la accesibilidad</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">Mejores prácticas de accesibilidad en CSS y JavaScript </a></li> + <li><a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">WAI-ARIA básico</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Multimedia">Multimedia accesible </a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Mobile">Accessibilidad mobil </a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Solucionador de problemas en </a><a href="/en-US/docs/Learn/Accessibility/Mobile">Accessibilidad</a></li> +</ul> +</div> +</div> diff --git a/files/es/learn/accessibility/qué_es_la_accesibilidad/index.html b/files/es/learn/accessibility/qué_es_la_accesibilidad/index.html new file mode 100644 index 0000000000..e92994e37c --- /dev/null +++ b/files/es/learn/accessibility/qué_es_la_accesibilidad/index.html @@ -0,0 +1,211 @@ +--- +title: ¿Qué es la accesibilidad? +slug: Learn/Accessibility/Qué_es_la_accesibilidad +translation_of: Learn/Accessibility/What_is_accessibility +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/Accessibility/HTML", "Learn/Accessibility")}}</div> + +<p class="summary">En este artículo se inicia el módulo con una explicación ampliada sobre qué es la accesibilidad. Esta visión general incluye qué grupos de personas necesitamos tener en cuenta y por qué, qué herramientas utilizan estas personas para interactuar con la web y cómo podemos hacer que la accesibilidad sea parte de nuestro flujo de trabajo de desarrollo web.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática y de lenguaje HTML y CSS.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarse con la accesibilidad (qué es y cómo te afecta como desarrollador web).</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_la_accesibilidad">¿Qué es la accesibilidad?</h2> + +<p>La accesibilidad hace que tus sitios web puedan ser utilizados por el mayor número de personas posible. Tradicionalmente, se ideó para las personas con discapacidad, pero la creación de sitios accesibles también beneficia a otros grupos, como los que utilizan los dispositivos móviles o los que tienen conexiones de red lentas.</p> + +<p>También podrías pensar en la accesibilidad como una forma de tratar a todos por igual y darles las mismas oportunidades, sin importar su capacidad o circunstancias. Al igual que es injusto excluir a alguien de un edificio porque vaya en silla de ruedas (generalmente, los edificios públicos modernos tienen rampas o ascensores), tampoco es correcto excluir a alguien de un sitio web porque tenga una discapacidad visual. Todos somos diferentes, pero todos somos humanos, y por lo tanto tenemos los mismos derechos.</p> + +<p>Por eso debemos hacer las cosas accesibles. En algunos países es obligado por ley proporcionar sitios web accesibles, lo que te puede abrir algunos mercados importantes que de otra manera no serían capaces de utilizar tus servicios o comprar tus productos.</p> + +<p>Crear sitios web accesibles nos beneficia a todos:</p> + +<ul> + <li>El HTML semántico, aparte de mejorar la accesibilidad, también mejora la optimización en motores de búsqueda (SEO), y la gente encuentra tu sitio web con mayor facilidad.</li> + <li>Preocuparse por la accesibilidad demuestra buenos criterios éticos y morales, lo que mejora tu imagen pública.</li> + <li>Mejorar la accesibilidad también hace que tu sitio sea más fácil de usar por otros grupos, como los usuarios de dispositivos móviles o los que tienen internet de baja velocidad. De hecho, todo el mundo puede beneficiarse de estas mejoras.</li> + <li>¿Hemos mencionado también que en algunos países está estipulado por ley?</li> +</ul> + +<h2 id="¿Con_que_tipo_de_discapacidades_nos_encontraremos">¿Con que tipo de discapacidades nos encontraremos?</h2> + +<p>Las personas con discapacidad son tan diversas como las personas sin discapacidad, y también lo son sus discapacidades. La clave está en pensar más allá de tu ordenador y en cómo utilizas la web y empezar a aprender acerca de cómo otros la utilizan. <em>Tú no eres tus usuarios</em>. A continuación explicaremos los principales tipos de discapacidad que vamos a considerar, junto con las herramientas especiales que se utilizan para acceder al contenido web (conocidas como <strong>tecnologías de apoyo</strong> o <strong>AT</strong>, de <em>assistive technologies</em>).</p> + +<div class="note"> +<p><strong>Nota</strong>: La hoja informativa sobre <a href="https://www.who.int/es/news-room/fact-sheets/detail/disability-and-health">discapacidad y salud</a> de la Organización Mundial de la Salud establece que «Más de mil millones de personas, aproximadamente el 15% de la población mundial, tienen alguna forma de discapacidad» y «Entre 110 millones y 190 millones de adultos tienen dificultades funcionales significativas».</p> +</div> + +<h3 id="Personas_con_discapacidad_visual">Personas con discapacidad visual</h3> + +<p>Las personas con discapacidad visual son aquellas con ceguera, poca visión o daltonismo. Muchas personas con discapacidad visual utilizan amplificadores de pantalla que consisten en lupas físicas o funciones de zoom por software. La mayoría de los navegadores y sistemas operativos de hoy en día tienen instaladas funciones de zoom. Algunos usuarios confían en los lectores de pantalla, un software que lee en voz alta los textos digitales. Algunos ejemplos de lectores de pantalla incluyen:</p> + +<ul> + <li>Productos comerciales de pago, como <a class="external external-icon" href="https://www.freedomscientific.com/Products/software/JAWS/">JAWS</a> (Windows) y <a href="https://yourdolphin.com/screenreader">Dolphin Screen Reader</a> (Windows).</li> + <li>Productos gratuitos, como <a class="external external-icon" href="https://www.nvaccess.org/">NVDA</a> (Windows), <a class="external external-icon" href="https://www.chromevox.com/">ChromeVox</a> (Chrome, Windows y Mac OS X) y <a class="external external-icon" href="https://wiki.gnome.org/Projects/Orca">Orca</a> (Linux).</li> + <li>Productos integrados en el sistema operativo, como <a class="external external-icon" href="https://www.apple.com/accessibility/mac/vision/">VoiceOver</a> (MacOS, iPadOS, IOS), <a class="external external-icon" href="https://support.microsoft.com/en-us/help/22798/windows-10-narrator-get-started">Narrator</a> (Microsoft Windows), <a class="external external-icon" href="https://www.chromevox.com/">ChromeVox</a> (en Chrome OS) y <a class="external external-icon" href="https://play.google.com/store/apps/details?id=com.google.android.marvin.talkback">TalkBack</a> (Android).</li> +</ul> + +<p>Familiarizarse con los lectores de pantalla puede ser útil, así como configurar un lector de pantalla y jugar con él para aprender cómo funciona. Consulta nuestra <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Screenreaders"> guía de lectores de pantalla de prueba para la navegación cruzada</a> para obtener más detalles sobre su uso. El vídeo siguiente proporciona un breve ejemplo de cómo es esta experiencia.</p> + +<p>{{EmbedYouTube("IK97XMibEws")}}</p> + +<p>En términos de estadística, la Organización Mundial de la Salud estima que «Alrededor de 285 millones de personas de todo el mundo tienen discapacidad visual: 39 millones son ciegas y 246 tienen visión reducida.» (Véase <a href="https://www.who.int/es/news-room/fact-sheets/detail/blindness-and-visual-impairment">Discapacidad visual y ceguera</a>). Esa es una población grande y significativa de usuarios (casi la misma población de los Estados Unidos de América), a la que simplemente perderás porque tu sitio web no está codificado correctamente.</p> + +<h3 id="Personas_con_discapacidades_auditivas">Personas con discapacidades auditivas</h3> + +<p>También conocidas como personas con trastornos auditivos o personas sordas. Son un grupo de personas con niveles de audición bajos o nulos. Las personas con discapacidad auditiva usan AT (véase <a href="https://www.nidcd.nih.gov/health/assistive-devices-people-hearing-voice-speech-or-language-disorders">Dispositivos de asistencia para personas con trastornos auditivos, de voz, del habla o del lenguaje</a>), pero en realidad no hay AT específicos para el uso del ordenador/web.</p> + +<p>Hay, sin embargo, técnicas específicas para ofrecer alternativas textuales a contenidos de audio, que van desde simples transcripciones hasta pistas de texto (es decir, subtítulos) que se pueden mostrar junto con el vídeo. Pero lo veremos más adelante.</p> + +<p>Las personas con discapacidad auditiva también representan una importante base de usuarios: «466 millones de personas en todo el mundo tienen pérdida auditiva discapacitante», dice la hoja informativa sobre <a href="https://www.who.int/es/news-room/fact-sheets/detail/deafness-and-hearing-loss">Sordera y pérdida auditiva</a> de la Organización Mundial de la Salud.</p> + +<h3 id="Personas_con_discapacidad_motriz">Personas con discapacidad motriz</h3> + +<p>Estas personas tienen discapacidades relativas a la movilidad, que pueden implicar problemas puramente físicos (como la pérdida de una extremidad o la parálisis) o trastornos neurológicos/genéticos que conducen a la debilidad o pérdida de control en las extremidades. Algunas personas simplemente pueden tener dificultades a la hora de mover el ratón, mientras que otras podrían verse más gravemente afectadas, tal vez estén paralizadas y necesiten utilizar un <a href="https://www.performancehealth.com/baseball-cap-head-pointer">puntero de cabeza</a> para interactuar con los ordenadores.</p> + +<p>Este tipo de discapacidad se da principalmente por la vejez, y no por cualquier trauma o condición específica, y también podría resultar de limitaciones en el hardware (algunos usuarios podrían no tener un ratón).</p> + +<p>La forma en que esto afecta al desarrollo web es el requisito de que los controles sean accesibles por el teclado. Hablaremos de la accesibilidad del teclado en artículos posteriores de este módulo, pero te recomendamos probar algunos sitios web utilizando solo el teclado para ver cómo funcionan. Por ejemplo, ¿se puede utilizar la tecla de tabulación para moverse entre los diferentes controles de un formulario web? Puedes encontrar más detalles sobre los controles del teclado en nuestro apartado <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Using_native_keyboard_accessibility">Accesibilidad desde el teclado</a>.</p> + +<p>Si nos basamos en las estadísticas, vemos que un número significativo de personas tienen problemas de movilidad. Los Centros para el Control y la Prevención de Enfermedades de <a href="https://www.cdc.gov/nchs/fastats/disability.htm">Discapacidad y Funcionalidad (Adultos a partir de 18 años no registrados en una institución)</a> de los Estados Unidos informan de que el porcentaje de adultos con alguna disfunción física en los EUA es del 16,1%.</p> + +<h3 id="Personas_con_discapacidad_cognitiva">Personas con discapacidad cognitiva</h3> + +<p>La discapacidad cognitiva engloba una amplia gama de discapacidades, desde las personas que presentan las capacidades intelectuales más limitadas hasta toda la población que tiene problemas a la hora de recordar por los síntomas de la edad. Este amplio abanico incluye a las personas con enfermedades mentales como la <a href="https://www.nimh.nih.gov/health/topics/depression/index.shtml">depresión</a> y la <a href="https://www.nimh.nih.gov/health/topics/schizophrenia/index.shtml">esquizofrenia</a>. También incluye a personas con dificultades de aprendizaje, como la <a href="https://www.ninds.nih.gov/Disorders/All-Disorders/Learning-Disabilities-Information-Page">dislexia</a> y el <a href="https://www.nimh.nih.gov/health/topics/attention-deficit-hyperactivity-disorder-adhd/index.shtml">trastorno por déficit de atención con hiperactividad</a>. Es importante destacar que, aunque hay una gran diversidad dentro de las definiciones clínicas de alteraciones cognitivas, las personas que las experimentan tienen un conjunto común de problemas funcionales, que incluye dificultades a la hora de entender los contenidos, recordar cómo completar las tareas y confusión ante páginas web diseñadas de forma incoherente.</p> + +<p>Una buena base de accesibilidad para personas con deficiencias cognitivas incluye:</p> + +<ul> + <li>proporcionar el contenido en más de un formato, como puede ser texto-a-voz o vídeo;</li> + <li>proporcionar contenidos fáciles de entender, como texto escrito con estándares de lenguaje sencillo;</li> + <li>centrar la atención en el contenido importante;</li> + <li>minimizar las distracciones, tales como contenidos innecesarios o anuncios;</li> + <li>proporcionar un diseño coherente de la página web y del sistema de navegación;</li> + <li>usar elementos ya conocidos, como los enlaces subrayados en azul cuando aún no se han visitado, y en morado cuando sí;</li> + <li>dividir los procesos en pasos lógicos y esenciales con indicadores de progreso;</li> + <li>ofrecer un sistema de autenticación del sitio web de la forma más fácil posible sin comprometer la seguridad; y</li> + <li>diseñar formularios fáciles de completar, con mensajes de error claros y de fácil solución.</li> +</ul> + +<h3 id="Observaciones">Observaciones</h3> + +<ul> + <li>Diseñar para la <a href="/en-US/docs/Web/Accessibility/Cognitive_accessibility">accesibilidad cognitiva</a> proporcionará buenas prácticas de diseño que beneficiarán a todo el mundo.</li> + <li>Muchas personas con discapacidades cognitivas también tienen discapacidades físicas. Los sitios web deben cumplir con las directrices de accesibilidad a los contenidos web <a href="https://www.w3.org/WAI/standards-guidelines/wcag/">Web Content Accessibility Guidelines</a> de W3C, que incluyen las <a href="/en-US/docs/Web/Accessibility/Cognitive_accessibility#Guidelines">directrices de accesibilidad cognitiva</a>.</li> + <li>El apartado <a href="https://www.w3.org/WAI/GL/task-forces/coga/">Cognitive and Learning Disabilities Accessibility Task Force</a> de W3C aporta pautas de accesibilidad web para personas con discapacidades cognitivas.</li> + <li>WebAIM tiene una <a href="https://webaim.org/articles/cognitive/">página cognitiva</a> con la información y los recursos correspondientes.</li> + <li>Los Centros para el Control de Enfermedades estimaron que, en 2018, 1 de cada 4 ciudadanos de Estados Unidos presentaba alguna discapacidad y que la discapacidad cognitiva es la más común entre los jóvenes.</li> + <li>En los EUA, el término «retraso mental» se ha sustituido por el de «discapacidad intelectual». En el Reino Unido, a la «discapacidad intelectual» se le llama comúnmente «discapacidades de aprendizaje» o «dificultades de aprendizaje».</li> +</ul> + +<h2 id="Implementa_la_accesibilidad_en_tu_proyecto">Implementa la accesibilidad en tu proyecto</h2> + +<p>Un mito común de la accesibilidad es que se trata de un «extra añadido» que encarece tu proyecto. Este mito <em>puede</em> resultar cierto si:</p> + +<ul> + <li>Tratas de «readaptar» la accesibilidad de un sitio web que tiene problemas de accesibilidad importantes.</li> + <li>Solo has empezado a considerar la accesibilidad y temas relacionados en las últimas etapas de un proyecto.</li> +</ul> + +<p>Sin embargo, si se tiene en cuenta la accesibilidad desde el inicio de un proyecto, el coste es muy reducido.</p> + +<p>Al planificar tu proyecto, debes tener en cuenta las pruebas de accesibilidad en la fase de pruebas, lo mismo que las pruebas para cualquier otro sector de público objetivo importante (por ejemplo, los navegadores de escritorio o los navegadores para dispositivo móvil). Somete tu proyecto a pruebas desde una etapa temprana y con frecuencia, idealmente con pruebas automatizadas para detectar carencias detectables en la programación, como la falta de <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Text_alternatives">textos alternativos</a> en las imágenes o textos de enlace no adecuados (consulta <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Element_relationships_and_context">Relaciones entre elementos y contexto</a>). Y haz algunas pruebas con grupos de usuarios con discapacidad para ver cómo se desenvuelven con las características más complejas de tu sitio web. Por ejemplo:</p> + +<ul> + <li>¿Las personas que utilizan lectores de pantalla tendrán problemas con mi selector de fechas?</li> + <li>¿Pueden saber las personas con discapacidad visual si el contenido se actualiza dinámicamente?</li> + <li>¿Puedo acceder a los botones de mi interfaz de usuario desde el teclado y desde las interfaces táctiles?</li> +</ul> + +<p>Puedes y debes tener en cuenta las áreas potencialmente problemáticas del contenido que habrá que modificar para proporcionarles accesibilidad, asegúrate de que se prueban a fondo y piensa en soluciones/alternativas. El contenido textual (como veremos en el próximo artículo) es fácil, pero ¿qué pasa con el contenido multimedia y con esos fantásticos gráficos 3D? Echa un ojo al presupuesto del proyecto y piensa en soluciones que estén a tu disposición para convertir tales contenidos en accesibles. Transcribir todos tus archivos multimedia es una opción posible, aunque cara.</p> + +<p>Seamos realistas. El «100% de accesibilidad» es un ideal inalcanzable, ya que siempre te encontrarás con algún tipo de caso límite en que un determinado usuario encuentra ciertos contenidos difíciles de usar, pero debes hacer todo lo que puedas. Si planeas incluir un gráfico 3D circular creado a partir de WebGL, es posible que desees incluir una tabla de datos como una representación alternativa accesible. O bien puedes simplemente incluir la tabla y deshacerte del gráfico circular 3D (todo el mundo puede acceder a la tabla, su codificación resulta más simple, y además consume menos recursos de la CPU y es de mantenimiento más fácil.</p> + +<p>Por otro lado, si trabajas en un sitio web de una galería que muestra obras de arte interesantes en 3D, no sería razonable esperar que cada obra de arte sea perfectamente accesible para las personas con discapacidad visual, ya que se trata de un medio completamente visual.</p> + +<p>Para demostrar que te importa y que has pensado en la accesibilidad, publica una declaración de accesibilidad en la página web que explique tu política de accesibilidad y los pasos realizados para hacer que el sitio web sea accesible. Si alguien se queja de que tiene un problema de accesibilidad: inicia un diálogo con ellos, se empático y toma las medidas razonables para tratar de solucionar el problema.</p> + +<div class="note"> +<p><strong>Nota</strong>: Nuestro artículo sobre <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility">Cómo afrontar los problemas de accesibilidad más comunes</a> expone los detalles de accesibilidad que es necesario tener más en cuenta.</p> +</div> + +<p>En resumen:</p> + +<ul> + <li>Considera la accesibilidad desde el inicio de un proyecto y haz pruebas con frecuencia. Al igual que cualquier otro error, un problema de accesibilidad se vuelve más caro de arreglar cuanto más tarde se descubre.</li> + <li>Ten en cuenta que muchas de las buenas prácticas de accesibilidad benefician a todo el mundo, no solo a los usuarios con discapacidad. Por ejemplo, el marcado semántico no solo es bueno para los lectores de pantalla, sino que también es de carga y ejecución rápidas. Esto nos beneficia a todos, especialmente a quienes entran con dispositivos móviles y/o tienen conexión lenta.</li> + <li>Publica una declaración de accesibilidad en la página web y relacionarse con la gente que tiene problemas.</li> +</ul> + +<h2 id="Directrices_de_accesibilidad_y_la_ley">Directrices de accesibilidad y la ley</h2> + +<p>Hay numerosas listas de control y conjuntos de directrices en las cuales basar las pruebas de accesibilidad, por lo que podría parecer abrumador a primera vista. Nuestro consejo es que te familiarices con las áreas básicas en las que te interesa centrarte, así como que comprendas las estructuras de alto nivel de las directrices que son más relevantes para ti.</p> + +<ul> + <li>Para empezar, el W3C ha publicado un documento muy extenso y detallado que incluye criterios de accesibilidad muy precisos, independientes de la tecnología. Se llaman <a href="https://www.w3.org/WAI/standards-guidelines/wcag/">Web Content Accessibility Guidelines</a> (WCAG). Los criterios se dividen en cuatro categorías principales, las cuales especifican según el tipo de implementaciones: perceptibles, operables, comprensibles y robustas. El mejor lugar para adquirir una ligera introducción y comenzar el aprendizaje es <a href="https://www.w3.org/WAI/standards-guidelines/wcag/glance/">WCAG at a Glance</a>. No es necesario que te aprendas las directrices WCAG de memoria, solo tienes que ser consciente de las áreas de preocupación principales y utilizar una variedad de técnicas y herramientas para destacar aquellas áreas que no se ajustan a los criterios WCAG (véase más abajo).</li> + <li>Tu país también puede tener una legislación específica que regule la necesidad de la accesibilidad que los sitios web. Por ejemplo, la norma <a href="https://www.etsi.org/deliver/etsi_en/301500_301599/301549/02.01.02_60/en_301549v020102p.pdf">EN 301 549</a> en la UE, la <a href="https://www.section508.gov/training">sección 508 de la Ley de Rehabilitación</a> en los EUA, la <a href="https://www.einfach-fuer-alle.de/artikel/bitv_english/">Ordenanza Federal de Tecnología de la Información sin barreras</a> en Alemania, el <a href="https://www.legislation.gov.uk/uksi/2018/952/introduction/made">Reglamento de accesibilidad 2018</a> en el Reino Unido, la <a href="https://www.agid.gov.it/it/design-servizi/accessibilita-siti-web">Accessibilità</a> en Italia, la <a href="https://www.humanrights.gov.au/world-wide-web-access-disability-discrimination-act-advisory-notes-ver-41-2014">Ley de Discriminación por Discapacidad</a> en Australia, etc. La W3C tiene una lista de <a href="https://www.w3.org/WAI/policies/">políticas y leyes de accesibilidad web</a> según países.</li> +</ul> + +<p>Así, mientras que la WCAG es un conjunto de directrices, tu país probablemente tiene leyes que rigen la accesibilidad web, o al menos la accesibilidad de los servicios disponibles para el público (que incluyen sitios web, televisión, espacios físicos, etc.). Conocer estas leyes puede resultarte útil. Si no te preocupas por comprobar que tu contenido sea accesible, podrías incurrir en alguna responsabilidad legal, si la gente se queja.</p> + +<p>Suena serio, pero en realidad solo tienes que considerar la accesibilidad como la prioridad principal a la hora de desarrollar tu web, como ya hemos dicho. En caso de duda, asesórate por un abogado cualificado. Y como nosotros no lo somos, no vamos a ofrecer más consejos sobre este tema.</p> + +<h2 id="API_de_accesibilidad">API de accesibilidad</h2> + +<p>Los navegadores web hacen uso de <strong>API de accesibilidad</strong> especiales (proporcionadas por el sistema operativo subyacente) que exponen información útil para las tecnologías de asistencia (AT, <em>assistive technologies</em>): la mayoría de AT tienden a utilizar información semántica, por lo que esta información no incluye información de estilo o JavaScript. Esta información se estructura en un árbol de datos, denominado <strong>árbol de accesibilidad</strong>.</p> + +<p>Los diferentes sistemas operativos disponen de diferentes API de accesibilidad:</p> + +<ul> + <li>Windows: MSAA/IAccessible, UIAExpress, IAccessible2</li> + <li>Mac OS X: NSAccessibility</li> + <li>Linux: AT-SPI</li> + <li>Android: Accessibility framework</li> + <li>iOS: UIAccessibility</li> +</ul> + +<p>Cuando la información semántica nativa proporcionada por los elementos HTML de tus aplicaciones web falla, puedes complementarlo con características de la <a href="https://www.w3.org/TR/wai-aria/">especificación WAI-ARIA</a>, que añaden información semántica al árbol para mejorar la accesibilidad. Puedes aprender más acerca de WAI-ARIA en nuestro artículo de <a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">fundamentos WAI-ARIA</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Este artículo debería haber dado una descripción detallada sobre la accesibilidad, mostrar por qué es importante y enseñar cómo puede encajar en tu flujo de trabajo. Ahora también deberías tener sed de conocimientos sobre los detalles de implementación que hacen que los sitios sean accesibles. Comenzaremos con esto en la sección siguiente, observando por qué HTML es una buena base para la accesibilidad.</p> + +<p>{{NextMenu("Learn/Accessibility/HTML", "Learn/Accessibility")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Accessibility/What_is_accessibility">¿Qué es la accesibilidad?</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/HTML">HTML: Una buena base para la accesibilidad</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/CSS_and_JavaScript">Buenas prácticas de accesibilidad en CSS y JavaScript</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/WAI-ARIA_basics">Fundamentos WAI-ARIA</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Multimedia">Multimedia accesible</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Mobile">Accesibilidad móvil</a></li> + <li><a href="/en-US/docs/Learn/Accessibility/Accessibility_troubleshooting">Resolución de problemas de accesibilidad</a></li> +</ul> + +<h2 id="Véase_también">Véase también</h2> + +<ul> + <li><a href="/en-US/docs/Web/Accessibility/Understanding_WCAG">WCAG</a> + + <ul> + <li><a href="/en-US/docs/Web/Accessibility/Understanding_WCAG/Perceivable">Perceptible</a></li> + <li><a href="/en-US/docs/Web/Accessibility/Understanding_WCAG/Operable">Operable</a></li> + <li><a href="/en-US/docs/Web/Accessibility/Understanding_WCAG/Understandable">Comprensible</a></li> + <li><a href="/en-US/docs/Web/Accessibility/Understanding_WCAG/Robust">Robusto</a></li> + </ul> + </li> +</ul> diff --git a/files/es/learn/aprender_y_obtener_ayuda/index.html b/files/es/learn/aprender_y_obtener_ayuda/index.html new file mode 100644 index 0000000000..a7f06d90d8 --- /dev/null +++ b/files/es/learn/aprender_y_obtener_ayuda/index.html @@ -0,0 +1,321 @@ +--- +title: Aprender y obtener ayuda +slug: Learn/Aprender_y_obtener_ayuda +tags: + - Aprender + - Desarrollo web + - Principiante + - conseguir ayuda + - obtener ayuda +translation_of: Learn/Learning_and_getting_help +--- +<p>{{learnsidebar}}</p> + +<p>Es genial que dediques algo de tiempo a aprender un nuevo conjunto de habilidades, pero puedes emplear algunas buenas prácticas que harán que tu aprendizaje sea más efectivo. También hay momentos en los que te atascarás y te sentirás frustrado, incluso los desarrolladores web profesionales se sienten así regularmente, y vale la pena conocer las formas más efectivas de tratar de obtener ayuda para que puedas progresar en tu trabajo. Este artículo proporciona algunos consejos y sugerencias en ambas áreas que te ayudarán a obtener más provecho del aprendizaje del desarrollo web, así como una lectura adicional para que puedas obtener más información sobre cada subtema si lo deseas.</p> + +<h2 id="Aprendizaje_efectivo">Aprendizaje efectivo</h2> + +<p>Sigamos adelante y pensemos en un aprendizaje efectivo.</p> + +<h3 id="Diferentes_métodos_de_aprendizaje">Diferentes métodos de aprendizaje</h3> + +<p>Es interesante considerar que hay dos formas principales en las que tu cerebro aprende cosas — el aprendizaje <strong>enfocado</strong> y el aprendizaje <strong>difuso</strong>:</p> + +<ul> + <li>El aprendizaje enfocado es lo que tradicionalmente podrías asociar con las materias académicas. Te concentras profundamente en un tema de bajo nivel y resuelves los problemas específicos demostrando que eres muy capaz. Estás enfocado en una área estrecha.</li> + <li>El aprendizaje difuso tiene más que ver con el pensamiento de alto nivel en un área más amplia. Dejas que tu mente divague más y aparentemente haces conexiones aleatorias entre diferentes cosas. Este es más el tipo de pensamiento que llevas a cabo mientras estás en la ducha o durante un descanso para tomar café.</li> +</ul> + +<p>A partir de los estudios que los neurocientíficos han realizado sobre la actividad cerebral, hemos descubierto que realmente no se puede participar en ambas formas de aprendizaje, o de pensamiento simultáneamente. Entonces, ¿cuál debes elegir? Puedes pensar que el aprendizaje enfocado es mejor para estudiar, pero en realidad, <strong>ambos</strong> son muy importantes.</p> + +<p>El pensamiento enfocado es excelente para concentrarte mucho en temas específicos, profundizar en la resolución de problemas y mejorar tu dominio de las técnicas requeridas, fortaleciendo las vías neuronales en tu cerebro donde se almacena esa información. Sin embargo, no es muy bueno para entender "el panorama general" y desbloquear nuevas vías neuronales cuando intentas comprender nuevos temas o resolver nuevos problemas que no has encontrado antes.</p> + +<p>Para eso, necesitas un pensamiento difuso. Esto es lo opuesto al enfoque — dejas que tu cerebro divague por el paisaje más amplio, buscando conexiones que no tenías antes, tocando cosas nuevas (o nuevas combinaciones de cosas) en las que luego puedes concentrarte para fortalecerlas y empezar a entender realmente lo que significan.</p> + +<p>Es por eso que generalmente es bueno leer primero un material introductorio para obtener una comprensión de alto nivel de un área, antes de saltar a los detalles específicos.</p> + +<p>También es la razón por la que, a veces, puedes quedar realmente atrapado en un problema, pero luego averiguar la respuesta cuando vas a tomar un café (o a caminar). Podrías:</p> + +<ol> + <li>Saber cómo solucionar el problema A con la herramienta A.</li> + <li>Saber cómo solucionar el problema B con la herramienta B.</li> + <li>No saber cómo solucionar el problema C.</li> +</ol> + +<p>Supongamos que te enfocas en el problema C por un tiempo y te frustras porque no puedes encontrar la solución para resolverlo. Pero luego, después de caminar para tomar un poco de aire fresco, es posible que descubras que, mientras tu mente divaga, de repente estableces una conexión entre la herramienta A y la herramienta B, ¡y te das cuenta de que las puedes usar juntas para solucionar el problema C! No siempre es así de simple, pero también es sorprendente cuántas veces sucede. Esto también resalta la importancia de tomar descansos regulares cuando estás estudiando frente a la computadora.</p> + +<h3 id="Diferentes_materiales_de_aprendizaje">Diferentes materiales de aprendizaje</h3> + +<p>También vale la pena mirar los diferentes tipos de materiales de aprendizaje disponibles, para ver cuáles son los más efectivos para que aprendas.</p> + +<h4 id="Artículos_textuales">Artículos textuales</h4> + +<p>Encontrarás muchos artículos escritos en la web para enseñarte sobre diseño web. Como la mayor parte de este curso, por ejemplo. Algunos de los artículos serán tutoriales, para enseñarte una determinada técnica o concepto importante (como "<em>aprender a crear un reproductor de video</em>" o "<em>Aprender el modelo de cajas CSS</em>"), y algunos de los artículos serán material de referencia, para permitirte recordar detalles que hayas olvidado (como "<em>¿cuál es la sintaxis de la propiedad <code>background</code> de CSS</em>"?)</p> + +<p>MDN Web Docs es muy bueno para ambos tipos — el área en la que te encuentras actualmente es excelente para aprender técnicas y conceptos, y también tenemos varias secciones de referencia gigantes que te permiten buscar cualquier sintaxis que no puedas recordar.</p> + +<p>También hay varios otros recursos excelentes en la web, algunos de los cuales mencionaremos a continuación.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: el texto anterior debería haberte proporcionado un dato importante: <em>¡no se espera que recuerdes todo!</em> Los desarrolladores web profesionales todo el tiempo usan herramientas como <em>MDN Web Docs</em> para buscar cosas que han olvidado. Como descubrirás a lo largo de estas líneas, aprender desarrollo web tiene más que ver con la resolución de problemas y patrones de aprendizaje que con el aprendizaje de muchas sintaxis.</p> +</div> + +<h4 id="Videos">Videos</h4> + +<p>También hay una serie de sitios que tienen contenido de aprendizaje de video en ellos. YouTube es obvio, con canales como <a href="https://www.youtube.com/channel/UC7TizprGknbDalbHplROtag" rel="noopener">Mozilla Layout Land</a>, <a href="https://www.youtube.com/MozillaDeveloper" rel="noopener">MozillaDeveloper</a> y <a href="https://www.youtube.com/user/ChromeDevelopers/" rel="noopener">Google ChromeDevelopers</a> que proporcionan muchos útiles videos. Muchas personas prefieren artículos textuales para un aprendizaje más profundo y material de referencia, y videos para explicaciones rápidas de conceptos y nuevas características, pero realmente depende de ti lo que prefieras aprender. Aquí no hay una respuesta correcta e incorrecta.</p> + +<h4 id="Código_de_juegos_interactivos">Código de juegos interactivos</h4> + +<p>Posiblemente seas el tipo de persona que prefiere instrucciones mínimas y preferirías saltar directamente y comenzar a jugar con el código. Este también es un enfoque razonable, y algunos sitios de aprendizaje tienden a favorecerlo. <a href="https://www.codecademy.com/" rel="noopener">Codecademy,</a> por ejemplo, es un sitio de aprendizaje donde los tutoriales consisten principalmente en editores de códigos interactivos en los que debes escribir directamente el código y ver si se logró el resultado deseado.</p> + +<p>Muchas páginas de referencia de documentos web de MDN también proporcionan ejemplos interactivos, donde puedes modificar el código y ver cómo cambia el resultado en vivo. Y tampoco hay nada de malo en crear tus propios ejemplos de código en tu computadora o en un editor de código en línea como <a href="https://jsbin.com/?html,css,js,output" rel="noopener">JSBin</a>, <a href="https://codepen.io/" rel="noopener">Codepen</a> o <a href="https://glitch.com/" rel="noopener">Glitch</a>. De hecho, ¡te invitarán a usarlos como parte de este curso cuando estés aprendiendo!</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Los editores de código en línea también son realmente útiles para compartir el código que has escrito, por ejemplo, si estás colaborando en el aprendizaje con otra persona que no se encuentra en la misma ubicación o se lo envías a alguien para pedir ayuda con eso. Puedes compartir la dirección web del ejemplo con ellos para que puedan verlo y ayudarte.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Es posible que prefieras un método de aprendizaje sobre los demás, pero, de manera realista, probablemente terminarás con un enfoque híbrido. Y probablemente se te ocurran otros métodos además de los tres que cubrimos anteriormente.</p> +</div> + +<h3 id="Haz_un_plan">Haz un plan</h3> + +<p>Es una buena idea crear un plan para ayudarte a lograr lo que quieres conseguir a través de tu aprendizaje.</p> + +<h4 id="Una_declaración_de_objetivos">Una declaración de objetivos</h4> + +<p>Suena tonto, pero ¿por qué no comenzar con una sola oración que diga lo que quieres lograr? Los siguientes tienen diferentes ámbitos, pero todos son realistas y alcanzables:</p> + +<ul> + <li>Quiero convertirme en un desarrollador web profesional dentro de dos años.</li> + <li>Quiero aprender lo suficiente como para crear un sitio web para mi club de tenis amateur local.</li> + <li>Quiero aprender HTML y CSS para poder ampliar mi rol de trabajo para encargarme de actualizar el contenido del sitio web de nuestra empresa.</li> +</ul> + +<p>Los siguientes no son tan razonables:</p> + +<ul> + <li>Quiero pasar de ser un principiante completamente novato a ser un desarrollador web senior en tres meses.</li> + <li>Quiero comenzar mi propia empresa y construir una red social que supere a Facebook en dos años.</li> +</ul> + +<h4 id="¿Qué_necesitas_para_llegar_allí">¿Qué necesitas para llegar allí?</h4> + +<p>Una vez que hayas descrito tu objetivo, es una buena idea investigar qué necesitarás para lograrlo. Por ejemplo:</p> + +<p>Materiales que necesito:</p> + +<ul> + <li>Un ordenador</li> + <li>Acceso a Internet</li> + <li>Bolígrafos y papel</li> +</ul> + +<p>Conocimiento que necesito:</p> + +<ul> + <li>Cómo usar HTML, CSS, JavaScript y las herramientas asociadas y las mejores prácticas para crear sitios web y aplicaciones web (¡definitivamente te podemos ayudar con esto!).</li> + <li>Cómo obtener un dominio, alojamiento y usarlos para poner un sitio web o una aplicación en línea.</li> + <li>Cómo dirigir una pequeña empresa.</li> + <li>Cómo publicitar tu negocio y atraer clientes.</li> +</ul> + +<h4 id="¿Cuánto_tiempo_y_dinero_costará">¿Cuánto tiempo y dinero costará?</h4> + +<p>Calcula el tiempo y el costo para obtener estas cosas. Si necesitas trabajar para ganar dinero para comprar los materiales requeridos, entonces deberás tener en cuenta el tiempo para hacerlo. Una vez que tengas un estimado del tiempo, puedes comenzar a elaborar un plan para tu vida.</p> + +<h4 id="¿Cuántas_horas_por_semana_necesitas_invertir">¿Cuántas horas por semana necesitas invertir?</h4> + +<p>Una vez que sepas lo que necesitas hacer y cuánto tiempo crees que te llevará, puedes comenzar a escribir un plan a seguir para lograr tu objetivo. Puede ser tan simple como:</p> + +<p>"Me llevará 500 horas aprender lo que necesito saber, y tengo un año para hacerlo, así que si asumo 2 semanas de vacaciones, tendré que trabajar en esto durante 10 horas por semana. Estoy gratis por las tardes y fines de semana, así que planearé mi tiempo en torno a eso".</p> + +<p>La cantidad de tiempo que puedes dedicar a esto, por supuesto, depende de cuáles sean tus circunstancias. Si estás en la escuela, entonces tienes mucho más tiempo libre que si tienes un trabajo y niños que mantener. Todavía es posible lograr tus objetivos, pero debes ser realista sobre la rapidez con que puedes lograrlo.</p> + +<p>Si estás haciendo un curso colegial o universitario para aprender desarrollo web, entonces la mayor parte de esta planificación la haces tú, ¡qué suerte!</p> + +<p>Cuando hayas elaborado un horario semanal, debes mantener un registro de lo que logras hacer cada semana en una simple hoja de cálculo o incluso en un cuaderno.</p> + +<p>Además, sería una buena idea tener algunos objetivos secundarios resueltos que te permitan realizar fácilmente un seguimiento de dónde te encuentras, por ejemplo:</p> + +<ul> + <li>Conceptos básicos de HTML y CSS aprendidos en verano</li> + <li>Conceptos básicos de JavaScript aprendidos en Diciembre</li> + <li>Ejemplo de proyecto del sitio web creado para el próximo mes de abril</li> + <li>etc.</li> +</ul> + +<p>Sigue pensando en cuánto progreso estás haciendo y ajusta tu plan si es necesario.</p> + +<h3 id="Mantente_motivado">Mantente motivado</h3> + +<p>Es difícil mantenerte motivado, especialmente si estás tratando de aprender una habilidad compleja como la programación o el desarrollo web. Lo que sigue son algunos consejos para mantenerte motivado y seguir trabajando:</p> + +<ul> + <li><strong>Intenta que tu entorno de trabajo sea lo más productivo posible</strong>. Intenta conseguir un escritorio y una silla cómodos para trabajar, asegúrate de tener suficiente luz para ver lo que estás haciendo e intenta incluir cosas que te ayuden a concentrarte (por ejemplo, música suave, fragancias, cualquier otra cosa que necesites). No intentes trabajar en una habitación con distracciones, por ejemplo, un televisor encendido, ¡con tus amigos mirando fútbol! Además, deja tu teléfono móvil fuera de la habitación; la mayoría de las personas que lo tenemos nos distraemos mucho con el teléfono, por lo que debes dejarlo en otro lugar.</li> + <li><strong>Tómate descansos regulares</strong>. No es bueno para tu motivación seguir trabajando durante horas sin descanso, especialmente si te resulta difícil o te estás quedando atrapado en un problema. Eso solo conduce a la frustración — a menudo, es mejor tomar un descanso, muévete un poco, luego relájate con una bebida antes de volver al trabajo, y como dijimos anteriormente, el aprendizaje difuso que haces en ese momento a menudo puede ayudarte para encontrar una solución al problema que estabas enfrentando. Además, físicamente es malo trabajar durante demasiado tiempo sin un descanso — mirar un monitor durante demasiado tiempo puede lastimar los ojos, y permanecer sentado demasiado tiempo puede ser malo para la espalda o las piernas. Recomendamos tomar un descanso de 15 minutos cada hora a 90 minutos.</li> + <li><strong>Come, haz ejercicio y duerme</strong>. Come saludablemente, haz ejercicio regularmente y asegúrate de dormir lo suficiente. Esto suena obvio, pero es fácil olvidar cuando realmente te dedicas a la codificación. Incluye estos ingredientes esenciales en tu horario y asegúrate de no estar haciendo tu tiempo de aprendizaje en lugar de estas cosas.</li> + <li><strong>Regálate recompensas</strong> . Es cierto que <em>todo trabajo y nada de juego hacen que Jack sea un niño aburrido</em>. Debes tratar de programar cosas divertidas para hacer después de cada sesión de aprendizaje, que solo tendrás cuando hayas terminado y completado el aprendizaje. Si realmente te gustan los juegos, por ejemplo, hay algo bastante motivador en decir "no jugaré esta noche a menos que termine mis 5 horas de aprendizaje". Ahora, todo lo que necesitas es fuerza de voluntad. ¡Buena suerte!</li> + <li><strong>Coaprendizaje y demostración</strong>. Esta no será una opción para todos, pero si es posible, trata de aprender junto con otros. Una vez más, esto es más fácil si estás haciendo un curso universitario sobre desarrollo web, pero ¿tal vez podrías convencer a un amigo para que aprenda junto contigo? o encontrar una reunión local o un grupo de intercambio de habilidades. Es realmente útil y motivador tener a alguien con quien discutir ideas y pedir ayuda, y también debes tomarte el tiempo para demostrar tu trabajo. Esas palabras de agradecimiento te estimularán.</li> +</ul> + +<h3 id="Resolución_de_problemas_eficaz">Resolución de problemas eficaz</h3> + +<p>No hay una única forma efectiva de resolver todos los problemas (y aprender todo) lo relacionado con el diseño y desarrollo web, pero hay algunos consejos generales que te servirán en la mayoría de los casos.</p> + +<h4 id="Romper_las_cosas_en_trozos">Romper las cosas en trozos</h4> + +<p>Para empezar, cuando intentas implementar algo específico y parece realmente difícil entenderlo, debes tratar de dividirlo en múltiples problemas o fragmentos más pequeños.</p> + +<p>Por ejemplo, si estás considerando la tarea de "Crear un sitio web simple de dos columnas", la puedes desglosar de la siguiente manera:</p> + +<ul> + <li>Crea la estructura HTML</li> + <li>Resuelve la tipografía básica del sitio</li> + <li>Elabora un esquema de color básico</li> + <li>Implementa un diseño de alto nivel: encabezado, menú de navegación horizontal, área de contenido principal con columnas principales y laterales y pie de página.</li> + <li>Implementa un menú de navegación horizontal.</li> + <li>etc.</li> +</ul> + +<p>Luego, podrías desglosarlo aún más, por ejemplo, "Implementar menú de navegación horizontal" podría escribirse como:</p> + +<ul> + <li>Haz una lista de los elementos del menú situados horizontalmente en una línea.</li> + <li>Elimina los valores predeterminados innecesarios, como el espaciado de las listas y viñetas.</li> + <li>Estiliza el cursor/enfoque/estados activos de los elementos del menú adecuadamente.</li> + <li>Haz los elementos del menú igualmente espaciados a lo largo de la línea.</li> + <li>Da a los elementos del menú suficiente espacio vertical.</li> + <li>Asegúrate de que el texto esté centrado dentro de cada elemento del menú</li> + <li>etc.</li> +</ul> + +<p>Cada uno de estos problemas no parece tan difícil de resolver como el gran problema que tuviste inicialmente. ¡Ahora solo tienes que empezar a resolverlos todos!</p> + +<h4 id="Aprende_y_reconoce_los_patrones">Aprende y reconoce los patrones</h4> + +<p>Como dijimos antes, el diseño/programación web se trata principalmente de resolución de problemas y patrones. Una vez que hayas escrito lo que necesitarás hacer para resolver un problema específico, puedes comenzar a descubrir qué características tecnológicas usar para resolverlo. Por ejemplo, los desarrolladores web profesionales han creado muchos menús de navegación horizontal, por lo que inmediatamente comenzarás a pensar en una solución como esta:</p> + +<p>Un menú de navegación generalmente se crea a partir de una lista de enlaces, algo así como:</p> + +<pre class="brush: html notranslate"><ul> + <li>Primer elemento del menú</li> + <li>Segundo elemento del menú</li> + <li>Tercer elemento del menú</li> + <li>etc.</li> +</ul> +</pre> + +<p>Para hacer que todos los elementos se asienten horizontalmente en una línea, la forma moderna más fácil es usar flexbox:</p> + +<pre class="notranslate">ul { + display: flex; +}</pre> + +<p>Para eliminar el espacio innecesario y las viñetas, podemos hacer esto:</p> + +<pre class="notranslate">ul { + list-style-type: none; + padding: 0; +}</pre> + +<p>etc.</p> + +<p>Si realmente eres un principiante en el desarrollo web, tendrás que estudiar y buscar en la web y encontrar soluciones para tales problemas. Si eres un desarrollador web profesional, probablemente recordarás la última vez que resolviste un problema similar, y solo tendrás que buscar algunos bits de la sintaxis que olvidaste desde entonces.</p> + +<p>Cuando encuentres soluciones a tales problemas, vale la pena escribir notas sobre lo que hiciste y mantener algunos ejemplos de código mínimos en un directorio en algún lugar para que puedas mirar hacia atrás en el trabajo anterior.</p> + +<p>Además, la web tiene {{web.link("/es/docs/Learn/Common_questions/What_are_browser_developer_tools", "herramientas de desarrollo")}} que te permiten ver el código utilizado para crear cualquier sitio en la web, si no tienes una solución a mano, un buen método de investigación es encontrar sitios web con características similares en la naturaleza y averiguar cómo lo hicieron.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Observa cómo hablamos antes sobre el problema que estamos tratando de resolver primero, y la tecnología utilizada para resolverlo, en segundo lugar. Esta, casi siempre es la mejor manera de hacerlo — no comiences con una tecnología nueva y genial que desees usar, e intenta adaptarla a tu caso de uso.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: La solución más sencilla suele ser la mejor.</p> +</div> + +<h3 id="Practica">Practica</h3> + +<p>Cuanto más practiques la resolución de un problema, más fuertes serán las vías neuronales de tu cerebro en esa área y más fácil será recordar los detalles y la lógica de ese problema en particular.</p> + +<p>Sigue jugando con el código y practica más. Si se te acaban los problemas por resolver, busca algunas pruebas en línea, realiza algunos cursos más o pregunta a tus amigos y familiares (o escuela, o iglesia local) si hay algo que les gustaría que construyeras para ellos.</p> + +<h2 dir="ltr" id="Obtener_ayuda">Obtener ayuda</h2> + +<p dir="ltr">El desarrollo web requiere que aprendas un complejo conjunto de habilidades — a veces estarás atascado y necesitarás ayuda. Como dijimos antes, incluso los desarrolladores profesionales regularmente necesitan ayuda para resolver problemas.</p> + +<p dir="ltr">Hay una variedad de formas de obtener ayuda, y la siguiente información son algunos consejos para hacerlo de manera más efectiva.</p> + +<h3 dir="ltr" id="Búsquedas_web_efectivas">Búsquedas web efectivas</h3> + +<p dir="ltr">Una habilidad importante para aprender es el arte de las búsquedas web efectivas — ¿qué términos de búsqueda necesitas usar en tu motor de búsqueda favorito para encontrar los artículos que necesitas?</p> + +<p dir="ltr">A menudo es bastante obvio qué buscar. Por ejemplo:</p> + +<ul dir="ltr"> + <li>Si deseas obtener más información sobre el diseño web receptivo, puedes buscar "diseño web receptivo".</li> + <li>Si deseas obtener más información sobre una característica tecnológica específica, como el elemento HTML <code><video></code>, el <code>background-color</code> o las propiedades <code>opacity</code> de CSS, o el método <code>Date.setTime()</code> de JavaScript, debes buscar el nombre de la característica.</li> + <li>Si estás buscando información más específica, puedes agregar otras palabras clave como modificadores, por ejemplo, "atributo de reproducción automática de elementos <video>" o "Parámetros Date.setTime".</li> +</ul> + +<p dir="ltr">Si deseas buscar algo que tenga palabras de moda menos obvias, debes pensar en qué es más probable que te devuelva lo que deseas.</p> + +<ul dir="ltr"> + <li>Ejecuta el código después de cumplir varias promesas</li> + <li>Reproduce una transmisión de video desde una cámara web en el navegador</li> + <li>Crea un degradado lineal en el fondo de tu elemento</li> +</ul> + +<h4 id="Mensajes_de_error">Mensajes de error</h4> + +<p>Si tienes un problema con algún código y aparece un mensaje de error específico, a menudo es una buena idea copiar el mensaje de error en tu motor de búsqueda y utilizarlo como término de búsqueda. Si otras personas han tenido el mismo problema, es probable que haya algunos artículos o publicaciones de blog al respecto en lugares como MDN o Stack Overflow.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: <a href="https://stackoverflow.com/">Stack Overflow</a> es un sitio web realmente útil; básicamente es una enorme base de datos de preguntas y respuestas seleccionadas sobre diversas tecnologías y técnicas relacionadas. Probablemente encontrarás una respuesta que responda a tu pregunta. Si no, puedes hacer una pregunta y ver si alguien puede ayudarte.</p> +</div> + +<h4 id="Prueba_en_el_navegador">Prueba en el navegador</h4> + +<p dir="ltr">A menudo es una buena idea ver si tu problema está afectando a todos los navegadores, o si solo ocurre en uno o en un pequeño número de navegadores. Si solo afecta a un navegador, por ejemplo, puedes usar ese navegador para limitar la búsqueda. Las búsquedas de ejemplo podrían verse así:</p> + +<ul dir="ltr"> + <li>La reproducción de <video> no funciona en el navegador iOS.</li> + <li>Firefox no parece admitir la API de Beetlejuice.</li> +</ul> + +<h3 dir="ltr" id="Usa_MDN">Usa MDN</h3> + +<p dir="ltr">El sitio en el que ya estás tiene una gran cantidad de información disponible, tanto material de referencia para buscar la sintaxis del código como guías/tutoriales para aprender técnicas.</p> + +<p dir="ltr">Hemos proporcionado la mayoría de las respuestas a las preguntas que tendrás sobre los fundamentos del desarrollo web en esta parte de MDN. Si estás atascado, es bueno volver a leer los artículos asociados para ver si te perdiste algo.</p> + +<p dir="ltr">Si no estás seguro de qué artículo leer, intenta buscar en MDN algunas palabras clave relacionadas (como se indicó anteriormente), o intenta una búsqueda web general. Para buscar en MDN, puedes usar la funcionalidad de búsqueda incorporada del sitio o mejor aún, usar tu motor de búsqueda favorito y poner "mdn" delante del término de búsqueda, por ejemplo, "diseño web receptivo mdn" o "backgrounf-color mdn".</p> + +<h3 dir="ltr" id="Otros_recursos_en_línea">Otros recursos en línea</h3> + +<p>Ya mencionamos Stack Overflow, pero hay otros recursos en línea que pueden ayudar.</p> + +<p>Es bueno encontrar una comunidad de la que formar parte, y obtendrás mucho respeto si intentas ayudar a otros a responder sus preguntas y también a hacer las tuyas. Otros buenos ejemplos incluyen:</p> + +<ul dir="ltr"> + <li><a href="https://discourse.mozilla.org/c/mdn" rel="noopener">Discurso MDN</a></li> + <li><a href="https://www.sitepoint.com/community/" rel="noopener">Foros de Sitepoint</a></li> + <li><a href="https://www.webdeveloper.com/" rel="noopener">Foros de webdeveloper.com</a></li> +</ul> + +<p dir="ltr">Sin embargo, también tiene sentido encontrar grupos útiles en sitios de redes sociales como Twitter o Facebook. Busca grupos que discutan los temas de desarrollo web que te interesen y únete. Sigue a las personas en Twitter que sabes que son influyentes, inteligentes o simplemente parecen compartir muchos consejos útiles.</p> + +<h3 dir="ltr" id="Encuentros_físicos">Encuentros físicos</h3> + +<p dir="ltr">Por último, deberías intentar asistir a algunas reuniones físicas para conocer a otras personas de ideas afines, especialmente aquellas que atienden a principiantes. <a href="https://www.meetup.com/find/tech/" rel="noopener">meetup.com</a> es un buen lugar para encontrar reuniones físicas locales, y también puedes probar tu prensa local o lo que hay en los sitios.</p> + +<p dir="ltr">También puedes intentar asistir a conferencias web completas. Si bien estas pueden ser costosas, puedes intentar ofrecerte como voluntario con ellos, y muchas conferencias ofrecen boletos de tarifa reducida, por ejemplo, boletos de estudiante o diversidad.</p> + +<h2 dir="ltr" id="Ve_también">Ve también</h2> + +<ul dir="ltr"> + <li><a href="https://www.coursera.org/learn/learning-how-to-learn" rel="noopener">Coursera: aprende a aprender</a></li> + <li><a href="https://www.freecodecamp.org/" rel="noopener">Freecodecamp</a></li> + <li><a href="https://www.codecademy.com/" rel="noopener">Codecademy</a></li> +</ul> diff --git a/files/es/learn/codificacion-scripting/index.html b/files/es/learn/codificacion-scripting/index.html new file mode 100644 index 0000000000..50c3065d4a --- /dev/null +++ b/files/es/learn/codificacion-scripting/index.html @@ -0,0 +1,10 @@ +--- +title: Codificación-Scripting +slug: Learn/codificacion-scripting +tags: + - Codificación + - Principiante + - Scripting +translation_of: Learn +--- +<p>REDIRIGE <a href="/es/docs/Learn">Aprende</a></p> diff --git a/files/es/learn/common_questions/cuanto_cuesta/index.html b/files/es/learn/common_questions/cuanto_cuesta/index.html new file mode 100644 index 0000000000..aeffd72c64 --- /dev/null +++ b/files/es/learn/common_questions/cuanto_cuesta/index.html @@ -0,0 +1,162 @@ +--- +title: ¿Cuánto cuesta hacer algo en la Web? +slug: Learn/Common_questions/Cuanto_cuesta +tags: + - Comenzando + - Herramientas de desarrollo web + - Principiante + - alojamiento + - costo + - hosting +translation_of: Learn/Common_questions/How_much_does_it_cost +--- +<div class="summary"> +<p>Dedicarse a la web no es tan barato como parece. En este artículo discutimos cuánto puedes tener que gastar, y por qué.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Deberías ya entender <a href="/en-US/Learn/What_software_do_I_need">qué software necesitas</a>, la diferencia entre <a href="/en-US/Learn/page_vs_site_vs_server_vs_search_engine">una página web, un sitio web, etc</a>., y qué <a href="/en-US/Learn/Understanding_domain_names">es un nombre de dominio</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Examina el proceso completo para crear un sitio web y descubre cuánto te puede costar cada paso.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p><span class="seoSummary">Al lanzar un sitio web, puedes no gastar nada, o puede que el costo sea muy elevado. En este artículo discutimos acerca de cuánto cuesta todo y cómo obtienes lo que pagas (o no pagas).</span></p> + +<h2 id="Software">Software</h2> + +<h3 id="Editores_de_texto">Editores de texto</h3> + +<p>Probablemente tienes un editor de texto: tal como Notepad en Windows, Gedit en Linux, TextEdit en Mac. Le resultará más fácil escribir código si elige un editor que coloree el código, chequee la sintaxis y te ayude a mantener la estructura del programa. </p> + +<p>Muchos editores son gratis, por ejemplo <a href="https://atom.io/">Atom</a>, <a href="http://brackets.io/">Brackets</a>, <a href="http://bluefish.openoffice.nl/">Bluefish</a>, <a href="http://www.barebones.com/products/textwrangler/">TextWrangler</a>, <a href="http://eclipse.org/">Eclipse</a>, y <a href="https://netbeans.org/">Netbeans</a>. Algunos, como <a href="http://www.sublimetext.com/">Sublime Text</a>, los puedes probar tanto como quieras, pero se te anima a pagar. Otros, como <a href="https://www.jetbrains.com/phpstorm/">PhpStorm</a>, pueden costar entre unas pocas docenas y 200 dólares, en dependencia del plan que pague. Algunos de ellos, como <a href="http://www.visualstudio.com/">Microsoft Visual Studio</a>, pueden costar cientos o miles de dólares; aunque Visual Studio Express is gratis para desarrolladores individuales o proyectos de código abierto. A menudo, los editores pagados tienen una versión de prueba.</p> + +<p>Para comenzar, le segerimos probar con diferentes editores, para tener un indicio de cuál trabaja mejor para ti. Si está solamente escribiendo código simple de {{Glossary("HTML")}}, {{Glossary("CSS")}}, and {{Glossary("Javascript")}}, utilice un editor sencillo.</p> + +<p>El el precio no refleja de manera confiable la calidad o utilidad de un editor de texto. Tienes que probarlo por ti mismo y decidir si se ajusta a tus necesidades. Por ejemplo, Sublime Text es barato, pero tiene muhos plugins gratis que pueden extender su funcionalidad. </p> + +<h3 id="Editores_de_imágenes">Editores de imágenes</h3> + +<p>Tu sistema incluye seguramente un simple editor de imágenes, o visor: Paint en Windows, Eye of Gnome en Ubuntu, Preview en Mac. Estos programas son relativamente limitados, pronto gustarás tener un editor más potente para añadir capas, efectos y agrupamiento de imágenes.</p> + +<p>Los editores pueden ser gratis (<a href="http://www.gimp.org/">GIMP</a>, <a href="https://www.getpaint.net/">Paint.NET</a>), de costo moderado (<a href="http://www.paintshoppro.com/">PaintShop Pro</a>, menos de $100), o cientos de dólares (<a href="https://www.adobe.com/products/photoshop.html">Adobe Photoshop</a>).</p> + +<p>Puedes usar cualquiera de ellos, ya que tienen funciones similares, aunque algunos son tan completos que nunca vas a utilizar cada característica. Si en algún punto necesitas intercambiar proyectos con otros diseñadores, deberías descubrir qué herramientas utilizan. Los editores pueden exportar los proyectos finalizados a formatos de archivo estándares, pero cada editor guarda los proyectos actuales en su formato especializado. La mayoría de las imágenes en Internet están protegidas por los derechos de autor, por lo que es mejor chequear la licencia del aechivo antes de utilizarlo. Sitios como <a href="https://pixabay.com/">Pixabay</a> proporcionan imágenes bajo la licencia CC0, así que la puedes usar, editar y publicar incluso con modificaciones para uso comercial.</p> + +<h3 id="Editores_de_medios">Editores de medios</h3> + +<p>Si desea incluir video o audio en su sitio web, puede incrustar servicios online (por ejemplo YouTube, Vimeo, or Dailymotion), o incluir sus propios videos (ver más abajo los costos de ancho de banda).</p> + +<p>Para archivos de audio, puede encontrar software gratuito(<a href="http://audacity.sourceforge.net/?lang=en">Audacity</a>, <a href="http://www.wavosaur.com/">Wavosaur</a>), o pagar hasta unos poco cientos de dólares (<a href="http://www.sonycreativesoftware.com/soundforge">Sony Sound Forge</a>, <a href="http://www.adobe.com/products/audition.html">Adobe Audition</a>). Sin embargo, el software de edición de vídeo puede ser gratis (<a href="http://www.pitivi.org/">PiTiVi</a>, <a href="http://www.openshot.org/">OpenShot</a> for Linux, <a href="https://www.apple.com/mac/imovie/">iMovie</a> for Mac), menos de $100 (<a href="https://www.adobe.com/us/products/premiere-elements.html">Adobe Premiere Elements</a>), o varios cientos de dólares (<a href="https://www.adobe.com/products/premiere.html">Adobe Premiere Pro</a>, <a href="http://www.avid.com/US/products/family/Media-Composer">Avid Media Composer</a>, <a href="https://www.apple.com/final-cut-pro/">Final Cut Pro</a>). El software recibido con tu cámara digital puede cubrir todas tus necesidades.</p> + +<h3 id="Herramientas_de_publicación">Herramientas de publicación</h3> + +<p>Además necesitas una forma de subir archivos: desde tu disco duro a un servidor web distante. Para hacer esto deberías utilizar una herramienta de publicación tal como un cliente (S)<a href="/en-US/docs/Glossary/FTP">FTP</a>, <a href="https://en.wikipedia.org/wiki/Rsync">RSync</a>, o <a href="https://help.github.com/articles/using-a-custom-domain-with-github-pages/">Git/GitHub</a>.</p> + +<p>Cada sistema operativo incluye un cliente (S)FTP, como parte de su administrador de archivos. Windows Explorer, Nautilus (un administrador de archivos común en Linux), y Mac Finder inclueyen todos esta funcionalidad. Sin embargo, las personas a menudo seleccionan clientes (S)FTP dedicados a mostrar directorios locales y remotos y almacenar contraseñas de servidor.</p> + +<p>Si desea instalar un cliente (S)FTP, existen varias opciones seguras y gratuitas: por ejemplo, <a href="https://filezilla-project.org/">FileZilla</a> para todas las plataformas, <a href="http://winscp.net/">WinSCP</a> para Windows, <a href="https://cyberduck.io/">Cyberduck</a> para Mac o Windows, <a href="https://en.wikipedia.org/wiki/List_of_FTP_server_software">y otros más</a>.</p> + +<p>Debido a que el protocolo FTP es inseguro, deberías asegurarte de utilizar SFTP — la versión segura, encriptada de FTP que la mayoría de los sitios de alojamiento (en inglés <em>hosting</em>) actuales ofrecen por defecto— u otra solución segura como Rsync sobre SSH.</p> + +<h2 id="Navegadores">Navegadores</h2> + +<p>Ya debes tener un navegador o puedes conseguirlo gratuito. Si lo necesitas, descarga Firefox <a href="https://www.mozilla.org/en-US/firefox/all/">aquí</a> o Google Chrome <a href="https://www.google.com/chrome/browser/">aquí</a>.</p> + +<h2 id="Acceso_a_la_web">Acceso a la web</h2> + +<h3 id="Computadora_módem">Computadora / módem</h3> + +<p>Necesitas una computadora. El costo puede variar mucho, en dependencia de tu presupuesto, y dónde vivas. Para publicar un sitio web básico, sólo necesitas una computadora básica capaz de ejecutar, por lo que el nivel de entrada puede ser bastante bajo. </p> + +<p>Por supuesto, necesitarás una computadora más formal si quieres producir diseños complicados, retocar fotos, o producir archivos de audio y vídeo. </p> + +<p>Necesitas subir contenido a un servidor remoto (ver <em>Alojamiento</em> más abajo), por lo que necesitas un módem.Tu proveedor {{Glossary("ISP")}} puede venderte la conexión a internet por unos pocos dólares al mes, aunque tu presupuesto pudiera variar, en dependencia de tu localización.</p> + +<h3 id="Acceso_del_Proveedor_ISP">Acceso del Proveedor ISP</h3> + +<p>Asegúrese de contar con suficiente {{Glossary("Ancho de banda", "ancho de banda")}}:</p> + +<ul> + <li>El acceso de ancho de banda bajo puede ser adecuado para soportar un sitio web simple: imágenes reducidas, textos, algunos archivos CSS y JavaScript. Esto probablemente te cueste unas pocas docenas de dólares, incluyendo la renta del módem.</li> + <li>De otra manera, necesitarás un ancho de banda superior, tal como acceso por DSL, cable, o fibra, si desea un sitio web más avanzado con cientos de archivos o quiere entregar archivos pesados de vídeo/audio directamente desde tu servidor. Te pudiera costar lo mismo que el acceso de ancho de banda bajo, hasta varios cientos de dólares mensuales para necesidades más profesionales. </li> +</ul> + +<h2 id="Alojamiento">Alojamiento</h2> + +<h3 id="Entendiendo_el_ancho_de_banda">Entendiendo el ancho de banda</h3> + +<p>Los proveedores de alojamiento te cobran de acuerdo a cuánto {{Glossary("Ancho de banda", "ancho de banda")}} consume tu sitio web. . Esto depende de cuántas personaas, y robots de rastreo Web, accedan a tu contenido durante un tiempo dado, y cuánto espacio en el servidor tu contenido ocupa. Esta es la razón por la cual las personas usualmente almacenan sus videos en servicios dedicadostales como Youtube, Dailymotion, y Vimeo. Por ejemplo, tu proveedor puede tener un plan que incluye hasta varios miles de visitantes por díam por un uso “razonable”. Sea cuidadoso, puesto que puede variar mucho de un servidor de alojamiento a otro. Como regla de oro, reconozca que el servicio de alojamiento confiable, pagado y personal puede costar alrededor de 10 a 15 dólares al mes. </p> + +<div class="note"> +<p>Note que que no existe el ancho de banda “ilimitado”. Si consumes una enorme cantidad de ancho de banda, espere pagar una enorme cantidad de dinero.</p> +</div> + +<h3 id="Nombre_de_dominio">Nombre de dominio</h3> + +<p>Su nombre de dominio tiene que ser comprado a través de un proveedor de nombres (un registrador). Tu proveedor de alojamiento puede además ser un registrador (por ejemplo <a href="https://www.1and1.com/">1&1</a> y <a href="https://www.gandi.net/?lang=en">Gandi</a> son al mismo tiempo registradores y proveedores de alojamiento). El nombre de dominio usualmente cuesta $5-15 por año. Este costo varía en dependencia de:</p> + +<ul> + <li>Obligaciones locales: algunos nombres de dominio de primer nivel pertenecientes a países son más costosos, ya que diferentes países establecen precios diferentes.</li> + <li>Servicios asociados con un nombre de dominio: algunos registradores proveen protección contra spam ocultando tu dirección postal y corre electrónico detrás de sus propias direcciones: la dirección postal puede ser proveída a cargo del registrador y tu dirección de correo puede ser ocultada detrás del alias de tu registrador. </li> +</ul> + +<h3 id="Alojamiento_de_aficionados_vs._Alojamiento_“empaquetado”">Alojamiento de aficionados vs. Alojamiento “empaquetado”</h3> + +<p>Cuando deseas publicar un sitio web, puedes hacer todo por ti mismo: preparar una base de datos (si es necesaria), Sistema de Gestión de Contenidos, or {{Glossary("CMS")}} (como <a href="http://wordpress.org/">Wordpress</a>, <a href="http://dotclear.org/">Dotclear</a>, <a href="http://www.spip.net/en_rubrique25.html">spip</a>, etc.), subir tus propias plantillas o contenido preeditado.</p> + +<p>Pudieras utilizar el entorno de tu proveedor de alojamiento, por aproximadamente de 10 a 15 dólares al mes, o suscribirse directamente a un servicio de alojamiento con CMS pre-empaquetado (por ejemplo, <a href="http://wordpress.com/">Wordpress</a>, <a href="https://www.tumblr.com/">Tumblr</a>, <a href="https://www.blogger.com/">Blogger</a>). Para esta última no tienes que pagar nada, pero puedes tener menos control sobre las plantillas y otras opciones. </p> + +<h3 id="Alojamiento_gratuito_vs._alojamiento_pagado">Alojamiento gratuito vs. alojamiento pagado</h3> + +<p>Te pudieras preguntar, ¿por qué pago por mi alojamiento cuando existen tantos servicios gratuitos?</p> + +<ul> + <li>Tienes más libertad cuando pagas. Tu sitio web es tuyo, y puedes trasladarlo a la perfección de un proveedor de alojamiento a otro.</li> + <li>Los proveedores de alojamiento gratuito puede añadir anuncios Free hosting providers may add advertising to your content, beyond your control.</li> +</ul> + +<p>Es mejor pagar el alojamiento que depender de alojamiento gratuito, ya que en la mayoría de los sitios pagados es posible trasladar tus archivos fácilmente y el tiempo de actividad está garantizado. La mayoría de los proveedores de alojamiento te dan un gran descuento para comenzar. </p> + +<p>Algunas personan optan por un enfoque mixto. Por ejemplo, su blog principal en un sitio pagado con un nombre de dominio completo, y a su vez contenido espóntaneo, menos estratégico en un servicio de alojamiento gratuito.</p> + +<h2 id="Agencias_y_alojamiento_de_sitios_web_profesionales">Agencias y alojamiento de sitios web profesionales</h2> + +<p>Si desea un sitio web profesional, probablemente le pedirás a una agencia web que lo haga por ti.<br> + <br> + Aquí, los costos dependen de múltiples factores, tales como: </p> + +<ul> + <li>¿Es este un sitio web sencillo con unas pocas páginas de texto? ¿O un sitio web más complejo con miles de extensas páginas?</li> + <li>¿Quieres actualizarlo de manera regular? ¿O será un sitio web estático?</li> + <li>¿Tu sitio web debe conectarse a tu compañía para obtener el contenido (es decir, datos internos)?</li> + <li>¿Quieres algunas características fanstásticas de las más usadas del momento? En el momento que se escribió este artículo, los clientes buscan sitios de página única con complicados paralajes (React).</li> + <li>¿Necesitarás que la agencia cree historias de usuarios o resuelva complejos problemas {{Glossary("UX")}}? Por ejemplo, crear una estrategia que atraiga usuarios, o pruebas A/B para seleccionar una solución entre diferentes ideas. </li> +</ul> + +<p>...y para alojamiento:</p> + +<ul> + <li>¿Quieres servidores adicionales, en caso de que tu servidor se caiga?</li> + <li>¿Es 95% porciento adecuada la fiabilidad, o necesitas servicio profesional las 24 horas?</li> + <li>¿Quiere un gran perfil, servidores dedicados ultra-responsivos, o puede trabajar con una máquina más lenta compartida?</li> +</ul> + +<p>En dependencia de cómo responda estas preguntas, su sitio pudiera costar miles hasta cientos de miles de dólares.</p> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<p>Ahora que entiende que cantidad de dinero su sitio puede costarle, es tiempo de comenzar a diseñar un sitio web y <a href="/en-US/docs/Learn/Set_up_a_basic_working_environment">preparar su entorno de trabajo</a>.</p> + +<ul> + <li>Lea sobre <a href="/en-US/docs/Learn/Choose,_Install_and_set_up_a_text_editor">cómo seleccionar e instalar un editor de texto</a>.</li> + <li>SI está más enfocado en diseño, eche una mirada a la <a href="/en-US/Learn/Anatomy_of_a_web_page">anatomía de una página web</a>.</li> +</ul> diff --git a/files/es/learn/common_questions/diseños_web_comunes/index.html b/files/es/learn/common_questions/diseños_web_comunes/index.html new file mode 100644 index 0000000000..7e05cbcaad --- /dev/null +++ b/files/es/learn/common_questions/diseños_web_comunes/index.html @@ -0,0 +1,115 @@ +--- +title: ¿Qué contienen los diseños web comunes? +slug: Learn/Common_questions/diseños_web_comunes +tags: + - CSS + - Común + - Diseño + - Diseño Común + - HTML + - Principiante +translation_of: Learn/Common_questions/Common_web_layouts +--- +<div>{{IncludeSubnav("/en-US/Learn")}}</div> + +<div class="summary"> +<p>Cuando diseña páginas para su sitio web es bueno tener una idea de los diseños más comunes.</p> +</div> + +<table class="learn-box nostripe standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Asegúrese que usted ya ha pensado sobre <a href="/es/docs/Learn/Common_questions/Thinking_before_coding">lo que quiere lograr</a> con su proyecto web.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender dónde colocar las cosas en sus páginas web, y cómo hacerlo. </td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p>Existe una razón para que hablemos sobre diseño web. Se comienza con una página en blanco, y se pueden tomar muchas direcciones. Si no tienes mucha experiencia, comenzar con una página en blanco pudiera ser un poco temible. Nosotros tenemos alrededor de 25 años de experiencia y te daremos algunas reglas básicas para ayudarte a diseñar tu sitio. </p> + +<p>Aún ahora con el nuevo enfoque de la web para móviles, la mayoría de las páginas web principales son construídas a partir de las siguientes partes:</p> + +<dl> + <dt>Encabezado</dt> + <dd>Visible en la parte superior de cada página de un sitio. Contiene información relevante para todas las páginas (como el nombre del sitio o el logo) y un sistema de navegación fácil de usar.</dd> + <dt>Contenido principal</dt> + <dd>Es el área más grande, contiene contenido único para la página actual.</dd> + <dt>Contenido secundario</dt> + <dd>1) Información complementaria del contenido principal; 2) información compartida entre un subconjunto de páginas; 3) sistema de navegación alternativo. De hecho, todo lo que no es absolutamente requerido por el contenido de la página principal. </dd> + <dt>Pie de página</dt> + <dd>Visible en la parte inferior de cada página de un sitio. Análogamente al encabezado contiene información global, en este caso menos llamativa como avisos legales o información de contacto.</dd> +</dl> + +<p>Estos elementos son bastante comunes en todos los factores de forma, pero pueden ser dispuestos de diferentes maneras. Aquí se presentan algunos ejemplos (<strong>1 </strong>representa encabezado, <strong>2 </strong>pie de página; <strong>A </strong>contenido principal; <strong>B1, B2 </strong>barras laterales):</p> + +<p><strong>Diseño de una columna.</strong> Especialmente importante para navegadores de móviles de modo que no se llene la pequeña pantalla.</p> + +<p><img alt="Example of a 1 column layout: Main on top and asides stacked beneath it." src="https://mdn.mozillademos.org/files/9501/1-col-layout.png" style="height: 100px; width: 160px;"></p> + +<p><strong>Diseño de dos columnas.</strong> A menudo utilizado para tabletas, ya que tienen pantallas de tamaño medio.</p> + +<p> <img alt="Example of a basic 2 column layout: One aside on the left column, and main on the right column." src="https://mdn.mozillademos.org/files/9499/2-col-layout-right.png" style="height: 100px; width: 160px;"> <img alt="Example of a basic 2 column layout: One aside on the right column, and main on the left column." src="https://mdn.mozillademos.org/files/9497/2-col-layout-left.png" style="height: 100px; width: 160px;"></p> + +<p><strong>Diseños de tres columnas</strong>. Solamene adecuado para escritorios con pantallas grandes. (Incluso muchos usuarios de escritorio prefieren ver cosas en pequeñas ventanas que en pantalla completa.)</p> + +<p><img alt="Example of a basic 3 column layout: Aside on the left and right column, Main on the middle column." src="https://mdn.mozillademos.org/files/9491/3-col-layout.png" style="height: 100px; width: 160px;"> <img alt="Another example of a 3 column layout: Aside side by side on the left, Main on the right column." src="https://mdn.mozillademos.org/files/9493/3-col-layout-alt.png" style="height: 100px; width: 160px;"> <img alt="Another example of a 3 column layout: Aside side by side on the right, Main on the left column." src="https://mdn.mozillademos.org/files/9495/3-col-layout-alt2.png" style="height: 100px; width: 160px;"></p> + +<p>La verdadera diversión comienza cuando empiezas a mezclarlos todos juntos.</p> + +<p><img alt="Example of mixed layout: Main on top and asides beneath it side by side." src="https://mdn.mozillademos.org/files/9503/1-col-layout-alt.png" style="height: 100px; width: 160px;"> <img alt="Example of a mixed layout: Main on the left column and asides stack on top of each other on the right column" src="https://mdn.mozillademos.org/files/9505/2-col-layout-left-alt.png" style="height: 100px; width: 160px;"> <img alt="Example of a mixed layout: one aside on the left column and main in the right column with a aside beneath main." src="https://mdn.mozillademos.org/files/9507/2-col-layout-mix.png" style="height: 100px; width: 160px;"> <img alt="Example of a mixed layout: Main on the left of the first row and one aside on the right of that same row, a second aside convering the whole second row." src="https://mdn.mozillademos.org/files/9509/2-col-layout-mix-alt.png" style="height: 100px; width: 160px;">…</p> + +<p>Estos son solo ejemplos y eres bastante libre de diseñar las cosas como quieras. Puedes notar que mientras el contenido se puede mover alrededor de la pantalla, siempre se mantiene el encabezado (1) en la parte superior y el pie de página (2) en la parte inferior. Además, el contenido principal (A) es lo más importante, así que dale la mayor parte del espacio. </p> + +<p>Estas son reglas del juego que puedes aprovechar. Desde luego, existen diseños complejos y excepciones. En otros artículos discutiremos cómo diseñar sitios responsivos (sitios que cambian en dependencia del tamaño de la pantalla) y sitios cuyos diseños varían entre las páginas. Por ahora, es mejor mantener tu diseño consistente en todo tu sitio. </p> + +<h2 id="Aprendizaje_activo">Aprendizaje activo</h2> + +<p><em>Aún no hay aprendizaje activo disponible. <a href="/en-US/docs/MDN/Getting_started">Por favor, considere contribuir</a>.</em></p> + +<h2 id="Profundización">Profundización</h2> + +<p>Estudiemos algunos ejemplos más concretos tomados de sitios web bien conocidos. </p> + +<h3 id="Diseño_de_una_columna">Diseño de una columna</h3> + +<p><strong><a href="http://www.invisionapp.com/" rel="external">Aplicación de Invision</a></strong>. Un diseño típico de una columna proporcionando toda la información linealmente en una sola página. </p> + +<p><img alt="Example of a 1 column layout in the wild" src="https://mdn.mozillademos.org/files/9523/screenshot-product.jpg" style="height: 643px; width: 200px;"> <img alt="1 column layout with header, main content, a stack of aside contents and a footer" src="https://mdn.mozillademos.org/files/9525/screenshot-product-overlay.jpg" style="height: 643px; width: 200px;"></p> + +<p>Bastante sencillo. Sólo recuerda que muchas personas navegarán por tu sitio desde escritorios, así que haz tu contenido también utilizable allí.</p> + +<h3 id="Diseño_de_dos_columnas.">Diseño de dos columnas.</h3> + +<p><strong><a href="http://abduzeedo.com/typography-mania-261" rel="external">Abduzeedo</a></strong>, un simple diseño de blog. Los blogs usualmente tienen dos columnas, una para el contenido principal que es más ancha y otra más estrecha para el contenido secundario (como widgets, niveles de navegación secundarios y anuncios). </p> + +<p><img alt="Example of a 2 column layout for a blog" src="https://mdn.mozillademos.org/files/9527/screenshot-blog.jpg" style="height: 643px; width: 200px;"> <img alt="A 2 column layout with the main content on the left column" src="https://mdn.mozillademos.org/files/9529/screenshot-blog-overlay.jpg" style="height: 643px; width: 200px;"></p> + +<p>En este ejemplo, mira la imagen (B1) justo debajo del encabezado. Está relacionada con el contenido principal, pero el contenido principal tiene sentido sin esta, de este modo pudieras pensar que la imagen forma parte del contenido principal o del lateral. En realidad no importa. Lo que importa es que si pones algo justo debajo del encabezado, debería ser parte del contenido principal o estar directamente relacionado con este. </p> + +<h3 id="Es_una_trampa">Es una trampa</h3> + +<p><strong><a href="http://www.mica.edu/About_MICA.html" rel="external">MICA</a></strong>. Este es un poco más complicado. Parece un diseño de tres columnas...</p> + +<p><img alt="Example of a false 3 columns layout" src="https://mdn.mozillademos.org/files/9531/screenshot-education.jpg" style="height: 267px; width: 200px;"> <img alt="It looks like a 3 columns layout but actually, the aside content is floating around." src="https://mdn.mozillademos.org/files/9533/screenshot-education-overlay.jpg" style="height: 267px; width: 200px;"></p> + +<p>...pero no lo es. B1 y B2 flotan alrededor del contenido principal. Recuerda esa palabra "float"--te acordarás cuando empieces a aprender sobre {{Glossary("CSS")}}.</p> + +<p>¿Por qué pensarías que es un diseño de tres columnas? Porque la imagen en la parte superior derecha está en forma de L, porque B1 parece una columna sosteniendo el conenido principal desplazado, y porque la "M" y la "I" del logo MICA crean una línea de fuerza vertical.</p> + +<p>Este es un buen ejemplo de diseño clásico que admite cierta creatividad. Los diseños simples son más fáciles de implementar, pero deje espacio expresar su creatividad en el área.</p> + +<h3 id="Un_diseño_mucho_más_complicado">Un diseño mucho más complicado</h3> + +<p><strong>La <a href="https://www.operadeparis.fr/en/saison-2014-2015/opera/la-boheme-puccini" rel="external">Opera de Paris</a>.</strong></p> + +<p><img alt="An example of a tricky layout." src="https://mdn.mozillademos.org/files/9535/screenshot-opera.jpg" style="height: 424px; width: 200px;"> <img alt="This is a 2 column layout but the header is overlaping the main content." src="https://mdn.mozillademos.org/files/9537/screenshot-opera-overlay.jpg" style="height: 424px; width: 200px;"></p> + +<p>Básicamente un diseño de dos columnas, pero notarás muchos ajustes por aquí y por allá que rompen visualmente el diseño. Especialmente, el encabezado se superposiciona a la imagen del contenido principal. La manera en que la curva del menú del encabezado se une con la curva en el fondo de la imagen, hacen que el encabezado y el contenido principal parezcan un solo componente a pesar de que son técnicamente completamente distintos. </p> + +<p>Como ves, puedes crear maravillosos sitios web incluso sólo con diseños básicos. Échale una mirada a tus propios sitos web favoritos y pregúntate a ti mismo, ¿dónde está el encabezado, el pie de página, el contenido principal y el contenido secundario? Esto te inspirará para tu propio diseño y te dará buenas pistas sobre para cuáles diseños funciona y para cuáles no. </p> diff --git a/files/es/learn/common_questions/how_does_the_internet_work/index.html b/files/es/learn/common_questions/how_does_the_internet_work/index.html new file mode 100644 index 0000000000..238ea2e5ae --- /dev/null +++ b/files/es/learn/common_questions/how_does_the_internet_work/index.html @@ -0,0 +1,99 @@ +--- +title: ¿Cómo funciona Internet? +slug: Learn/Common_questions/How_does_the_Internet_work +tags: + - Internet + - Principiante + - Tutorial + - Web +translation_of: Learn/Common_questions/How_does_the_Internet_work +--- +<div class="summary"> +<p>En este artículo se describe lo que es Internet y cómo funciona.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Ninguno, pero te animamos a leer el <a href="/en-US/docs/Learn/Thinking_before_coding">Artículo sobre el establecimiento de metas</a> primero.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprenderás lo básico de infraestructura técnica de la web y la diferencia entre Internet y Web.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p><strong>Internet</strong> es la columna vertebral de la Web, la infraestructura técnica que la hace posible. En lo más básico, Internet es una gran red de computadoras que se comunican simultáneamente.</p> + +<p><a href="http://en.wikipedia.org/wiki/Internet#History" rel="external">La historia de internet es algo oscura</a>. Comenzó en la década de 1960 como un proyecto de investigación financiado por el ejercito de los EE.UU, y luego se convirtió en una infraestructura pública en la década de 1980 con el apoyo de muchas universidades públicas y empresas privadas. Las distintas tecnologías que soporta internet han evolucionado con el tiempo, pero la forma en que funciona no ha cambiado mucho: Internet es una forma de conectar las computadoras entre sí y asegurar que, pase lo que pase, encuentren una manera de mantenerse conectadas.</p> + +<h2 id="Aprendizaje_activo">Aprendizaje activo</h2> + +<ul> + <li><a href="https://www.youtube.com/watch?v=7_LPdttKXPc" rel="external">Cómo funciona internet explicado en 5 minutos</a>: Un vídeo de 5 minutos para entender los fundamentos de internet por Aaron Titus.</li> + <li><a href="https://www.youtube.com/watch?v=x3c1ih2NJEg">¿Cómo funciona Internet? </a>Video detallado de 8 minutos de visualización.</li> +</ul> + +<h2 id="Profundizar">Profundizar</h2> + +<h3 id="Una_simple_red">Una simple red</h3> + +<p>Cuando dos ordenadores necesitan comunicarse, tienes que vincularlos, ya sea físicamente (por lo general con un <a href="http://en.wikipedia.org/wiki/Ethernet_crossover_cable" rel="external">cable de Ethernet</a>) o de forma inalámbrica (por ejemplo por <a href="http://en.wikipedia.org/wiki/WiFi" rel="external">WiFi</a> o sistema de <a href="http://en.wikipedia.org/wiki/Bluetooth" rel="external">Bluetooth</a>). Todos los ordenadores modernos pueden soportar cualquiera de este tipo de conexiones.</p> + +<div class="note"> +<p><strong>Nota:</strong> En el resto de este artículo, sólo nos referiremos al uso de cables físicos, pero es igualmente aplicable a las redes inalámbricas.</p> +</div> + +<p><img alt="Dos computadoras conectadas entre sí" src="https://mdn.mozillademos.org/files/8441/internet-schema-1.png" style="height: 152px; width: 600px;"></p> + +<p>La red no se limita a dos ordenadores, se pueden conectar tantos como se deseen aunque siendo más complicado cada vez. Por ejemplo, para conectar diez ordenadores, se necesitarían 45 cables y unos nueve conectores por ordenador!</p> + +<p><img alt="Diez ordenadores interconectados" src="https://mdn.mozillademos.org/files/8443/internet-schema-2.png"></p> + +<p>Para resolver este problema, cada ordenador en una red está conectado a una pequeña computadora especial llamada enrutador o router (en inglés). Este enrutador cumple una función: tal como hace un señalizador en una estación de tren, el router se encarga de asegurar que el mensaje enviado desde un ordenador emisor llegue al destino correcto. Para que el ordenador B reciba un mensaje desde el ordenador A, este debe enviarlo primero al router, quien a su vez lo remite al ordenador B asegurándose que dicho mensaje no sea entregado a otro ordenador C.</p> + +<p>Una vez que agregamos un enrutador al sistema, nuestra red de 10 ordenadores solo requiere 10 cables: un enchufe para cada ordenador y un enrutador con 10 enchufes.</p> + +<p><img alt="Diez ordenadores con un router" src="https://mdn.mozillademos.org/files/8445/internet-schema-3.png" style="height: 576px; width: 600px;"></p> + +<h3 id="Una_red_de_redes">Una red de redes</h3> + +<p>Hasta aquí todo es más o menos simple, pero ¿qué sucede al conectar cientos, miles, millones de ordenadores entre sí?. Por supuesto un solo <em>enrutador</em> no puede escalar tanto, pero, si lees cuidadosamente, dijimos que un <em>enrutador</em> es como un pequeño ordenador, entonces ¿qué nos impide conectar dos <em>enrutadores </em>a la vez?. Nada: hagámoslo.</p> + +<p><img alt="Dos routers conectados entre sí" src="https://mdn.mozillademos.org/files/8447/internet-schema-4.png"></p> + +<p>Conectando ordenadores a enrutadores y luego enrutadores entre sí, podemos escalar infinitamente.</p> + +<p><img alt="Routers interconectados" src="https://mdn.mozillademos.org/files/8449/internet-schema-5.png" style="height: 563px; width: 600px;"></p> + +<p>Una red así se acerca mucho a lo que llamamos Internet, pero hay algo que nos falta. Construimos esa red para nuestros propios propósitos. Hay otras redes ahí fuera: tus amigos, tus vecinos, cualquiera puede tener su propia red de ordenadores. Pero no es posible instalar cables entre tu casa y el resto del mundo, así que ¿cómo puedes manejar esto? Bueno, ya hay cables conectados a tu casa, por ejemplo, la energía eléctrica y el teléfono. La infraestructura telefónica ya conecta tu casa con cualquier persona en el mundo, así que es el cable perfecto que necesitamos. Para conectar nuestra red a la infraestructura telefónica, necesitamos un equipo especial llamado <em>modem</em>. Este <em>modem</em> convierte la información de nuestra red en información manejable por la infraestructura telefónica y viceversa.</p> + +<p><img alt="Un router conectado a un modem" src="https://mdn.mozillademos.org/files/8451/internet-schema-6.png" style="height: 340px; width: 600px;"></p> + +<p>Entonces estamos conectados a la infraestructura telefónica. El siguiente paso es enviar el mensaje desde nuestra red a la red que queremos llegar. Para lograr eso, conectaremos nuestra red a un proveedor de servicios de internet (ISP de sus siglas en inglés Internet Service Provider). Un ISP es una empresa que gestiona algunos enrutadores especiales interconectados, que también pueden acceder a enrutadores de otros ISP. Así, el mensaje de nuestra red es llevada a través de la red de redes de ISP, hasta la red de destino. Internet consiste en toda esta infraestructura de redes.</p> + +<p><img alt="stack de Internet al completo" src="https://mdn.mozillademos.org/files/8453/internet-schema-7.png" style="height: 1293px; width: 340px;"></p> + +<h3 id="Encontrando_ordenadores">Encontrando ordenadores</h3> + +<p>Si deseas enviar un mensaje a una computadora, debes especificar a cuál. Es por ello que todo ordenador conectado a una red cuenta con una dirección única que lo identifica, llamada “dirección IP” o Protocolo de Internet(IP de sus siglas en inglés <em>Internet Protocol</em>). Esta dirección está compuesta por una serie de cuatro números separados por puntos, por ejemplo: <code>192.168.2.10</code>.</p> + +<p>Para los ordenadores es un identificador simple, pero los humanos tienen mayor dificultad a la hora de recordar y memorizar este tipo de dirección. Con el propósito de convertir esta serie numérica en algo que podamos asociar con mayor facilidad a la dirección IP se utiliza lo que conocemos como <em>nombre de dominio</em>. Por ejemplo, <code>google.com </code>es el nombre de dominio utilizado para sustituir la dirección IP <code>173.194.121.32</code>. Así, usar un nombre de dominio es la manera más fácil para nosotros de identificar un ordenador a través de Internet.</p> + +<p><img alt="Mostrar cómo un nombre de dominio sirve como alias a una dirección IP" src="https://mdn.mozillademos.org/files/8405/dns-ip.png" style="height: 160px; width: 330px;"></p> + +<h3 id="Internet_y_la_web">Internet y la web</h3> + +<p>Como puedes notar, cuando navegamos por la web con un navegador, normalmente utilizamos el nombre de dominio para llegar a un sitio web. ¿Significa eso que Internet y la Web son la misma cosa? No es tan simple. Como vimos, Internet es una infraestructura técnica que permite que miles de millones de ordenadores estén conectadas entre sí. Algunos de estos ordenadores, llamados <em>servidores web</em> son capaces de enviar mensajes inteligibles a los navegadores. Por tanto <em>Internet </em>es una infraestructura, mientras que la <em>Web</em> es un servicio construido sobre dicha infraestructura. Cabe señalar que existen otros servicios soportados por Internet, como es el correo electrónico e {{Glossary("IRC")}}.</p> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<ul> + <li><a href="/en-US/Learn/Getting_started_with_the_web/How_the_Web_works">Cómo funciona la Web.</a></li> + <li><a href="/en-US/docs/Learn/page_vs_site_vs_server_vs_search_engine">Comprender la diferencia entre una página web, un sitio web, un servidor web y un motor de búsqueda.</a></li> + <li><a href="/en-US/docs/Learn/Understanding_domain_names">La comprensión de los nombres de dominio.</a></li> +</ul> diff --git a/files/es/learn/common_questions/index.html b/files/es/learn/common_questions/index.html new file mode 100644 index 0000000000..4dcdd63447 --- /dev/null +++ b/files/es/learn/common_questions/index.html @@ -0,0 +1,145 @@ +--- +title: Preguntas frecuentes +slug: Learn/Common_questions +tags: + - CodingScripting + - Infrastructure + - Learn + - NeedsTranslation + - TopicStub + - Web + - WebMechanics +translation_of: Learn/Common_questions +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Esta sección del área de aprendizaje está diseñada para proveer respuestas a preguntas frecuentes que pueden surgir, las cuales no son necesariamente parte del núcleo estructurado de formas de aprendizaje (ej. los artículos de aprendizaje de <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML">HTML</a> o <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS">CSS</a>). Éstos artículos están diseñados para trabajar por su cuenta.</p> + +<h2 id="Cómo_funciona_la_Web">Cómo funciona la Web</h2> + +<p>Esta sección cubre los mecanismos de la web -preguntas relativas al conocimiento general del ecosistema de la Web y cómo funciona.</p> + +<dl> + <dt> + <h3 id="¿Cómo_funciona_la_Web"><a href="/en-US/docs/Learn/Common_questions/How_does_the_Internet_work">¿Cómo funciona la Web?</a></h3> + </dt> + <dd><strong>Internet </strong>es la columna vertebral de la Web, la infraestructura técnica que hace la Web posible. Básicamente, Internet es una gran red de ordenadores que se comunican todos entre sí. Este artículo explica cómo funciona, en un nivel básico.</dd> + <dt> + <h3 id="¿Cúal_es_la_diferencia_entre_página_web_sitio_web_servidor_web_y_motor_de_búsqueda"><a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/Pages_sites_servers_and_search_engines">¿Cúal es la diferencia entre página web, sitio web, servidor web y motor de búsqueda?</a></h3> + </dt> + <dd>En este artículo se describen varios conceptos relacionados con la web: páginas web, sitios web, servidores web y motores de búsqueda. Estos términos son confundidos habitualmente por los novatos en la Web, o son incorrectamente usados. ¡ Vamos a aprender que significa cada uno de ellos !</dd> + <dt> + <h3 id="¿Qué_es_una_URL"><a href="/en-US/docs/Learn/Common_questions/What_is_a_URL">¿Qué es una URL?</a></h3> + </dt> + <dd>Con {{Glossary("Hypertext")}} y {{Glossary("HTTP")}}, URL es uno de los conceptos clave de la Web. Es el mecanismo usado por {{Glossary("Browser","browsers")}} para recoger cualquier recurso publicado en la Web.</dd> + <dt> + <h3 id="¿Qué_es_un_nombre_de_dominio"><a href="/en-US/docs/Learn/Common_questions/What_is_a_domain_name">¿Qué es un nombre de dominio?</a></h3> + </dt> + <dd>Los nombres de dominio son una parte clave de la infraestructura de Internet. Éstos proveen direcciones entendibles por humanos para cualquier servidor web disponible en Internet.</dd> + <dt> + <h3 id="¿Qué_es_un_servidor_web"><a href="/en-US/docs/Learn/Common_questions/What_is_a_web_server">¿Qué es un servidor web?</a></h3> + </dt> + <dd>El término "servidor Web" puede referirse a hardware o software que sirve sitios web a clientes de la Web - o a ambos trabajando conjuntamente. En este artículo veremos cómo funcionan los servidores web, y por qué son importantes.</dd> + <dt> + <h3 id="¿Qué_son_los_hipervínculos"><a href="/en-US/docs/Learn/Common_questions/What_are_hyperlinks">¿Qué son los hipervínculos?</a></h3> + </dt> + <dd>En este artículo, veremos qué son los hipervínculos y por qué importan.</dd> +</dl> + +<h2 id="Herramientas_y_Organización"><strong>Herramientas y Organización</strong></h2> + +<p>Preguntas relacionadas con las herramientas/software que puedes usar para hacer páginas web.</p> + +<dl> + <dt> + <h3 id="¿Cúanto_cuesta_hacer_algo_en_la_web"><a href="/en-US/docs/Learn/Common_questions/How_much_does_it_cost">¿Cúanto cuesta hacer algo en la web?</a></h3> + </dt> + <dd>Cuando tú vas a lanzar un sitio web, no deberías malgastar nada de tus costes. En este artículo explicamos cuánto cuesta todo y qué consigues por lo que estás pagando (o no pagando).</dd> + <dt> + <h3 id="¿Qué_programas_necesito_para_crear_un_sitio_web"><a href="/en-US/docs/Learn/Common_questions/What_software_do_I_need">¿Qué programas necesito para crear un sitio web?</a></h3> + </dt> + <dd>En este artículo explicamos qué componentes software necesitas para editar, subir o ver un sitio web.</dd> + <dt> + <h3 id="¿Qué_editores_hay_disponibles"><a href="/en-US/docs/Learn/Common_questions/Available_text_editors">¿Qué editores hay disponibles?</a></h3> + </dt> + <dd>En este artículo nos centramos en algunas cosas para reflexionar cuando elegimos e instalamos un editor de texto para el desarrollo web.</dd> +</dl> + +<dl> + <dt> + <h3 id="¿Qué_son_las_herramientas_de_desarrollador_del_navegador"><a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">¿Qué son las herramientas de desarrollador del navegador?</a></h3> + </dt> + <dd>Todos los navegadores proveen un set de herramientas de desarrollo para depurar HTML, CSS y otros códigos web. Este artículo explica cómo usar las funciones básicas de herramientas de desarrollador de tu navegador.</dd> +</dl> + +<dl> + <dt> + <h3 id="¿Cómo_configuro_un_ambiente_de_trabajo_básico"><a href="/en-US/docs/Learn/Common_questions/Set_up_a_basic_working_environment">¿Cómo configuro un ambiente de trabajo básico?</a></h3> + </dt> + <dd>Cuado trabaje en un proyecto web, querrá probarlo localmente antes de mostrarlo al mundo. Alguno tipos de código requieren un servidor para probarlos, y en este artículo le mostraremos cómo configurar uno. También cubriremos cómo implementar una estructura escalable para que sus archivos se mantengan organizados, incluso cuando su proyecto crezca.</dd> + <dt> + <h3 id="¿Cómo_se_asegura_de_que_su_sitio_web_funciona_correctamente"><a href="/en-US/docs/Learn/Common_questions/Checking_that_your_web_site_is_working_properly">¿Cómo se asegura de que su sitio web funciona correctamente?</a></h3> + </dt> + <dd>Así que ha publicado su sitio web en línea, ¡muy bien! ¿Pero estás seguro de que funciona correctamente? Este artículo proporciona algunos pasos básicos para la solución de problemas.</dd> + <dt> + <h3 id="¿Cómo_se_configura_un_servidor_local_de_pruebas"><a href="/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server">¿Cómo se configura un servidor local de pruebas?</a></h3> + </dt> + <dd> + <div> + <p>Este artículo explica cómo configurar un servidor local de pruebas simple en su máquina y los conceptos básicos sobre cómo usarlo.</p> + </div> + </dd> + <dt> + <h3 id="¿Cómo_subir_archivos_a_un_servidor_web"><a href="/en-US/docs/Learn/Common_questions/Upload_files_to_a_web_server">¿Cómo subir archivos a un servidor web?</a></h3> + </dt> + <dd>Este artículo muestra cómo publicar su sitio en línea con herramientas FTP, una de las formas más comunes de obtener un sitio web en línea para que otros puedan acceder a él desde sus computadoras.</dd> + <dt> + <h3 id="¿Cómo_uso_las_páginas_de_GitHub"><a href="/en-US/docs/Learn/Common_questions/Using_GitHub_Pages">¿Cómo uso las páginas de </a><a href="/en-US/docs/Learn/Common_questions/Using_GitHub_Pages">GitHub?</a></h3> + </dt> + <dd>Este artículo proporciona una guía básica para publicar contenido utilizando la función gh-pages de GitHub.</dd> + <dt> + <h3 id="¿Cómo_alojar_tu_sitio_web_en_Google_App_Engine"><a href="/en-US/Learn/Common_questions/How_do_you_host_your_website_on_Google_App_Engine">¿Cómo alojar tu sitio web en Google App Engine?</a></h3> + </dt> + <dd>¿Buscas un lugar donde alojar tu sitio web? Aquí hay una guía paso a paso para alojar tu sitio web en Google App Engine.</dd> + <dt> + <h3 id="¿Qué_herramientas_están_disponibles_para_depurar_y_mejorar_el_rendimiento_del_sitio_web"><a href="/en-US/docs/Tools/Performance">¿Qué herramientas están disponibles para depurar y mejorar el rendimiento del sitio web?</a></h3> + </dt> + <dd>Este conjunto de artículos le muestra cómo utilizar las herramientas de desarrollo en Firefox para depurar y mejorar el rendimiento de su sitio web, utilizando las herramientas para comprobar el uso de la memoria, el árbol de nodos de JavaScript, la cantidad de nodos que se renderizan en el DOM y más.</dd> +</dl> + +<h2 id="Diseño_y_accesibilidad">Diseño y accesibilidad</h2> + +<p>Esta sección enlista preguntas relacionadas con la estética, estructura de páginas, técnicas de accesibilidad, etc.</p> + +<dl> + <dt> + <h3 id="¿Cómo_empiezo_a_diseñar_mi_sitio_web"><a href="/en-US/docs/Learn/Common_questions/Thinking_before_coding">¿Cómo empiezo a diseñar mi sitio web?</a></h3> + </dt> + <dd>Este artículo cubre el primer paso más importante de cada proyecto: definir lo que desea lograr con él.</dd> + <dt> + <h3 id="¿Qué_contienen_los_diseños_web_comunes"><a href="/en-US/docs/Learn/Common_questions/Common_web_layouts">¿Qué contienen los diseños web comunes?</a></h3> + </dt> + <dd>Al diseñar páginas para su sitio web, es bueno tener una idea de los diseños más comunes. Este artículo recorre algunos diseños web típicos, observando las partes que componen cada uno.</dd> + <dt> + <h3 id="¿Qué_es_la_accesibilidad"><a href="/en-US/docs/Learn/Common_questions/What_is_accessibility">¿Qué es la accesibilidad?</a></h3> + </dt> + <dd>Este artículo introduce los conceptos básicos detrás de la accesibilidad web.</dd> + <dt> + <h3 id="¿Cómo_podemos_diseñar_para_todo_tipo_de_usuarios"><a href="/en-US/docs/Learn/Common_questions/Design_for_all_types_of_users">¿Cómo podemos diseñar para todo tipo de usuarios?</a></h3> + </dt> + <dd>Este artículo proporciona técnicas básicas para ayudarlo a diseñar sitios web para todo tipo de usuario —la accesibilidad rápida gana y otras cosas.</dd> + <dt> + <h3 id="¿Qué_características_HTML_promueven_la_accesibilidad"><a href="/en-US/docs/Learn/Common_questions/HTML_features_for_accessibility">¿Qué características HTML promueven la accesibilidad?</a></h3> + </dt> + <dd>Este artículo describe características específicas de HTML que pueden ser utilizadas para hacer una página web más accesible para personas con diferentes discapacidades.</dd> +</dl> + +<h2 id="Preguntas_de_HTML_CSS_y_JavaScript">Preguntas de HTML, CSS y JavaScript</h2> + +<p>Para soluciones a problemas comunes de HTML/CSS/JavaScript, trata con los siguientes artículos.</p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/HTML/Howto">Usa HTML para solucionar problemas comunes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Howto">Usa CSS para solucionar problemas comunes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Howto">Usa JavaScript para solucionar problemas comunes</a></li> +</ul> diff --git a/files/es/learn/common_questions/pages_sites_servers_and_search_engines/index.html b/files/es/learn/common_questions/pages_sites_servers_and_search_engines/index.html new file mode 100644 index 0000000000..741efd415d --- /dev/null +++ b/files/es/learn/common_questions/pages_sites_servers_and_search_engines/index.html @@ -0,0 +1,119 @@ +--- +title: >- + ¿Cuál es la diferencia entre la página web, el sitio web, el servidor web y el + motor de búsqueda? +slug: Learn/Common_questions/Pages_sites_servers_and_search_engines +translation_of: Learn/Common_questions/Pages_sites_servers_and_search_engines +--- +<div class="summary"> +<p><span class="seoSummary">En este artículo describe varios conceptos referidos a la web: Páginas web, sitios web, servidores web, y motores de búsqueda. Estos términos con frecuencia son confundidos por recién llegados a la web, o son incorrectamente usados. Vamos a aprender que significa de cada uno!</span></p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Debes saber <a href="/en-US/Learn/How_the_Internet_works">¿Cómo funciona internet?</a>.</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Aprender la diferencia entre página web, un sitio web, un servidor web, y un motor de búsqueda.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p>Así como en cualquier área de conocimiento, la web viene con un montón de jerga. No te preocupes, no te abrumaremos con todo esto (tenemos un glosario por si tienes curiosidad). Sin embargo, hay un unos términos básicos que necesitas entender al principio, Ya que escuchará estas expresiones todo el tiempo mientras lee. A veces es fácil de confundir estos términos, puesto que hacen referencia a funcionalidades relacionadas pero diferentes. De hecho, a veces veras estos términos mal utilizados en las noticias y en otros lugares, por lo que llegar mezclarlos es entendible!</p> + +<p>Cubriremos estos términos y tecnologías con más detalle mientras exploramos más, pero estas definiciones rápidas serán un gran comienzo para ti:</p> + +<dl> + <dt>Página web</dt> + <dd> Un documento que se puede mostrar en un navegador web como Firefox, Google Chrome, Microsoft Internet Explorer o Edge, o Safary de Apple, A menudo también se puede denominar "páginas web" o simplemente "páginas".</dd> + <dt>Sitio web</dt> + <dd>Es una colección de páginas web que se agrupan y normalmente se conectan de varias maneras. A menudo llamado un "sitio web" o simplemente "sitio".</dd> + <dt>Servidor web</dt> + <dd>Una computadora que aloja un sitio web en Internet.</dd> + <dt>Motores de búsqueda</dt> + <dd>Un sitio web que te ayuda a encontrar páginas web, como Google, Bing o Yahoo o DuDuckGo. Normalmente se accede a los motores de búsqueda a través de un navegador web (por ejemplo, puede realizar búsquedas de motores en búsqueda directamente en la barra de direcciones de Firefox, Chrome, etc.) </dd> + <dt><br> + Veamos una analogía simple: una biblioteca pública. Esto es lo que generalmente harías al visitar una biblioteca:</dt> +</dl> + +<ol> + <li>Buscar en un índice de busqueda el título del libro que quiéres.</li> + <li>Tomar nota del número de catálogo del libro.</li> + <li>Ir a la sección particular que contiene el libro, buscár el número de catálogo del libro y obtener el libro.</li> +</ol> + +<p>Vamos a comparar la biblioteca con un servidor web:</p> + +<ul> + <li>La biblioteca es como un servidor web. Tiene varias secciones, que es similar a un servidor web que aloja varios sitios web.</li> + <li>Las diferentes secciones (ciencias, matemáticas, historia, etc.) en la biblioteca son como sitios web. Cada sección es como un sitio web único (dos secciones no contienen los mismos libros).</li> + <li>Los libros en cada sección son como páginas web. Un sitio web puede tener varias páginas web, por ejemplo, la sección de Ciencias (el sitio web) tendrá libros sobre calor, sonido, termodinámica, estadísticas, etc. (las páginas web). Las páginas web se pueden encontrar en una ubicación única (URL).</li> + <li>El índice de búsqueda es como el motor de búsqueda. Cada libro tiene su propia ubicación única en la biblioteca (dos libros no se pueden mantener en el mismo lugar) que se especifica mediante el número de catálogo.</li> +</ul> + +<dl> +</dl> + +<p><em>No esta disponible aprendizaje activo aun. <a href="https://developer.mozilla.org/en-US/docs/MDN/Getting_started">Por favor, considere la posibilidad de contribuir</a>.</em></p> + +<h2 id="Profundizando">Profundizando</h2> + +<p>Entonces, vamos a profundizar en cómo estos cuatro términos serán relacionados y por qué a veces se confunden entre sí.</p> + +<h3 id="Página_web">Página web</h3> + +<p>Una <strong>página web</strong> es un simple documento que puede ser mostrado por un {{Glossary("browser")}}. Estos documentos están escritos en lenguaje {{Glossary("HTML")}} (el que veremos en más detalle en <a href="https://developer.mozilla.org/en-US/docs/Web/HTML">otros artículos</a>). Una página web puede incluir una variedad de diferentes tipos de recursos, tales como:</p> + +<ul> + <li><em>información de estilos</em> — controlar la apariencia de una página</li> + <li><em>scripts</em> — que agrega interactividad a la página</li> + <li><em>medios</em> — imágenes, sonidos, y vídeos.</li> +</ul> + +<div class="note"> +<p><strong>Nota: </strong>los buscadores pueden mostrar otros tipos de documentos como archivos {{Glossary("PDF")}} o imágenes, pero el término <strong>página web</strong>específicamente hace referencia a documentos HTML. Por otro lado solo usamos el termino <strong>document</strong>(documento).</p> +</div> + +<p>Todas las páginas web disponibles en la red son accesibles mediante una dirección única. Para acceder a una página, simplemente escribe su direcciones en la barra de búsqueda de tu navegador:</p> + +<p style="text-align: center;"><img alt="Example of a web page address in the browser address bar" src="https://mdn.mozillademos.org/files/8529/web-page.jpg" style="height: 239px; width: 650px;"></p> + +<p>Un <em>sitio web</em> es una colección de páginas web vinculadas (más sus recursos asociados) que comparten un único nombre de dominio. Cada página web de un sitio web determinado proporciona enlaces explícitos—la mayoría del tiempo en forma de parte del texto que se puede hacer clic—que permite al usuario moverse de una página del sitio a otra.</p> + +<p>Para acceder a un sitio web, escribe su nombre su dominio en la barra de direcciones de tu buscador, y el mostrará la página principal del sitio web, o <em>homepage </em>(casualmente denominada "el home"):</p> + +<p><img alt="Example of a web site domain name in the browser address bar" src="https://mdn.mozillademos.org/files/8531/web-site.jpg" style="display: block; height: 365px; margin: 0px auto; width: 650px;"></p> + +<p><em>Página web y</em> <em>sitio web </em>son especialmente fácil de confundir cuando un <em>sitio </em>contiene una única <em>página web </em>Tales sitio son denominados <em>sitios de una sola página.</em></p> + +<h3 id="Servidor_web">Servidor web</h3> + +<p>Un <em>servidor web</em> es una computadora que aloja uno o mas <em>sitios web</em>. “Alojar” significa que todas las <em>páginas web </em> y sus archivos soportes están disponibles en esa computadora. El <em>servidor web</em> enviará cualquier <em>página web</em> desde el <em>sitio</em> que hospeda al navegador de cualquier usuario, por cada solicitud del usuario.</p> + +<p>No confundir <em>sito web</em> y <em>servidor web</em>. Por ejemplo, "Mi sitio web no responde", en realidad significa que el <em>servidor web</em> no responde y , por lo tanto, el <em>sitio web</em> no está disponible. Más importante aún, ya que un servidor web puede alojar varios sitios web, el término <em>servidor web</em> nunca se utiliza para designar un sitio, ya que podría causar un gran confusión. En nuestro ejemplo anterior, si dijimos: "Mi servidor web no responde", significa que no hay sitios web en ese servidor web disponibles.</p> + +<h3 id="Buscador">Buscador</h3> + +<p>Los buscadores son una fuente común de confusión en la web. Un buscador es un tipo especial de sitio web que ayuda a los usuarios a encontrar páginas web de sitios web.</p> + +<p>Hay muchos por ahí: <a href="https://www.google.com/">Google</a>, <a href="https://www.bing.com/">Bing</a>, <a href="https://www.yandex.com/">Yandex</a>, <a href="https://duckduckgo.com/">DuckDuckGo</a>,y muchos mas. Algunos son genéricos, otros están especializados en ciertos temas. Utilice los que prefiera.</p> + +<p>Muchos principiantes en la web confunden motores de búsqueda con navegadores. Aclaremos esto: Un <em><strong>navegador</strong></em> es una parte de software que devuelve y muestra páginas web; un <strong><em>buscador</em></strong> es un sitio web que ayuda a las personas a encontrar páginas web de otros sitios web. La confusión surge porque, la primera vez que alguien inicia un navegador, el navegador muestra la página principal del motor. Esto tiene sentido, porque, obviamente, lo primero que quieres hacer con un navegador es encontrar una página web para mostrar. No confundas la infraestructura (por ejemplo, el navegador) con el servicio (por ejemplo, el buscador). La distinción te ayudará un poco, pero incluso algunos profesionales hablan imprecisamente, así que no te sientas angustiado por eso.</p> + +<p>Aquí hay una instancia de Firefox que muestra un cuadro de búsqueda de Google como su página de inicio predeterminada:</p> + +<p><img alt="Example of Firefox nightly displaying a custom Google page as default" src="https://mdn.mozillademos.org/files/8533/search-engine.jpg" style="display: block; height: 399px; margin: 0px auto; width: 650px;"></p> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<ul> + <li>Profundizar más: <a href="/en-US/docs/Learn/What_is_a_web_server">Qué es un servidor Web</a></li> + <li>Vea cómo las páginas web están enlazadas en un sitio web: <a href="/en-US/docs/Learn/Understanding_links_on_the_web">Entendiendo los enlaces en la web</a></li> +</ul> + +<p> </p> diff --git a/files/es/learn/common_questions/que_es_un_servidor_web/index.html b/files/es/learn/common_questions/que_es_un_servidor_web/index.html new file mode 100644 index 0000000000..4969677db6 --- /dev/null +++ b/files/es/learn/common_questions/que_es_un_servidor_web/index.html @@ -0,0 +1,120 @@ +--- +title: Que es un servidor WEB? +slug: Learn/Common_questions/Que_es_un_servidor_WEB +tags: + - Infraestructura + - Principiante + - necesitaEsquema +translation_of: Learn/Common_questions/What_is_a_web_server +--- +<div class="summary"> +<p>En este articulo veremos que son los servidores, cómo funcionan y por qué son importantes.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Debes saber <a href="/en-US/docs/Learn/How_the_Internet_works">como funciona internet</a>, y <a href="/en-US/docs/Learn/page_vs_site_vs_server_vs_search_engine">entendiendo la diferencia entre pagina web, sitio web, servidor y motor de busqueda</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender qué es un servidor web y comprender cómo funciona.</td> + </tr> + </tbody> +</table> + +<h2 id="Sumario">Sumario</h2> + +<p>Con "Servidor web" podemos referirnos a hardware o software, o a ambos trabajando juntos.</p> + +<ol> + <li>En cuanto a hardware, un servidor web es una computadora que almacena los archivos que componen un sitio web (ej. documentos HTML , imágenes, hojas de estilos CSS y archivo JavaScript) y los entrega al dispositivo del usuario final. Está conectado a internet y es accesible a través de un nombre de dominio como<code> mozilla.org</code>.</li> + <li>En cuanto a software, un servidor web tiene muchas partes encargadas del control sobre cómo tienen acceso los usuarios a los archivos, por lo menos un servidor <em>HTTP. </em>Un servidor HTTP es una pieza de software que comprende {{Glossary("URL","URLs")}} (direcciones web) y {{Glossary("HTTP")}} (el protocolo que tu navegador usa para ver las páginas web).</li> +</ol> + +<p>Al nivel más básico, siempre que un navegador necesite un archivo almacenado en un servidor web, el navegador hará una solicitud al servidor mediante la vía HTTP. Cuando la petición llega al servidor web correcto (hardware), el servidor <em>HTTP </em> (software) envía el archivo antes solicitado, tambien a través de HTTP.</p> + +<p><img alt="Basic representation of a client/server connection through HTTP" src="https://mdn.mozillademos.org/files/8659/web-server.svg" style="height: 200px; width: 600px;"></p> + +<p>Para publicar un sitio web, necesitarás un servidor web dinámico o estático.</p> + +<p>Un <strong>servidor web estático</strong>, o pila, consiste en una computadora (hardware) con un servidor HTTP (software). Llamamos a este "estático" debido a que el servidor envía los archivos almacenados "tal cual" a tu navegador.</p> + +<p>Un <strong>servidor web dinámico </strong>consiste en un servidor web estático con un software extra , lo común es que sea una <em>aplicación</em> servidor <em> y una </em> base de datos<em>. Llamamos a esto</em> "dinámico" por que la aplicacion servidor actualiza los archivos almacenados en la base de datos antes de enviarlos mediante el servidor HTTP.</p> + +<p>Por ejemplo, para ver la página que ves en tu navegador finalmente, el servidor aplicación puede mostrar el diseño HTML con contenido desde una base de datos. Sitios como MDN o Wikipedia tienen cientos de páginas web, que no son realmente archivos HTML, si no una estrucura HTML asociada a una gigantesca base de datos. Esto hace mas fácil y rápido el mantenimiento y entrega del contenido.</p> + +<h2 id="Aprendizaje_activo">Aprendizaje activo</h2> + +<p><em>No hay aprendizaje activo disponible. <a href="https://developer.mozilla.org/en-US/docs/MDN/Getting_started">P</a><u>or favor, considere colaborar.</u></em></p> + +<h2 id="Inmersión_más_profunda">Inmersión más profunda</h2> + +<p>Para recuperar una página web, como ya dijimos, su navegador envía una solicitud al servidor web, que procede a buscar el archivo solicitado en su propio espacio de almacenamiento. Al encontrar el archivo, el servidor lo lee, lo procesa según sea necesario y lo envía al navegador. Veamos esos pasos con más detalle.</p> + +<h3 id="Alojamiento_de_archivos_Hosting">Alojamiento de archivos (Hosting)</h3> + +<p>Un servidor web primero debe almacenar los archivos del sitio web, es decir, todos los documentos HTML y sus medios relacionados, incluidas las imágenes, las hojas de estilo CSS, los archivos JavaScript, las fuentes y videos.</p> + +<p>Técnicamente, puede alojar todos esos archivos en su propia computadora, pero es mucho más conveniente almacenarlos en un servidor web dedicado que:</p> + +<ul> + <li>siempre está funcionando.</li> + <li>siempre está conectado a internet.</li> + <li>tiene la misma dirección IP todo el tiempo.</li> + <li>es mantenido por un proveedor externo.</li> +</ul> + +<p>Por todas estas razones, encontrar un buen proveedor de alojamiento es una parte clave del desarrollo de su sitio web. Investigue a través de los diversos servicios que ofrecen las compañías y elija uno que se ajuste a sus necesidades y a su presupuesto (los servicios van desde los gratuitos hasta los miles de dólares al mes). Puede encontrar mas información <a href="https://developer.mozilla.org/en-US/Learn/How_much_does_it_cost#Hosting">en este artículo</a>.</p> + +<p>Una vez que configura una solución de alojamiento web, solo tiene que <a href="/en-US/docs/Learn/Upload_files_to_a_web_server">cargar sus archivos en su servidor web</a>.</p> + +<h3 id="Comunicación_a_través_de_HTTP">Comunicación a través de HTTP</h3> + +<p>En segundo lugar, un servidor web brinda soporte para HTTP (<strong>H</strong>yper<strong>t</strong>ext <strong>T</strong>ransfer <strong>P</strong>rotocol ó <span>Protocolo de Transferencia de Hipertexto</span>). <span class="tlid-translation translation"><span title="">Como su nombre lo indica, HTTP especifica cómo transferir hypertext (es decir, documentos web vinculados) entre dos computadoras.</span></span></p> + +<p>Un <em>protocolo </em> es un conjunto de reglas para la comunicación entre dos computadoras. HTTP es un protocolo textual, sin estado.</p> + +<dl> + <dt>Textual</dt> + <dd>Todos los comandos son de texto plano y legible para ser leído por humanos.</dd> + <dt><span class="tlid-translation translation"><span class="alt-edited" title="">Sin estado</span></span></dt> + <dd>Ni el servidor ni el cliente recuerdan las comunicaciones anteriores. Por ejemplo, al confiar solo en HTTP, un servidor no puede recordar la contraseña que ingresó ni el paso que está realizando en una transacción. Necesita un servidor de aplicaciones para tareas como esa. (Cubriremos ese tipo de tecnología en otros artículos).</dd> +</dl> + +<p>HTTP proporciona reglas claras sobre cómo se comunican un cliente y un servidor. Cubriremos el propio HTTP en un <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP">artículo técnico</a> más adelante. Por ahora, sólo sé consciente de estas cosas:</p> + +<ul> + <li>Solo los clientes pueden hacer solicitudes HTTP a los servidores. Los servidores solo pueden responder a la solicitud HTTP de un cliente.</li> + <li>Al solicitar un archivo a través de HTTP, los clientes deben proporcionar la URL del archivo.</li> + <li>El servidor web debe responder a todas las solicitudes HTTP, al menos con un mensaje de error.</li> +</ul> + +<p><a href="https://developer.mozilla.org/en-US/404"><img alt="The MDN 404 page as an example of such error page" src="https://mdn.mozillademos.org/files/8661/mdn-404.jpg" style="float: right; height: 300px; width: 300px;"></a> En un servidor web, el servidor HTTP es responsable de procesar y responder las solicitudes entrantes.</p> + +<ol> + <li>Al recibir una solicitud, un servidor HTTP primero verifica si la URL solicitada coincide con un archivo existente.</li> + <li>Si es así, el servidor web envía el contenido del archivo de nuevo al navegador. Si no, un servidor de aplicaciones construye el archivo necesario.</li> + <li>Si ninguno de los procesos es posible, el servidor web devuelve un mensaje de error al navegador, generalmente "404 Not Found". ( Ese error es tan común que muchos diseñadores web pasan bastante tiempo diseñando páginas de error 404.)</li> +</ol> + +<h3 id="Contenido_Estático_vs._Dinámico">Contenido Estático vs. Dinámico</h3> + +<p><span class="tlid-translation translation"><span title="">En términos generales, un servidor puede entregar contenido estático o dinámico.</span> <span title="">"Estático" significa "servido como está".</span> <span title="">Los sitios web estáticos son los más fáciles de configurar, por lo que le sugerimos que convierta su primer sitio en un sitio estático.</span></span></p> + +<p>"Dinámico" significa que el servidor procesa el contenido o incluso lo genera desde una base de datos. Esta solución proporciona más flexibilidad, pero se vuelve más difícil de manejar, lo que hace que sea mucho más complejo desarrollar el sitio web.</p> + +<p>Tomemos por ejemplo la página que estás leyendo en este momento. En el servidor web que lo aloja, hay un servidor de aplicaciones que toma el contenido del artículo de una base de datos, lo formatea, lo coloca dentro de algunas plantillas HTML y le envía los resultados. En este caso, el servidor de aplicaciones se llama <a href="/en-US/docs/MDN/Kuma">Kuma </a>y está desarrollado con Python (utilizando el framework <a href="https://www.djangoproject.com/">Django</a>). El equipo de Mozilla creó Kuma para las necesidades específicas de MDN, pero hay muchas aplicaciones similares basadas en otras tecnologías.</p> + +<p><span class="tlid-translation translation"><span title="">Hay tantos servidores de aplicaciones que es resulta difícil sugerir uno en particular.</span></span> <span class="tlid-translation translation"><span title="">Algunos servidores de aplicaciones se adaptan a categorías específicas de sitios web como blogs, wikis o tiendas electrónicas;</span></span> <span class="tlid-translation translation"><span title="">otros, llamados</span></span> CMS (Content Management Systems ó <span class="tlid-translation translation"><span title="">Sistemas de Gestión de Contenidos</span></span>), <span class="tlid-translation translation"><span title="">son más genéricos.</span></span> <span class="tlid-translation translation"><span title="">Si está desarrollando un sitio web dinámico, tómese el tiempo para elegir una herramienta que se adapte a sus necesidades.</span></span> <span class="tlid-translation translation"><span title="">A menos que desee aprender algo de programación de servidores web</span></span> (¡es un área emocionante!), no necesita crear su propio servidor de aplicaciones.</p> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<p>Ahora que estás familiarizado con los servidores web, podrías:</p> + +<ul> + <li>leer sobre<a href="/en-US/docs/Learn/How_much_does_it_cost"> cuánto cuesta hacer algo en la web</a></li> + <li>consultar otros artículos relacionados con<a href="/en-US/docs/Learn/What_software_do_I_need">los diferentes software que puedes utilizar para crear un sitio web</a></li> + <li>pasar a algo práctico tipo: <a href="/en-US/docs/Learn/Upload_files_to_a_web_server">¿cómo subir archivos al servidor?</a>.</li> +</ul> diff --git a/files/es/learn/common_questions/que_software_necesito/index.html b/files/es/learn/common_questions/que_software_necesito/index.html new file mode 100644 index 0000000000..92687e7d13 --- /dev/null +++ b/files/es/learn/common_questions/que_software_necesito/index.html @@ -0,0 +1,226 @@ +--- +title: ¿Qué software necesito para construir un sitio web? +slug: Learn/Common_questions/Que_software_necesito +tags: + - Build a website + - Building + - Mecanismos Web + - Principiante + - software +translation_of: Learn/Common_questions/What_software_do_I_need +--- +<div class="summary"> +<p>En este artículo se explican cuales componentes de software necesita para editar, cargar, o visualizar un sitio web. </p> +</div> + +<table class="learn-box nostripe standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Deberías conocer acerca de <a href="/en-US/docs/Learn/page_vs_site_vs_server_vs_search_engine">la diferencia entre páginas web, sitios web, servidores web, y moteres de búsqueda.</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender qué componentes de software necesita si quiere editar, cargar o visualizar un sitio web.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p><span class="seoSummary">Puede descargar la mayoría de los programas que necesita para el desarrollo web de forma gratuita. Proporcionaremos unos enlaces en este artículo. </span></p> + +<p><span class="seoSummary">Necesitarás herramientas para:</span></p> + +<ul> + <li><span class="seoSummary">Crear y editar páginas web </span></li> + <li><span class="seoSummary">Cargar archivos a tu servidor web</span></li> + <li><span class="seoSummary">Visualizar tu servidor web</span></li> +</ul> + +<p><span class="seoSummary">Casi todos los sistemas operativos incluyen por defecto un editor de texto y un navegador, el cual puedes usar para ver los sitios web. Como resultado, usualmente sólo necesitas adquirir software para la transferencia de archivos a tu servidor web.</span></p> + +<h2 id="Aprendizaje_activo">Aprendizaje activo</h2> + +<p><em>No hay aprendizaje activo disponible todavía. <a href="/es/docs/MDN/Comenzando">Por favor, considere contribuir</a>.</em></p> + +<h2 id="Profundización">Profundización</h2> + +<h3 id="Creción_y_edición_de_páginas_web">Creción y edición de páginas web</h3> + +<p>Para crear y editar un sitio web, necesita un editor de texto. Editores de texto crean y modifican archivos de texto sin formato. Otros formatos, como <strong>{{Glossary("RTF")}}</strong>, te permiten añadirle formato, como negrita y señalado, esos no son adecuados para escribir páginas web. Debe pensar bien qué editor de texto usar, ya que trabajará intensamente con él mientras construye el sitio web.</p> + +<p>Todos los sistemas operativos de escritorio traen un editor de texto básico. Estos editores son muy sencillos, pero les faltan características especiales para codificar páginas web. Si desea algo un poco más elegante, hay muchas herramientas de terceros disponibles. Editores de terceros, a menudo viene con características extra, como coloreado de sintaxis, autocompletado, secciones expandibles y búsqueda de código. A continuación se muestra una lista de algunos editores:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Sistema operativo</th> + <th scope="col">Editor incorporado</th> + <th scope="col">Editor de terceros</th> + </tr> + </thead> + <tbody> + <tr> + <td>Windows</td> + <td> + <ul> + <li><a href="http://en.wikipedia.org/wiki/Notepad_%28software%29" rel="external">Notepad</a></li> + </ul> + </td> + <td> + <ul> + <li><a href="http://notepad-plus-plus.org/">Notepad++</a></li> + <li><a href="https://www.visualstudio.com/">Visual Studio Code</a></li> + <li><a href="https://www.jetbrains.com/webstorm/">Web Storm</a></li> + <li><a href="http://brackets.io/">Brackets</a></li> + <li><a href="https://shiftedit.net/">ShiftEdit</a></li> + <li><a href="https://www.sublimetext.com/">Sublime Text</a></li> + </ul> + </td> + </tr> + <tr> + <td>Mac OS</td> + <td> + <ul> + <li><a href="http://en.wikipedia.org/wiki/TextEdit" rel="external">TextEdit</a></li> + </ul> + </td> + <td> + <ul> + <li><a href="http://www.barebones.com/products/textwrangler/">TextWrangler</a></li> + <li><a href="https://www.visualstudio.com/">Visual Studio Code</a></li> + <li><a href="http://brackets.io/">Brackets</a></li> + <li><a href="https://shiftedit.net/">ShiftEdit</a></li> + <li><a href="https://www.sublimetext.com/">Sublime Text</a></li> + </ul> + </td> + </tr> + <tr> + <td>Linux</td> + <td> + <ul> + <li><a href="http://en.wikipedia.org/wiki/Vi" rel="external">Vi</a> (All UNIX)</li> + <li><a href="http://en.wikipedia.org/wiki/Gedit" rel="external">GEdit</a> (Gnome)</li> + <li><a href="http://en.wikipedia.org/wiki/Kate_%28text_editor%29" rel="external">Kate</a> (KDE)</li> + <li><a href="http://en.wikipedia.org/wiki/Leafpad" rel="external">LeafPad</a> (Xfce)</li> + </ul> + </td> + <td> + <ul> + <li><a href="http://www.gnu.org/software/emacs/">Emacs</a></li> + <li><a href="http://www.vim.org/" rel="external">Vim</a></li> + <li><a href="https://www.visualstudio.com/">Visual Studio Code</a></li> + <li><a href="http://brackets.io/">Brackets</a></li> + <li><a href="https://shiftedit.net/">ShiftEdit</a></li> + <li><a href="https://www.sublimetext.com/">Sublime Text</a></li> + </ul> + </td> + </tr> + <tr> + <td>Chrome OS</td> + <td> </td> + <td> + <ul> + <li><a href="https://shiftedit.net/">ShiftEdit</a></li> + </ul> + </td> + </tr> + </tbody> +</table> + +<p>Aquí se muestra una captura de pantalla de un editor de texto avanzado:</p> + +<p><img alt="Screenshot of Notepad++." src="https://mdn.mozillademos.org/files/8221/NotepadPlusPlus.png" style="display: block; height: 311px; margin: 0 auto; width: 450px;"> </p> + +<p>Esta es una captura de panalla de un editor de texto online:</p> + +<p><img alt="Screenshot of ShiftEdit" src="https://mdn.mozillademos.org/files/15837/shiftedit.png" style="display: block; height: 311px; margin: 0 auto; width: 475px;"></p> + +<h3 id="Subir_archivos_a_la_Web">Subir archivos a la Web</h3> + +<p>Cuando tu sitio web está listo para visualización pública , tendrás que subir tus páginas web a tu servidor web. Puedes comprar espacio en un servidor de varios proveedores (vea el artículo <a class="new" href="/en-US/docs/Learn/How_much_does_it_cost">¿Cuánto cuesta hacer algo en la web?</a>). Una vez que establezca qué proveedor utilizar, el proveedor le enviará un correo con la información de acceso, usualmente en la forma de una URL SFTP, nombre de usuario, contraseña, y otra información necesaria para conectarte con su servidor. Tenga en cuenta que el protocolo (S)FTP está actualmente algo pasado de moda, mientras otros sistemas de carga de archivos están comenzando a volverse populares como <a href="https://en.wikipedia.org/wiki/Rsync">RSync</a> y <a href="https://help.github.com/articles/using-a-custom-domain-with-github-pages/">Git/GitHub</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Note: </strong>FTP es inherentemente inseguro. Deberías asegurarte de que tu proveedor de alojamiento permite el uso de una conexión segura, por ejemplo SFTP o RSync sobre SSH.</p> +</div> + +<p>Subir archivos a un sitio web es un paso muy importante mientras se crea un sitio web, por lo que sete tema se abarca en detalle en <a href="/en-US/docs/Learn/Upload_files_to_a_web_server">un artículo aparte</a>. Por ahora, se presenta una lista de clientes (S)FTP gratuitos:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Sistema operativo</th> + <th colspan="2" rowspan="1" scope="col" style="text-align: center;"> Software FTP </th> + </tr> + </thead> + <tbody> + <tr> + <td>Windows</td> + <td> + <ul> + <li><a href="http://winscp.net" rel="external">WinSCP</a></li> + <li><a href="http://mobaxterm.mobatek.net/">Moba Xterm</a></li> + </ul> + </td> + <td colspan="1" rowspan="3"> + <ul> + <li><a href="https://filezilla-project.org/">FileZilla</a> (Todos los SO)</li> + </ul> + </td> + </tr> + <tr> + <td>Linux</td> + <td> + <ul> + <li><a href="https://wiki.gnome.org/action/show/Apps/Files?action=show&redirect=Apps%2FNautilus" rel="external">Nautilus/Files</a> (Gnome)</li> + <li><a href="http://dolphin.com/" rel="external">Dolphin</a> (KDE)</li> + </ul> + </td> + </tr> + <tr> + <td> Mac OS</td> + <td> + <ul> + <li><a href="http://cyberduck.de/">Cyberduck</a></li> + </ul> + </td> + </tr> + <tr> + <td> Chrome OS</td> + <td> + <ul> + <li><a href="https://shiftedit.net/">ShiftEdit</a> (Todos los SO)</li> + </ul> + </td> + <td colspan="1"> </td> + </tr> + </tbody> +</table> + +<h3 id="Navegación_por_sitios_web">Navegación por sitios web</h3> + +<p>Como ya sabe, necesita un navegador para ver los sitios web. Existen <a href="http://en.wikipedia.org/wiki/List_of_web_browsers">docenas</a> de opciones de navegadores para uso personal, pero cuando usted está desarrollando un sitio web debe probarlo al menos con los navegadores principales siguientes, para estar seguro de que su sitio web funciona para la mayoría de las personas: </p> + +<ul> + <li><a href="https://www.mozilla.org/en-US/firefox/new/" rel="external">Mozilla Firefox</a></li> + <li><a href="https://www.google.fr/chrome/browser/" rel="external">Google Chrome</a></li> + <li><a href="http://windows.microsoft.com/en-US/internet-explorer/download-ie" rel="external">Microsoft Internet Explorer</a></li> + <li><a href="http://www.apple.com/safari/" rel="external">Apple Safari</a></li> +</ul> + +<p>Si su sitio está destinado a un grupo específico (por ejemplo, una plataforma técnica o país), puede que tenga que probar el sitio con navegadores adicionales, como <a href="http://www.opera.com/" rel="external">Opera</a>, <a href="http://www.konqueror.org/">Konqueror</a>, o<a href="http://www.ucweb.com/ucbrowser/" rel="external"> UC Browser</a>.</p> + +<p>Sin embargo las pruebas se dificultan debido a que algunos navegadores sólo funcionan en determinados sistemas operativos. Apple Safari se ejecuta en iOS y Mac OS, mientras Internet Explorer corre solamente en Windows. Lo mejor es aprovechar los servicios como <a href="http://browsershots.org/" rel="external">Browsershots</a> o <a href="http://www.browserstack.com/" rel="external">Browserstack</a>. Browsershots proporciona capturas de pantallas de tu sitio web en diferentes navegadores. Browserstack realmente te otorga acceso remoto a máquinas virtuales de modo que puedes probar tu sitio en los entornos más comunes. De manera alternativa, puedes instalar tu propia máquina virtual, pero se necesita algo de experiencia. ( Si escoge este camino, Microsoft tiene algunas herramientas para desarrolladores incluso una máquina virtual lista para utilizar en <a href="https://modern.ie" rel="external">modern.ie</a>.)</p> + +<p>Sin falta ejecute algunas pruebas en dispositivos reales, especialmente en dispositivos móviles reales. Simulación de dispositivos móviles es una tecnología nueva, en evolución y menos confiable que la simulación de escritorio. Desde luego, los dispositivos móviles son costosos, por lo que le sugerimos echar un vistazo a <a href="http://opendevicelab.com/" rel="external">la inictiva de Laboratorios de dispositivos abiertos</a>. Puede además compartir dispositivos quiere probar en diferentes plataformas sin gastar mucho.</p> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<ul> + <li>Algunos de estos programas son gratis, pero no todos. <a href="/en-US/docs/Learn/Common_questions/How_much_does_it_cost">Descubra cuánto cuesta hacer algo en la web</a><a class="new" href="/en-US/docs/Learn/How_much_does_it_cost">.</a></li> + <li>Si desea aprrender más sobre editores de texto, lea este artículo acerca de <a href="/en-US/docs/Learn/Choose,_Install_and_set_up_a_text_editor">cómo seleccionar e instalar un editor de texto</a>.</li> + <li>Si se está preguntando cómo publicar en tu sitio web, eche un vistazo a <a href="/en-US/docs/Learn/Upload_files_to_a_web_server">"Cómo subir archivos a un servidor web"</a>.</li> +</ul> + +<p> </p> diff --git a/files/es/learn/common_questions/qué_es_una_url/index.html b/files/es/learn/common_questions/qué_es_una_url/index.html new file mode 100644 index 0000000000..ef50be60ad --- /dev/null +++ b/files/es/learn/common_questions/qué_es_una_url/index.html @@ -0,0 +1,152 @@ +--- +title: ¿Qué es una URL? +slug: Learn/Common_questions/Qué_es_una_URL +translation_of: Learn/Common_questions/What_is_a_URL +--- +<div class="summary"> +<p>Este artículo habla sobre las Uniform Resource Locators (URLs), explicando qué son y cómo se estructuran.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Primero necesitas saber <a href="/en-US/docs/Learn/How_the_Internet_works">Como funciona Internet</a>, <a href="/en-US/docs/Learn/What_is_a_Web_server">qué es un servidor Web</a> y <a href="/en-US/docs/Learn/Understanding_links_on_the_web">los conceptos detrás de los enlaces en la web</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprenderás lo que es una URL y como funcionan en la Web.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p><span class="seoSummary">Junto con el {{Glossary("Hypertext", "Hipertexto")}} y {{Glossary("HTTP")}}, las <strong><dfn>URL</dfn></strong> son uno de los conceptos claves de la Web. Es el mecanismo usado por los {{Glossary("Browser","navegadores")}} para obtener cualquier recurso publicadon en la web.</span></p> + +<p><strong>URL</strong> significa <em>Uniform Resource Locator (Localizador de Recursos Uniforme)</em>. Una URL no es más que una direccion que es dada a un recurso único en la Web. En teoria, cada URL valida apunta a un único recurso. Dichos recursos pueden ser páginas HTML, documentos CSS, imagenes, etc. En la practica, hay algunas excepciones, siendo la más común una URL apuntando a un recurso que ya no existe o que ha sido movido. Como el recurso representado por la URL y la URL en si son manejadas por el servidor Web, depende del dueño del servidor web manejar ese recurso y su URL asociada adecuadamente.</p> + +<h2 id="Active_Learning">Active Learning</h2> + +<p><em>There is no active learning available yet. <a href="/en-US/docs/MDN/Getting_started">Please, consider contributing</a>.</em></p> + +<h2 id="Profundizando">Profundizando</h2> + +<h3 id="Conceptos_básicos_anatomía_de_una_URL">Conceptos básicos: anatomía de una URL</h3> + +<p>Aquí hay algunos ejemplos de URL:</p> + +<pre class="notranslate">https://developer.mozilla.org +https://developer.mozilla.org/en-US/docs/Learn/ +https://developer.mozilla.org/en-US/search?q=URL</pre> + +<p>Cualquiera de esas URL se puede escribir en la barra de direcciones de su navegador para indicarle que cargue la página (recurso) asociada.</p> + +<p>Una URL está compuesta de diferentes partes, algunas obligatorias y otras opcionales. Veamos las partes más importantes usando la siguiente URL:</p> + +<pre class="notranslate">http://www.example.com:80/path/to/myfile.html?key1=value1&key2=value2#SomewhereInTheDocument</pre> + +<dl> + <dt><img alt="Protocol" src="https://mdn.mozillademos.org/files/15766/mdn-url-protocol@x2_update.png" style="height: 70px; width: 440px;"></dt> + <dd><code>http</code> es el protocolo. La primera parte de la URL indica qué protocolo debe usar el navegador. Un protocolo es un método establecido para intercambiar o transferir datos alrededor de una red informática. Por lo general, para sitios web es el protocolo HTTP o su versión segura, HTTPS. La Web requiere uno de estos dos, pero los navegadores también saben cómo manejar otros protocolos como mailto: (para abrir un cliente de correo) o ftp: para manejar la transferencia de archivos, así que no se sorprenda si ve tales protocolos.</dd> + <dt><img alt="Domaine Name" src="https://mdn.mozillademos.org/files/8015/mdn-url-domain@x2.png" style="height: 70px; width: 440px;"></dt> + <dd><code>www.example.com</code> es el nombre de dominio. Indica qué servidor web se solicita. Alternativamente, es posible usar directamente un {{Glossary("dirección IP")}}, pero debido a que es menos conveniente, no se usa con frecuencia en la Web.</dd> + <dt><img alt="Port" src="https://mdn.mozillademos.org/files/8017/mdn-url-port@x2.png" style="height: 70px; width: 440px;"></dt> + <dd><code>:80</code> es el puerto. Indica la "puerta" técnica utilizada para acceder a los recursos en el servidor web. Por lo general, se omite si el servidor web utiliza los puertos estándar del protocolo HTTP (80 para HTTP y 443 para HTTPS) para otorgar acceso a sus recursos. De lo contrario es obligatorio.</dd> + <dt><img alt="Path to the file" src="https://mdn.mozillademos.org/files/8019/mdn-url-path@x2.png" style="height: 70px; width: 440px;"></dt> + <dd><code>/path/to/myfile.html</code> es la ruta al recurso en el servidor web. En los primeros días de la Web, una ruta como esta representaba la ubicación de un archivo físico en el servidor web. Hoy en día, es principalmente una abstracción manejada por servidores web sin ninguna realidad física.</dd> + <dt><img alt="Parameters" src="https://mdn.mozillademos.org/files/8021/mdn-url-parameters@x2.png" style="height: 70px; width: 440px;"></dt> + <dd><code>?key1=value1&key2=value2</code> son parámetros adicionales proporcionados al servidor web. Esos parámetros son una lista de pares clave/valor separados con el símbolo &. El servidor web puede usar esos parámetros para hacer cosas adicionales antes de devolver el recurso. Cada servidor web tiene sus propias reglas con respecto a los parámetros, y la única forma confiable de saber si un servidor web específico está manejando parámetros es preguntando al propietario del servidor web.</dd> + <dt><img alt="Anchor" src="https://mdn.mozillademos.org/files/8023/mdn-url-anchor@x2.png" style="height: 70px; width: 440px;"></dt> + <dd><code>#SomewhereInTheDocument</code> es un ancla para otra parte del recurso en sí. Un ancla representa una especie de "marcador" dentro del recurso, dando al navegador las instrucciones para mostrar el contenido ubicado en ese lugar "marcado". En un documento HTML, por ejemplo, el navegador se desplazará hasta el punto donde se define el ancla; en un video o documento de audio, el navegador intentará ir a la hora que representa el ancla. Vale la pena señalar que la parte después del #, también conocido como el identificador de fragmento, nunca se envía al servidor con la solicitud.</dd> +</dl> + +<p>{{Note('Existen <a href="http://en.wikipedia.org/wiki/Uniform_Resource_Locator">algunas partes extras y reglas extras </a>con respecto a las URL, pero no son relevantes para usuarios habituales o desarrolladores web. No se preocupe por esto, no necesita conocerlos para construir y usar URL completamente funcionales.')}}</p> + +<p>Puede pensar en una URL como una dirección de correo postal normal: el protocolo representa el servicio postal que desea utilizar, el nombre de dominio es la ciudad o el pueblo y el puerto es como el código postal; la ruta representa el edificio donde se debe entregar su correo; los parámetros representan información adicional como el número de apartamento en el edificio; y, finalmente, el ancla representa a la persona real a la que ha dirigido su correo.</p> + +<h3 id="Cómo_usar_las_URL">Cómo usar las URL</h3> + +<p>Se puede escribir cualquier URL dentro de la barra de direcciones del navegador para acceder al recurso que se encuentra detrás. ¡Pero esto es sólo la punta del iceberg!</p> + +<p>El lenguaje {{Glossary("HTML")}} — <a href="/en-US/docs/Learn/HTML/HTML_tags">que se discutirá más adelante</a> — hace un uso extensivo de las URL:</p> + +<ul> + <li>para crear enlaces a otros documentos con el elemento {{HTMLElement("a")}};</li> + <li>para vincular un documento con sus recursos relacionados a través de varios elementos como {{HTMLElement("link")}} o {{HTMLElement("script")}};</li> + <li>para mostrar recursos como imágenes (con el elemento {{HTMLElement("img")}}), videos (con el elemento {{HTMLElement("video")}}), sonido y música (con el elemento {{HTMLElement("audio")}} ), etc.;</li> + <li>para mostrar otros documentos HTML con el elemento {{HTMLElement ("iframe")}}.</li> +</ul> + +<div class="note"> +<p><strong>Nota:</strong> Al especificar URL para cargar recursos como parte de una página (como cuando se usa <script>, <audio>, <img>, <video> y similares), solo debe usar URL HTTP y HTTPS. El uso de FTP, por ejemplo, no es particularmente seguro y muchos navegadores ya no lo admiten.</p> +</div> + +<p>Otras tecnologías, como {{Glossary("CSS")}} o {{Glossary("JavaScript")}}, usan URLs ampliamente, y estos son realmente el corazón de la Web.</p> + +<h3 id="URL_absolutas_vs_URL_relativas">URL absolutas vs URL relativas</h3> + +<p>Lo que vimos arriba se llama URL absoluta, pero también hay algo llamado URL relativa. Examinemos lo que significa esa distinción con más detalle.</p> + +<p>Las partes requeridas de una URL dependen en gran medida del contexto en el que se utiliza la URL. En la barra de direcciones de su navegador, una URL no tiene ningún contexto, por lo que debe proporcionar una URL completa (o absoluta), como las que vimos anteriormente. No necesita incluir el protocolo (el navegador usa HTTP de manera predeterminada) o el puerto (que solo se requiere cuando el servidor web de destino está utilizando algún puerto inusual), pero todas las otras partes de la URL son necesarias.</p> + +<p>Cuando se usa una URL dentro de un documento, como en una página HTML, las cosas son un poco diferentes. Debido a que el navegador ya tiene la propia URL del documento, puede usar esta información para completar las partes faltantes de cualquier URL disponible dentro de ese documento. Podemos diferenciar entre una URL absoluta y una URL relativa mirando solo la parte de ruta de la URL. Si la parte de ruta de la URL comienza con el carácter "/", el navegador buscará ese recurso desde la raíz superior del servidor, sin referencia al contexto dado por el documento actual.</p> + +<p>Veamos algunos ejemplos para aclarar esto.</p> + +<h4 id="Ejemplos_de_URL_absolutas">Ejemplos de URL absolutas</h4> + +<dl> + <dt>URL Completa (la misma que usamos antes)</dt> + <dd> + <pre class="notranslate">https://developer.mozilla.org/en-US/docs/Learn</pre> + </dd> + <dt>Protocolo implícito</dt> + <dd> + <pre class="notranslate">//developer.mozilla.org/en-US/docs/Learn</pre> + + <p>En este caso, el navegador llamará a esa URL con el mismo protocolo que el utilizado para cargar el documento que aloja esa URL.</p> + </dd> + <dt>Nombre de dominio implícito</dt> + <dd> + <pre class="notranslate">/en-US/docs/Learn</pre> + + <p>Este es el caso de uso más común para una URL absoluta dentro de un documento HTML. El navegador utilizará el mismo protocolo y el mismo nombre de dominio que el utilizado para cargar el documento que aloja esa URL. <strong>Nota</strong>: <em>no es posible omitir el nombre de dominio sin omitir también el protocolo</em>.</p> + </dd> +</dl> + +<h4 id="Ejemplos_de_URL_relativas">Ejemplos de URL relativas</h4> + +<p>Para comprender mejor los siguientes ejemplos, supongamos que las URL se invocan desde el documento ubicado en la siguiente URL:<code>https://developer.mozilla.org/en-US/docs/Learn</code></p> + +<dl> + <dt>Sub-recursos</dt> + <dd> + <pre class="notranslate">Skills/Infrastructure/Understanding_URLs +</pre> + Debido a que la URL no se inicia con <code>/</code>, el navegador intentará encontrar el documento en un subdirectorio del que contiene el recurso actual. Entonces, en este ejemplo, realmente queremos llegar a esta URL:<code>https://developer.mozilla.org/en-US/docs/Learn/Skills/Infrastructure/Understanding_URLs</code></dd> + <dt>Volviendo en el árbol de directorios</dt> + <dd> + <pre class="notranslate">../CSS/display</pre> + + <p>En este caso, usamos el <code>../</code> convención de escritura, heredada del mundo del sistema de archivos UNIX, para decirle al navegador que queremos subir desde un directorio. Aquí queremos llegar a esta URL:<code>https://developer.mozilla.org/en-US/docs/Learn/../CSS/display</code>, que se puede simplificar a: <code>https://developer.mozilla.org/en-US/docs/CSS/display</code></p> + </dd> +</dl> + +<h3 id="URL_semánticas">URL semánticas</h3> + +<p>A pesar de su sabor muy técnico, las URL representan un punto de entrada legible para un sitio web. Se pueden memorizar y cualquiera puede ingresarlos en la barra de direcciones de un navegador. Las personas están en el centro de la Web, por lo que se considera una buena práctica construir lo que se llama <a href="http://en.wikipedia.org/wiki/Semantic_URL"><em>URL semánticas</em></a>. Las URL semánticas usan palabras con un significado inherente que cualquier persona puede entender, independientemente de sus conocimientos técnicos.</p> + +<p>La semántica lingüística es, por supuesto, irrelevante para las computadoras. Probablemente has visto URL que parecen mashups de caracteres aleatorios. Pero hay muchas ventajas en la creación de URL legibles por humanos:</p> + +<ul> + <li>Es más fácil para ti manipularlos.</li> + <li>Aclara las cosas para los usuarios en términos de dónde están, qué están haciendo, qué están leyendo o interactuando en la Web.</li> + <li>Algunos motores de búsqueda pueden usar esa semántica para mejorar la clasificación de las páginas asociadas.</li> +</ul> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Understanding_domain_names">Comprendiendo nombres de dominio</a></li> +</ul> diff --git a/files/es/learn/common_questions/set_up_a_local_testing_server/index.html b/files/es/learn/common_questions/set_up_a_local_testing_server/index.html new file mode 100644 index 0000000000..e2223d3c8a --- /dev/null +++ b/files/es/learn/common_questions/set_up_a_local_testing_server/index.html @@ -0,0 +1,113 @@ +--- +title: ¿Cómo se configura un servidor de prueba local? +slug: Learn/Common_questions/set_up_a_local_testing_server +tags: + - Expreso + - Flask + - Lado-del-servidor + - Node + - PHP + - Principiante + - Python + - aprende + - django + - lamp + - servidores +translation_of: Learn/Common_questions/set_up_a_local_testing_server +--- +<div class="summary"> +<p>En este artículo explica cómo configurar un servidor de prueba local simple en su equipo y los conceptos básicos de cómo utilizarlo.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Primero debes saber <a href="/en-US/docs/Learn/How_the_Internet_works">cómo funciona internet</a>, y <a href="/en-US/docs/Learn/What_is_a_Web_server">qué es un servidor web</a>.</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Aprenderás cómo configurar un servidor de pruebas local</td> + </tr> + </tbody> +</table> + +<h2 id="Archivos_locales_versus_archivos_remotos">Archivos locales versus archivos remotos</h2> + +<p>En la mayor parte del área de aprendizaje, te decimos que abras tus ejemplos directamente en un navegador — lo que se hace con doble clic en el archivo HTML, o arrastrándolo y soltándolo en una ventana del navegador o eligiendo <em>Archivo</em> > <em>Abrir...</em> y navegando al archivo HTML, etc. Hay muchas maneras de lograr esto.</p> + +<p>Sabes si estás ejecutando el ejemplo desde un archivo local porque la dirección web tendrá <code>archivo://</code> al principio, seguido de la ruta al archivo en tu disco duro local. Por el contrario, si ves uno de nuestros ejemplos alojados en GitHub (o un ejemplo en algún otro servidor remoto), la dirección web tendrá <code>http://</code> o <code>https://</code> al principio, para mostrar que el archivo ha sido recibido a través de HTTP.</p> + +<h2 id="El_problema_de_probar_archivos_locales">El problema de probar archivos locales</h2> + +<p>Algunos ejemplos no se ejecutarán si los abre como archivos locales. Esto puede deberse a una variedad de razones, siendo las más probables:</p> + +<ul> + <li><strong>Cuentan con peticiones asincrónicas</strong>. Algunos navegadores (incluido chrome) no ejecutarán solicitudes asíncronas (consulte <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Obtención de datos desde el servidor</a>) si acaba de ejecutar el ejemplo desde un archivo local. Esto se debe a las restricciones de seguridad (para obtener más información sobre la seguridad web, lee <a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">La seguridad del sitio web</a>).</li> + <li><strong>Cuenta con un lenguaje de servidor</strong>. Los lenguajes de servidor (como PHP o Python) requieren de un servidor especial para interpretar el código y entregar los resultados.</li> +</ul> + +<h2 id="Ejecutando_un_servidor_HTTP_local_simple">Ejecutando un servidor HTTP local simple</h2> + +<p>Para evitar el problema de las solicitudes asíncronas, necesitamos probar estos ejemplos ejecutándolos a través de un servidor web local. Una de las maneras más fáciles de hacer esto para nuestros propósitos es usar el módulo <code>SimpleHTTPServer</code> de Python.</p> + +<p>Para hacer esto:</p> + +<ol> + <li> + <p>Instalar Python. Si usas Linux o Mac OS X, ya debe estar disponible en tu sistema. Si eres usuario de Windows, puedes conseguir un instalador desde la página principal de Python y seguir las instrucciones para instalarlo:</p> + + <ul> + <li>Vé a <a href="https://www.python.org/">python.org</a></li> + <li>Debajo de la sección de Descarga, haz clic en el link para Python "3.xxx".</li> + <li>En la parte superior de la página, selecciona el <em>instalador ejecutable windows x86</em> y descárgalo.</li> + <li>Cuando se haya descargado, córrelo.</li> + <li>En la primera página de instalación, asegúrate de marcar el checkbox "Añadir Python 3.xxx a la ruta"</li> + <li>Clic en <em>Instalar</em>, luego clic en <em>Cerrar</em> cuando la instalación ya haya finalizado.</li> + </ul> + </li> + <li> + <p>Abre la terminal (windows)/terminal (OS X/Linux). Para chequear que Python está instalado, ingrese el siguiente comando.</p> + + <div class="note"> + <p><strong>Nota</strong>: La v del ejemplo en mayuscula (V)</p> + </div> + + <pre class="brush: bash">python -V</pre> + </li> + <li> + <p>Esto debe retornar un número de versión. Si esto esta bien, navega al directorio que contiene tu ejemplo, usando el comando <code>cd</code>.</p> + + <pre class="brush: bash"># Incluye el nombre del directorio de entrar en él, +por ejemplo cd Escritorio + +# Use dos puntos para regresar un nivel de directorio +si es necesario,por ejemplo cd ../ +</pre> + </li> + <li> + <p>Ingresa el comando para iniciar el servidor en ese directorio:</p> + + <pre class="brush: bash"># En Mac y Linux +python -m SimpleHTTPServer +#Windows +python -m http.server</pre> + </li> + <li> + <p>Por defecto, se ejecutará el contenido del directorio en un servidor web local, en el puerto 8000. puedes ir a este servidor yendo a la URL <code>localhost:8000</code> en tu navegador web. Aquí verá el contenido del directorio listado - haga clic en el archivo HTML que desea ejecutar.</p> + </li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: si ya tienes corriendo algo en el puerto 8000, puedes escoger otro puerto corriendo el siguiente comando de servidor por un número de puerto alternativo, por ejemplo <code>python -m SimpleHTTPServer 7800</code>. Puedes acceder a tu contenido en el<code>localhost:7800</code>.</p> +</div> + +<h2 id="Ejecución_de_lenguajes_del_lado_del_servidor_localmente">Ejecución de lenguajes del lado del servidor localmente</h2> + +<p>El módulo <code>SimpleHTTPServer</code> de Python es útil, pero desconoce como ejecutar el código escrito en lenguajes como PHP o Python. Para resolver eso necesitarás algo más — lo que necesitarás exactamente depende del lenguaje del lado del servidor que estas intentando de ejecutar. Aquí están un par de ejemplos:</p> + +<ul> + <li>Para ejecutar el código del lado del servidor Python, necesitrá utilizar un framework web python. Puedes averiguar cómo usar el framework Django leyendog <a href="/en-US/docs/Learn/Server-side/Django">Django Web Framework (Python)</a>. <a href="http://flask.pocoo.org/">Flask</a> también es buena alternativa a Django (ligeramente menos pesado). Para ejecutar esto necesitarás <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/development_environment#Installing_Python_3">instalar Python/PIP</a>, luego instala Flask usando <code>pip3 install flask</code>. En este punto, deberías ser capaz de ejecutar los ejemplos de Python Flask usando por ejemplo <code>python3 python-example.py</code>, luego navegar al <code>localhost:5000</code> en tu navegador.</li> + <li>Para ejecutar código Node.js (JavaScript) del lado del servidor, necesitarás usar el nodo raw o un framework construido encima de él. Express es una buena opción — mira <a href="/en-US/docs/Learn/Server-side/Express_Nodejs">Express Web Framework (Node.js/JavaScript)</a>.</li> + <li>Para ejecutar código PHP del lado del servidor, necesitarás una configuración de servidor que pueda interpretar PHP. Las buenas opciones para los testeos locales de PHP son <a class="external external-icon" href="https://www.mamp.info/en/downloads/">MAMP</a> (Mac y Windows) t <a class="external external-icon" href="http://ampps.com/download">AMPPS</a> (Mac, Windows, Linux). Estos son paquetes completos que crean configuraciones locales que permiten ejecutar servidor Apache, PHP, y base de datos MySQL.</li> +</ul> diff --git a/files/es/learn/common_questions/thinking_before_coding/index.html b/files/es/learn/common_questions/thinking_before_coding/index.html new file mode 100644 index 0000000000..f675eb8d80 --- /dev/null +++ b/files/es/learn/common_questions/thinking_before_coding/index.html @@ -0,0 +1,177 @@ +--- +title: ¿Cómo empiezo a diseñar mi sitio web? +slug: Learn/Common_questions/Thinking_before_coding +tags: + - Pensar + - Principiante + - antes de codificar + - ideación + - proyecto +translation_of: Learn/Common_questions/Thinking_before_coding +--- +<p class="summary">Este artículo cubre el primer paso importante de cada proyecto: definir lo que se desea lograr con él.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Ninguno</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Aprender a definir metas para darle dirección a tu proyecto web.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p><span class="seoSummary">Al comenzar con un proyecto web, muchas personas se enfocan en el aspecto técnico. Por supuesto, debes estar más familiarizado con la técnica de su oficio, pero lo que realmente importa es lo que quieres lograr. Sí, parece obvio, pero demasiados proyectos fallan, no por falta de conocimiento técnico sino por falta de objetivos y visión.</span></p> + +<p>Entonces cuando tienes una idea y quieres convertirla en un sitio web, hay un par de cuestiones que debes responder antes que alguna otra cosa:</p> + +<ul> + <li>¿Qué es exactamente quiero lograr?</li> + <li>¿Cómo un sitio web me ayudará a alcanzar mis metas?</li> + <li>¿Qué es necesario hacer, y en qué orden, para alcanzar mis metas?</li> +</ul> + +<p>Todo esto es llamado <em>idealización del proyecto</em> y es un primer paso necesario para alcanzar tus metas, si eres un desarrollador principiante o experimentado.</p> + +<h2 id="Aprendizaje_Activo">Aprendizaje Activo</h2> + +<p><em>No hay aprendizaje activo todavía. <a href="/es/docs/MDN/Comenzando">Por favor, considere la posibilidad de contribuir</a>.</em></p> + +<h2 id="Profundizando">Profundizando</h2> + +<p>Un proyecto nunca comienza por el lado técnico. Los músicos jamás compondrán ninguna música a menos que primero tengan la idea de lo quieren tocar, y eso también vale para los pintores, escritores y desarrolladores web. La técnica viene en segundo lugar.</p> + +<p>La técnica es crítica. Los músicos deben dominar su instrumento, pero los buenos músicos nunca producen buena música sin una idea. Por lo tanto, antes de saltar al lado técnico, por ejemplo código y herramientas, primero debes dar un paso atrás y decidir en detalle lo que deseas hacer.</p> + +<p>Una discusión de horas con los amigos es un buen comienzo, pero inapropiado. Debes sentarte y estructurar tus ideas, para tener una visión clara sobre el camino que debes tomar para materializar tus ideas. Para hacer esto, sólo necesitas lápiz y papel y un tiempo para resolver al menos las siguientes preguntas.</p> + +<div class="note"> +<p><strong>Nota: </strong>Hay innumerables maneras de llevar a cabo la ideación del proyecto. No podemos presentarlas a todas aquí (un libro entero no sería suficiente). Lo que presentamos aquí es un método sencillo para manejar lo que los profesionales llaman <a href="http://en.wikipedia.org/wiki/Ideation_(idea_generation)">Ideación de Proyectos</a>, <a href="https://es.wikipedia.org/wiki/Planeamiento_de_proyectos">Planificación de Proyectos</a> y <a href="https://es.wikipedia.org/wiki/Gesti%C3%B3n_de_proyectos">Gestión de Proyectos</a>.</p> +</div> + +<h3 id="¿Qué_es_exactamente_lo_que_quiero_lograr">¿Qué es exactamente lo que quiero lograr?</h3> + +<p>Esta es la más importante pregunta a responder, ya que impulsa todo lo demás. Enumera todas la metas que deseas alcanzar. Puede ser cualquier cosa: vender bienes para ganar dinero, expresar opiniones políticas, conocer nuevos amigos, actuar con músicos, coleccionar imágenes de gatos o lo que quieras.</p> + +<p>Supongamos que eres músico. Y puedes desear que:</p> + +<ul> + <li>Permitir que las gente escuche tu música.</li> + <li>Venta de golosinas.</li> + <li>Conocer otros músicos.</li> + <li>Hablar acerca de tu música.</li> + <li>Enseñar música a través de vídeos.</li> + <li>Publicar fotos de tus gatos.</li> + <li>Encontrar un/a nuevo/a novio/a.</li> +</ul> + +<p>Una vez que tengas la lista, necesitas priorizar. Ordena los objetivos desde los más importantes hacia los menos importantes.</p> + +<ol> + <li>Encontrar un/a nuevo/a novio/a.</li> + <li>Permitir que las gente escuche tu música.</li> + <li>Hablar acerca de tu música.</li> + <li>Conocer otros músicos.</li> + <li>Venta de golosinas.</li> + <li>Enseñar música a través de vídeos.</li> + <li>Publicar fotos de tus gatos.</li> +</ol> + +<p>Haciendo este sencillo ejercicio, escribir metas y clasificarlas, te ayudará cuando tengas que tomar decisiones. (¿Debería implementar estas características, usar estos servicios, crear este diseño?)</p> + +<p>Entonces, ahora que tienes tu lista de objetivos priorizada, pasemos a la siguiente pregunta.</p> + +<h3 id="¿Cómo_podría_un_sitio_web_llevarme_a_mis_objetivos">¿Cómo podría un sitio web llevarme a mis objetivos?</h3> + +<p>Entonces, tienes tu lista de objetivos y sientes que necesitas un sitio web para alcanzarlos. ¿Estás seguro?</p> + +<p>Echemos un vistazo a nuestro ejemplo. Tenemos cinco metas relacionadas con la música, una relacionada a la vida personal (Encontrar pareja), y las fotos del gato completamente ajenas. ¿Es razonable construir un único sitio para cubrir todos esos objetivos? ¿Es necesario? Después de todo, una gran cantidad de servicios web existentes podría llevarte a tus objetivos sin necesidad de crear uno nuevo.</p> + +<p>Encontrar pareja es un caso prioritario en el que tiene más sentido utilizar los recursos existentes en lugar de construir todo un nuevo sitio. ¿Por qué? Porque invertiríamos más tiempo construyendo y manteniendo el sitio web en lugar de realmente buscar una pareja. Dado que nuestro objetivo es lo que más importa, debemos gastar nuestra energía en aprovechar las herramientas ya existentes en lugar de empezar desde cero. Una vez más, hay tantos servicios web ya disponibles para mostrar fotos que no vale la pena el esfuerzo para construir un nuevo sitio sólo para anunciar acerca de lo lindo que son nuestros gatos.</p> + +<p>Los otros cinco objetivos están todos conectados con la música. Hay, por supuesto, muchos servicios web que podrían manejar estas metas, pero tiene sentido, en este caso, construir un sitio web propio. Tal sitio web es la manera de agregar todo lo que queremos publicar en un solo lugar (bueno para las metas 3, 5 y 6). En resumen, ya que estos objetivos giran en torno al mismo tema, tener todo en un solo lugar nos ayudará a alcanzar nuestras metas y facilitará a nuestros seguidores el conectarse con nosotros.</p> + +<p>¿Cómo puede un sitio web ayudarme a alcanzar mis metas? Al responder a eso, encontrarás la mejor manera de alcanzar dichas metas y te ahorrarás desperdiciar esfuerzo.</p> + +<h3 id="¿Qué_hay_que_hacer_y_en_qué_orden_para_alcanzar_mis_metas">¿Qué hay que hacer, y en qué orden, para alcanzar mis metas?</h3> + +<p>Ahora que sabes qué es lo que quieres lograr, es momento de volver los objetivos en pasos prácticos. Como una nota lateral, tus metas no están necesariamente petrificadas, ellas evolucionan con el tiempo incluso en el transcurso del proyecto, si te encuentras con obstáculos inesperados o simplemente cambias de opinión.</p> + +<p>En lugar de una extensa explicación, volvamos a nuestro ejemplo con esta tabla.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Metas</th> + <th scope="col">Cosas por hacer</th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">Permitir que las gente escuche tu música</td> + <td> + <ol> + <li>Grabar música</li> + <li>Prepara algunos archivos de audio utilizables online (¿Podrías hacer esto con servicios web existentes?)</li> + <li>Dale a las personas acceso a tu música en alguna parte de tu sitio web</li> + </ol> + </td> + </tr> + <tr> + <td style="vertical-align: top;">Hablar acerca de tu música</td> + <td> + <ol> + <li>Escribe algunos artículos para iniciar la discusión</li> + <li>Define cómo deben lucir los artículos</li> + <li>Publica los artículos en el sitio web (¿Cómo hacer esto?)</li> + </ol> + </td> + </tr> + <tr> + <td style="vertical-align: top;">Conocer otros músicos</td> + <td> + <ol> + <li>Provee modos para que las personas te contacten (¿Email? ¿Facebook? ¿Teléfono? ¿Correo?)</li> + <li>Define cómo las personas encontrarán esos canales de contacto desde tu sitio web</li> + </ol> + </td> + </tr> + <tr> + <td style="vertical-align: top;">Venta de golosinas</td> + <td> + <ol> + <li>Crea las golosinas</li> + <li>Almacena las golosinas</li> + <li>Encuentra un modo de manejar el envío</li> + <li>Encuentra una manera de manejar el pago</li> + <li>Hacer un mecanismo en tu sitio para que la gente haga pedidos</li> + </ol> + </td> + </tr> + <tr> + <td style="vertical-align: top;">Enseñar música mediante vídeos</td> + <td> + <ol> + <li>Grabar vídeos de lecciones</li> + <li>Preparara archivos de vídeos visibles online (Una vez más, ¿Podría hacer esto con los servicios de web ya existentes?)</li> + <li>Dar a la gente acceso a tus vídeos en alguna parte de tu sitio</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<p>Dos cosas para resaltar. En primer lugar, algunos de estos items no están relacionados con la web (ej.: Grabar, escribir artículos). A menudo estas actividades fuera de línea importan incluso mucho más que el proyecto del sitio web. En ventas, por ejemplo, es mucho más importante y requiere mucho tiempo manejar la oferta, el pago y el envío que construir un sitio web donde las personas puedan realizar pedidos.</p> + +<p>En segundo lugar, establecer pasos procesables conduce a nuevas preguntas que necesitarás contestar. Por lo general, resultan ser más preguntas de lo que pensábamos al principio. (Ej. : ¿debo aprender a hacer todo yo mismo, pedirle a alguien que lo haga por mí, o utilizar servicios de terceros?).</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Como puedes ver, la idea simple “Quiero hacer un sitio web” genera una larga lista de quehaceres, la cual sólo crece conforme piensas en ella. Pronto puede parecer abrumador, pero no entres en pánico. No es necesario responder todas las preguntas y no necesitas hacer todo lo de tu lista. Lo que importa es tener una visión de lo que deseas y cómo alcanzarlo. Una vez que tengas una visión clara, necesitarás decidir cómo y cuándo hacerlo. Divida grandes tareas en pequeños pasos procesables, y esos pequeños pasos sumarán a grandes logros.</p> + +<p> </p> diff --git a/files/es/learn/common_questions/what_are_browser_developer_tools/index.html b/files/es/learn/common_questions/what_are_browser_developer_tools/index.html new file mode 100644 index 0000000000..c08f596c74 --- /dev/null +++ b/files/es/learn/common_questions/what_are_browser_developer_tools/index.html @@ -0,0 +1,248 @@ +--- +title: ¿Cuáles son las herramientas de desarrollo del navegador? +slug: Learn/Common_questions/What_are_browser_developer_tools +tags: + - CSS + - CodingScripting + - HTML + - Herramientas para el desarrollador + - JavaScript + - Navegador + - Novato + - Principiante + - aprende +translation_of: Learn/Common_questions/What_are_browser_developer_tools +--- +<div>{{IncludeSubnav("/es/Learn")}}</div> + +<div class="summary"> +<p>Todos los navegadores web modernos incluyen un potente conjunto de herramientas para desarrolladores. Estas herramientas hacen una variedad de cosas, desde inspeccionar HTML, CSS y JavaScript actualmente cargados, hasta mostrar qué activos ha solicitado la página y cuánto tiempo tardaron en cargarse. Este artículo explica cómo utilizar las funciones básicas de las herramientas de desarrollo de tu navegador.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Antes de ejecutar los siguientes ejemplos, abre el <a href="http://mdn.github.io/beginner-html-site-scripted/">sitio de ejemplo para principiantes</a> que creamos durante la serie de artículos <a href="/es/Learn/Getting_started_with_the_web">Introducción a la Web</a>. Lo deberías tener abierto mientras sigues los pasos que explicamos a continuación.</p> +</div> + +<h2 id="Cómo_abrir_devtools_en_tu_navegador">Cómo abrir devtools en tu navegador</h2> + +<p>Las herramientas para desarrolladores (<code>devtools</code>) viven dentro de tu navegador en una subventana que se ve más o menos así, dependiendo del navegador que estés utilizando:</p> + +<p><img alt="Devtools" src="https://mdn.mozillademos.org/files/16205/DevTools_63_inspector.png" style="border: 1px solid black; display: block; height: 1364px; margin: 0px auto; width: 672px;"></p> + +<p>¿Cómo la levantas? Existen tres distintas maneras:</p> + +<ul> + <li><em><strong>Teclado:</strong></em> <em><kbd>Ctrl</kbd>+<kbd>Mayús</kbd>+<kbd>I</kbd></em>, excepto en + + <ul> + <li><strong>Internet Explorer y Edge: </strong><kbd>F12</kbd></li> + <li><strong>macOS: </strong><em><span class="Unicode"><kbd>⌘</kbd>+<kbd>⌥</kbd>+<kbd>I</kbd></span></em></li> + </ul> + </li> + <li><span class="Unicode"><em><strong>Barra de menú:</strong></em></span> + <ul> + <li><strong>Firefox</strong>: Menú <img alt="Devtools" src="https://mdn.mozillademos.org/files/9637/2014-01-10-13-08-08-f52b8c.png" style="height: 16px; width: 16px;"><span class="Unicode"><em><span class="Unicode">➤ Desarrollador web</span></em> <em><span class="Unicode">➤ Alternar herramientas,</span> </em><span class="Unicode"> o </span> <em>➤ Herramientas</em></span> <em>➤ Alternar herramientas del desarrollador web</em></li> + <li><strong>Chrome:</strong> <em><span class="Unicode">Más herramientas</span> ➤ Herramientas del desarrollador</em></li> + <li><strong>Safari:</strong> <em><span class="Unicode">Desarrollador ➤</span> Mostrar el inspector web.</em> Si no puedes ver el menú <em>Desarrollar</em>, ve a <em>Safari<span class="Unicode"> ➤</span> Preferencias ➤ Avanzado</em> y marca la casilla de verificación <em>Mostrar menú desarrollador en la barra de menú</em>.</li> + <li><strong>Opera</strong>: <em><span class="Unicode">Desarrollador ➤ </span> Herramientas para desarrolladores</em></li> + </ul> + </li> + <li><strong><em>Menú contextual:</em></strong> Presiona y mantén presionado / haz clic con el botón derecho en un elemento en una página web (Ctrl-clic en Mac) y elige <em>Inspeccionar elemento</em> en el menú contextual que aparece. (<em>Una ventaja adicional:</em> este método, inmediatamente resalta el código del elemento en el que hiciste clic con el botón derecho).</li> +</ul> + +<p><img alt="Inspector" src="https://mdn.mozillademos.org/files/16206/inspector_context.png" style="display: block; height: 232px; margin: 0px auto; width: 350px;"></p> + +<h2 id="El_inspector_explorador_del_DOM_y_editor_CSS">El inspector: explorador del DOM y editor CSS</h2> + +<p>Las herramientas del desarrollador, generalmente se abren de forma predeterminada en el inspector, parecido a la siguiente captura de pantalla. Esta herramienta muestra cómo se ve el HTML en tu página en tiempo de ejecución, así como qué CSS se aplica a cada elemento de la página. También te permite modificar instantáneamente el HTML y CSS y ver los resultados de tus cambios reflejados en vivo en la ventana del navegador.</p> + +<p><img alt="Inspector resaltado" src="https://mdn.mozillademos.org/files/16208/inspector_highlighted.png" style="border-style: solid; border-width: 1px; display: block; height: 509px; margin: 0px auto; width: 672px;"></p> + +<p>Si <em>no</em> ves al inspector,</p> + +<ul> + <li>Toca o haz clic en la pestaña <em>Inspector</em>.</li> + <li>En Internet Explorer, toca/haz clic en <em>Explorador del DOM</em> o presiona <kbd>Ctrl</kbd>+<kbd>1</kbd>.</li> + <li>En Microsoft Edge u Opera, toca/haz clic en Elementos.</li> + <li>En Safari, los controles no se presentan con tanta claridad, pero deberías ver el HTML si no has seleccionado otra cosa para que aparezca en la ventana. Presiona el botón <em>Estilo</em> para ver el CSS.</li> +</ul> + +<h3 id="Explorando_el_DOM_con_el_inspector">Explorando el DOM con el inspector</h3> + +<p>Para empezar, haz clic con el botón derecho (Ctrl+clic) en un elemento HTML en el inspector del DOM y observa el menú contextual. Las opciones disponibles en el menú varían según el navegador, pero en su mayoría, las más importantes son las mismas:</p> + +<p><img alt="Inspector del DOM" src="https://mdn.mozillademos.org/files/16209/dom_inspector.png" style="border: 1px solid black; display: block; height: 320px; margin: 0px auto; width: 350px;"></p> + +<ul> + <li><strong>Eliminar nodo</strong> (A veces <em>Eliminar elemento</em>). Elimina el elemento actual.</li> + <li><strong>Editar como HTML</strong> (A veces <em>Agregar atributo</em>/<em>Editar texto</em>). Te permite cambiar el HTML y ver los resultados en tiempo real. Muy útil para depurar y probar.</li> + <li><strong>:hover/:active/:focus</strong>. Obliga a que se activen los estados de los elementos, para que puedas ver cómo se vería su estilo.</li> + <li><strong>Copiar/Copiar como HTML</strong>. Copie el HTML seleccionado actualmente.</li> + <li>Algunos navegadores también disponen de <em>Copiar ruta CSS</em> y <em>Copiar XPath</em>, para permitirte copiar el selector CSS o la expresión XPath que seleccionaría el elemento HTML actual.</li> +</ul> + +<p>Intenta editar algo de tu DOM ahora. Haz doble clic en un elemento o haz clic con el botón derecho del mouse y selecciona <em>Editar como HTML</em> en el menú contextual. Puedes realizar los cambios que desees, pero no los puedes guardar.</p> + +<h3 id="Explorar_el_editor_CSS">Explorar el editor CSS</h3> + +<p>De manera predeterminada, el editor CSS muestra las reglas CSS aplicadas al elemento seleccionado actualmente:</p> + +<p><img alt="Inspector CSS" src="https://mdn.mozillademos.org/files/16211/CSS_Inspector.png" style="display: block; height: 281px; margin: 0px auto; width: 500px;"></p> + +<p>Estas características son especialmente útiles:</p> + +<ul> + <li>Las reglas aplicadas al elemento actual se muestran en orden de mayor a menor especificidad.</li> + <li>Haz clic en las casillas de verificación junto a cada declaración para ver qué pasaría si eliminaras la declaración.</li> + <li>Haz clic en la pequeña flecha al lado de la abreviatura de cada propiedad para mostrar los nombres completos equivalentes de la propiedad.</li> + <li>Haz clic en el nombre o valor de una propiedad para que aparezca un cuadro de texto, donde puedes ingresar un nuevo valor para obtener una vista previa en vivo de un cambio de estilo.</li> + <li>Junto a cada regla está el nombre del archivo y el número de línea en el que se define la regla. Al hacer clic en esa regla, las herramientas de desarrollo saltan para mostrarlas en su propia vista, donde generalmente puedes editar y guardar.</li> + <li>También puedes hacer clic en la llave de cierre de cualquier regla para que aparezca un cuadro de texto en una nueva línea, donde puedes escribir una declaración completamente nueva para tu página.</li> +</ul> + +<p>Notarás una serie de pestañas en las que se puede hacer clic en la parte superior del Visor CSS:</p> + +<ul> + <li><em>Calculado</em>: Muestra los estilos calculados para el elemento seleccionado actualmente (los valores finales normalizados que aplica el navegador).</li> + <li><em>Diseño</em>: En Firefox, esta área incluye dos secciones: + <ul> + <li><em>Modelo de caja</em>: representa visualmente el modelo de caja del elemento actual, por lo que de un vistazo puedes identificar qué relleno, borde y margen se le aplica, y qué tan grande es su contenido.</li> + <li><em>Cuadrícula</em>: Si la página que estás inspeccionando utiliza Grid CSS, esta sección te permite ver los detalles de la cuadrícula.</li> + </ul> + </li> + <li><em>Fuentes</em>: En Firefox, la pestaña <em>Fuentes</em> muestra los tipos de letra aplicados al elemento actual.</li> +</ul> + +<h3 id="Conocer_más">Conocer más</h3> + +<p>Obtén más información sobre el Inspector en diferentes navegadores:</p> + +<ul> + <li><a href="https://developer.mozilla.org/es/docs/Tools/Page_Inspector">Inspector de páginas de Firefox.</a></li> + <li><a href="https://docs.microsoft.com/es-es/microsoft-edge/">Explorador del DOM de Edge.</a></li> + <li><a href="https://developers.google.com/web/tools/chrome-devtools/inspect-styles?utm_source=dcc&utm_medium=redirect&utm_campaign=2016q3">inspector del DOM de Chrome.</a> (el inspector de Opera funciona igual que este)</li> + <li><a href="https://developer.apple.com/library/safari/documentation/AppleApplications/Conceptual/Safari_Developer_Guide/ResourcesandtheDOM/ResourcesandtheDOM.html#//apple_ref/doc/uid/TP40007874-CH3-SW1">Safari inspector y explorador de estilos.</a></li> +</ul> + +<h2 id="El_depurador_de_JavaScript">El depurador de JavaScript</h2> + +<p>El depurador de JavaScript te permite observar el valor de las variables y establecer puntos de interrupción, lugares en tu código en los que deseas pausar la ejecución e identificar los problemas que impiden que tu código se ejecute correctamente.</p> + +<p><img alt="Depurador de Firefox" src="https://mdn.mozillademos.org/files/16239/firefox_debugger.png" style="border: 1px solid black; display: block; height: 556px; margin: 0 auto; width: 672px;"></p> + +<p>Para llegar al depurador:</p> + +<p><strong>Firefox</strong>: Selecciona <img alt="" src="https://mdn.mozillademos.org/files/9637/2014-01-10-13-08-08-f52b8c.png" style="height: 16px; width: 16px;"> ➤ <em>Desarrollador Web</em> ➤ <em>Depurador</em> o presiona <kbd>Ctrl</kbd>+<kbd>Mayús</kbd>+<kbd>S</kbd> para abrir el depurador de JavaScript. Si ya estás viendo las herramientas, haz clic en la pestaña <strong>Depurador</strong>.</p> + +<p><strong>Chrome</strong>: Abre las herramientas para desarrolladores y luego selecciona la pestaña <strong>Fuentes</strong>. (Opera funciona de la misma manera).</p> + +<p><strong>Edge e Internet Explorer 11</strong>: presiona <kbd>F12</kbd> y luego <kbd>Ctrl</kbd>+<kbd>3</kbd>, o si ya estás viendo las herramientas, haz clic en la pestaña Depurador.</p> + +<p><strong>Safari</strong>: Abre las herramientas para desarrolladores y luego selecciona la pestaña Depurador.</p> + +<h3 id="Explorando_el_depurador">Explorando el depurador</h3> + +<p>En Firefox hay tres paneles en el depurador de JavaScript.</p> + +<h4 id="Lista_de_archivos">Lista de archivos</h4> + +<p>El primer panel de la izquierda contiene la lista de archivos asociados con la página que estás depurando. Selecciona el archivo con el que deseas trabajar de esta lista. Haz clic en un archivo para seleccionarlo y ver su contenido en el panel central del depurador.</p> + +<p><img alt="Lista de archivos" src="https://mdn.mozillademos.org/files/16240/File_List.png" style="border: 1px solid black; display: block; height: 326px; margin: 0 auto; width: 350px;"></p> + +<h4 id="Código_fuente">Código fuente</h4> + +<p>Establece puntos de interrupción donde desees pausar la ejecución. En la siguiente imagen, el resaltado del número 18 muestra que la línea tiene un punto de interrupción establecido.</p> + +<p><img alt="Código fuente" src="https://mdn.mozillademos.org/files/16241/Source_code.png" style="border: 1px solid black; display: block; height: 251px; margin: 0 auto; width: 400px;"></p> + +<h4 id="Ver_expresiones_y_puntos_de_interrupción">Ver expresiones y puntos de interrupción</h4> + +<p>El panel de la derecha muestra una lista de las expresiones en observación que has agregado y los puntos de interrupción que has establecido.</p> + +<p>En la imagen, la primera sección, <strong>Ver expresiones</strong>, muestra que se ha agregado la variable <code>listItems</code>. Puedes expandir la lista para ver los valores del arreglo.</p> + +<p>La siguiente sección, <strong>Puntos de interrupción</strong>, enumera los puntos de interrupción establecidos en la página. En <code>example.js</code>, se ha establecido un punto de interrupción en la instrucción <code>listItems.push(inputNewItem.value);</code></p> + +<p>Las dos últimas secciones solo aparecen cuando el código se está ejecutando.</p> + +<p>La sección <strong>Pila de llamadas</strong> muestra qué código se ejecutó para llegar a la línea actual. Puedes ver que el código está en la función que maneja un clic del mouse y que el código está actualmente en pausa en el punto de interrupción.</p> + +<p>La sección final, <strong>Alcances</strong>, muestra qué valores son visibles desde varios puntos dentro de tu código. Por ejemplo, en la siguiente imagen, puedes ver los objetos disponibles para el código en la función <code>addItemClick</code>.</p> + +<p><img alt="ver elementos" src="https://mdn.mozillademos.org/files/16242/watch_items.png" style="border: 1px solid black; display: block; height: 743px; width: 350px;"></p> + +<h3 id="Conocer_más_2">Conocer más</h3> + +<p>Obtén más información sobre el depurador de JavaScript en diferentes navegadores:</p> + +<ul> + <li><a href="/es/docs/Tools/Debugger">Depurador de JavaScript en Firefox.</a></li> + <li><a href="https://docs.microsoft.com/es-es/microsoft-edge/devtools-guide/debugger">Depurador de Microsoft Edge.</a></li> + <li><a href="https://developers.google.com/web/tools/chrome-devtools/javascript/">Depurador de Chrome.</a></li> + <li><a href="https://developer.apple.com/safari/tools/">Depurador de Safari.</a></li> +</ul> + +<h2 id="La_consola_de_JavaScript">La consola de JavaScript</h2> + +<p>La consola de JavaScript es una herramienta increíblemente útil para depurar JavaScript que no funciona como se esperaba. Te permite ejecutar líneas de JavaScript en la página actualmente cargada en el navegador e informa los errores encontrados cuando el navegador intenta ejecutar tu código. Para acceder a la consola en cualquier navegador:</p> + +<p>Si las herramientas para desarrolladores ya están abiertas, haz clic o presiona la pestaña Consola.</p> + +<p>De lo contrario, Firefox te permite abrir la consola directamente usando <kbd>Ctrl</kbd>+<kbd>Mayús</kbd>+<kbd>K</kbd> o usando el comando del menú: Menú <img alt="" src="https://mdn.mozillademos.org/files/9637/2014-01-10-13-08-08-f52b8c.png" style="height: 16px; width: 16px;"> <span class="Unicode"> <em><span class="Unicode"> ➤ Desarrollador web</span></em> <em><span class="Unicode"> ➤ Consola web,</span></em> <span class="Unicode"> o</span> <em>Herramientas ➤</em></span> <em>Desarrollador web ➤ Consola web. </em>En otro navegador, abre las herramientas para desarrolladores y luego haz clic en la pestaña Consola.</p> + +<p>Esto te dará una ventana como la siguiente:</p> + +<p><img alt="Sólo consola" src="https://mdn.mozillademos.org/files/16212/console_only.png" style="border: 1px solid black; display: block; height: 187px; margin: 0px auto; width: 672px;"></p> + +<p>Para ver qué sucede, intenta ingresar los siguientes fragmentos de código en la consola uno por uno (y luego presiona Intro):</p> + +<ol> + <li> + <pre class="brush: js notranslate">alert('hello!');</pre> + </li> + <li> + <pre class="brush: js notranslate">document.querySelector('html').style.backgroundColor = 'purple';</pre> + </li> + <li> + <pre class="brush: js notranslate">const myWordmark = document.createElement('img'); +myWordmark.setAttribute('src','https://blog.mozilla.org/press/wp-content/themes/OneMozilla/img/mozilla-wordmark.png'); +document.querySelector('h1').appendChild(myWordmark);</pre> + </li> +</ol> + +<p>Ahora intenta ingresar las siguientes versiones incorrectas del código y ve lo que obtienes.</p> + +<ol> + <li> + <pre class="brush: js notranslate">alert('hello!);</pre> + </li> + <li> + <pre class="brush: js notranslate">document.cheeseSelector('html').style.backgroundColor = 'purple';</pre> + </li> + <li> + <pre class="brush: js notranslate">const myWordmark = document.createElement('img'); +myBanana.setAttribute('src','https://blog.mozilla.org/press/wp-content/themes/OneMozilla/img/mozilla-wordmark.png'); +document.querySelector('h1').appendChild(myWordmark);</pre> + </li> +</ol> + +<p>Comenzarás a ver el tipo de errores que devuelve el navegador. A menudo, estos errores son bastante crípticos, ¡pero debería ser bastante sencillo resolver estos problemas!</p> + +<h3 id="Conocer_más_3">Conocer más</h3> + +<p>Obtén más información sobre la consola de JavaScript en diferentes navegadores:</p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Tools/Web_Console">Consola Web de Firefox.</a></li> + <li><a href="https://docs.microsoft.com/es-es/microsoft-edge/devtools-guide-chromium">Consola de JavaScript Edge.</a></li> + <li><a href="https://developer.chrome.com/devtools/docs/console">Consola JavaScript de Chrome.</a> (el inspector de Opera funciona de la misma manera)</li> + <li><a href="https://developer.apple.com/library/safari/documentation/AppleApplications/Conceptual/Safari_Developer_Guide/Console/Console.html#//apple_ref/doc/uid/TP40007874-CH6-SW1">Consola en Safari.</a></li> +</ul> + +<h2 id="Ve_también">Ve también</h2> + +<ul> + <li><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">Depurar HTML.</a></li> + <li><a href="/es/docs/Learn/CSS/Introduction_to_CSS/Debugging_CSS">Depurar CSS.</a></li> +</ul> diff --git a/files/es/learn/common_questions/what_are_hyperlinks/index.html b/files/es/learn/common_questions/what_are_hyperlinks/index.html new file mode 100644 index 0000000000..dd1d28573d --- /dev/null +++ b/files/es/learn/common_questions/what_are_hyperlinks/index.html @@ -0,0 +1,91 @@ +--- +title: Qué son los hipervínculos? +slug: Learn/Common_questions/What_are_hyperlinks +translation_of: Learn/Common_questions/What_are_hyperlinks +--- +<div class="summary"> +<p>En este artículo, repasaremos qué son los hipervínculos y por qué son importantes.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Debes saber <a href="/en-US/Learn/How_the_Internet_works">how the Internet works</a> Y estar familiarizado con<a href="/en-US/docs/Learn/page_vs_site_vs_server_vs_search_engine"> the difference between a webpage, a website, a web server, and a search engine</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Conozca los enlaces en la web y por qué son importantes.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p>Los hipervínculos, generalmente llamados enlaces, son un concepto fundamental detrás de la Web. Para explicar qué son los enlaces, debemos retroceder a los conceptos básicos de la arquitectura web.</p> + +<p>En 1989, Tim Berners-Lee, el inventor de la Web, habló de los tres pilares en los que se basa la Web:</p> + +<ol> + <li>{{Glossary("URL")}}, un sistema de direcciones que realiza un seguimiento de los documentos web</li> + <li>{{Glossary("HTTP")}}, un protocolo de transferencia para encontrar documentos cuando se les da su URL</li> + <li>{{Glossary("HTML")}}, un formato de documento que permite hipervínculos incrustados</li> +</ol> + +<p>Como puede ver en los tres pilares, todo en la Web gira en torno a los documentos y cómo acceder a ellos. El propósito original de la Web era proporcionar una manera fácil de alcanzar, leer y navegar a través de documentos de texto. Desde entonces, la Web ha evolucionado para proporcionar acceso a imágenes, videos y datos binarios, pero estas mejoras apenas han cambiado los tres pilares.</p> + +<p>Antes de la Web, era bastante difícil acceder a los documentos y pasar de uno a otro. Al ser legibles por humanos, las URL ya facilitaron las cosas, pero es difícil escribir una URL larga cada vez que desee acceder a un documento. Aquí es donde los hipervínculos revolucionaron todo. Los enlaces pueden correlacionar cualquier cadena de texto con una URL, de modo que el usuario pueda alcanzar instantáneamente el documento de destino activando el enlace.</p> + +<p>Los enlaces se destacan del texto circundante al estar subrayados y en texto azul. Toque o haga clic en un enlace para activarlo, o si usa un teclado, presione Tab hasta que el enlace esté enfocado y presione Entrar o la barra espaciadora.</p> + +<p><img alt="Example of a basic display and effect of a link in a web page" src="https://mdn.mozillademos.org/files/8625/link-1.png" style="height: 492px; width: 477px;"></p> + +<p>Los enlaces son el avance que hizo que la Web fuera tan útil y exitosa. En el resto de este artículo, discutimos los diversos tipos de enlaces y su importancia para el diseño web moderno.</p> + +<h2 id="Profundizando">Profundizando</h2> + +<p>Como dijimos, un enlace es una cadena de texto vinculada a una URL, y usamos enlaces para permitir saltar fácilmente de un documento a otro. Dicho esto, hay algunos matices que vale la pena considerar:</p> + +<h3 id="Tipos_de_enlaces">Tipos de enlaces</h3> + +<dl> + <dt>Enlace interno</dt> + <dd>Un enlace entre dos páginas web, donde ambas páginas pertenecen al mismo sitio web, se denomina enlace interno. Sin enlaces internos, no existe un sitio web (a menos, por supuesto, que sea un sitio web de una página).</dd> + <dt>Enlace externo</dt> + <dd>Un enlace desde su página web a la página web de otra persona. Sin enlaces externos, no hay Web, ya que la Web es una red de páginas web. Utilice enlaces externos para proporcionar información además del contenido disponible a través de su página web.</dd> + <dt>Enlaces entrantes</dt> + <dd>Un enlace desde la página web de otra persona a su sitio. Es lo contrario de un enlace externo. Tenga en cuenta que no tiene que volver a vincular cuando alguien vincula a su sitio.</dd> +</dl> + +<p>Cuando esté creando un sitio web, concéntrese en los enlaces internos, ya que estos hacen que su sitio sea utilizable. Encuentre un buen equilibrio entre tener demasiados enlaces y muy pocos. Hablaremos sobre el diseño de la navegación del sitio web en otro artículo, pero como regla general, cada vez que agregue una nueva página web, asegúrese de que al menos una de sus otras páginas enlaza con esa nueva página. Por otro lado, si su sitio tiene más de aproximadamente diez páginas, es contraproducente vincular a cada página desde cualquier otra página.</p> + +<p>Cuando comienzas, no tienes que preocuparte tanto por los enlaces externos y entrantes, pero son muy importantes si quieres que los motores de búsqueda encuentren tu sitio (ver más abajo para más detalles).</p> + +<h3 id="Anclas">Anclas</h3> + +<p>La mayoría de los enlaces vinculan dos páginas web. Las anclas unen dos secciones de un documento. Cuando sigue un enlace que apunta a un ancla, su navegador salta a otra parte del documento actual en lugar de cargar un nuevo documento. Sin embargo, crea y utiliza anclajes de la misma manera que otros enlaces.</p> + +<p><img alt="Example of a basic display and effect of an anchor in a web page" src="https://mdn.mozillademos.org/files/8627/link-2.png" style="height: 492px; width: 477px;"></p> + +<h3 id="Enlaces_y_motores_de_búsqueda">Enlaces y motores de búsqueda</h3> + +<p>Los enlaces son importantes tanto para los usuarios como para los motores de búsqueda. Cada vez que los motores de búsqueda rastrean una página web, indexan el sitio web siguiendo los enlaces disponibles en la página web. Los motores de búsqueda no solo siguen enlaces para descubrir las distintas páginas del sitio web, sino que también usan el texto visible del enlace para determinar qué consultas de búsqueda son apropiadas para llegar a la página web de destino.</p> + +<p>Los enlaces influyen en la facilidad con que un motor de búsqueda se vinculará a su sitio. El problema es que es difícil medir las actividades de los motores de búsqueda. Las empresas, naturalmente, quieren que sus sitios tengan un alto ranking en los resultados de búsqueda. Sabemos lo siguiente acerca de cómo los motores de búsqueda determinan el rango de un sitio:</p> + +<ul> + <li>El texto visible de un enlace influye en qué consultas de búsqueda encontrarán una URL determinada.</li> + <li>Cuantos más enlaces entrantes pueda presumir una página web, más alto se ubica en los resultados de búsqueda.</li> + <li><em>Los enlaces externos influyen en el ranking de búsqueda de las páginas web de origen y destino, pero no está claro cuánto.</em></li> +</ul> + +<p><a href="http://en.wikipedia.org/wiki/Search_engine_optimization">SEO</a> (optimización de motores de búsqueda) es el estudio de cómo hacer que los sitios web tengan un alto ranking en los resultados de búsqueda. Mejorar el uso de enlaces de un sitio web es una técnica útil de SEO.</p> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<p>Ahora querrás configurar algunas páginas web con enlaces.</p> + +<ul> + <li>Para obtener más antecedentes teóricos, aprenda sobre <a href="/en-US/docs/Learn/Common_questions/What_is_a_URL">URLs y su estructura</a>, dado que todo enlace apunta a una URL.</li> + <li>¿Quieres algo un poco más práctico? El artículo <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">Creating hyperlinks</a> de nuestro módulo <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introducción a HTML</a> explica cómo implementar enlaces en detalle.</li> +</ul> diff --git a/files/es/learn/common_questions/what_is_a_domain_name/index.html b/files/es/learn/common_questions/what_is_a_domain_name/index.html new file mode 100644 index 0000000000..bc38251b25 --- /dev/null +++ b/files/es/learn/common_questions/what_is_a_domain_name/index.html @@ -0,0 +1,157 @@ +--- +title: ¿Qué es un nombre de dominio? +slug: Learn/Common_questions/What_is_a_domain_name +tags: + - Infraestructura + - Nombres de dominio + - Principiante + - Web +translation_of: Learn/Common_questions/What_is_a_domain_name +--- +<div class="summary"> +<p>En este artículo discutiremos acerca de los nombres de los dominios: qué son, cómo se estructuran y cómo conseguir uno.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Primero necesitas saber <a href="/en-US/docs/Learn/How_the_Internet_works">cómo funciona Internet</a> y entender <a href="/en-US/Learn/Understanding_URLs">qué son las URLs</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprende qué son los nombres de dominio, cómo funcionan, y por qué son importantes.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p><span class="seoSummary">Los nombres de dominio son una parte clave de la infraestructura de internet. Proporcionan una dirección legible para cualquier servidor web disponible en Internet.</span></p> + +<p><span class="seoSummary">Cualquier computadora conectada a Internet puede ser alcanzada a partir de una dirección {{Glossary("IP")}} pública, la cual puede estar formada por 32 bits para el protocolo IPv4 (por lo general se escribe con 4 números separados por puntos entre el 0 y 255, por ejemplo, <code>173.194.121.32</code>) o por 128 bits para la versión IPv6 (formada por 8 grupos de 4 números hexadecimales separados por dos puntos, ejemplo <code>2027:0da8:8b73:0000:0000:8a2e:0370:1337</code>). Las computadoras pueden manejar estas direcciones fácilmente, pero las personas pasan trabajo para saber de quien es el servidor o que servicio ofrece, ya que un número por sí solo no dice mucho. Además las direcciones IP son difíciles de recordar y pueden cambiarse en cualquier momento. Para resolver estos problemas se usan direcciones que las personas pueden leer, que son intuitivas, fáciles de recordar y dicen mucho sobre el servicio web que ofrecen, se denominan nombres de dominio. </span></p> + +<h2 id="Ánalisis_del_tema">Ánalisis del tema</h2> + +<h3 id="Estructura_de_los_nombres_de_dominio">Estructura de los nombres de dominio</h3> + +<p>Un nombre de dominio tiene una estructura simple formada por varias partes (puede tener solamente una parte, dos, tres,...), separadas por puntos y <strong>se leen de derecha a izquierda</strong>:</p> + +<p><img alt="Anatomy of the MDN domain name" src="https://mdn.mozillademos.org/files/11229/structure.png" style="height: 76px; width: 252px;"></p> + +<p>Cada una de estas partes provee información específica sobre el nombre de dominio completo.</p> + +<ul> + <li>TLDs l<span style="display: none;"> </span>ocales como <code>.us</code>, <code>.fr</code>, o <code>.se</code> pueden requerir el servicio en un determinado idioma o que esté alojado en un país específico - estan hecho para indicar que un recurso está en un idioma o país en particular.</li> + <li>Los TLDs que contienen <code>.gov</code> son solamente permitidos para ser usados por los departamentos de gobierno.</li> + <li>Los TLDs como <code>.edu</code> y <code>.ac</code> <code>.uk</code> se supone que se usen solamente en instituciones educacionales o académicas.</li> +</ul> + +<dl> + <dt>{{Glossary("TLD")}} (Top-Level Domain) Dominio de primer nivel.</dt> + <dd>El TLD proporciona la información más genérica. Los TLDs les dicen a usuarios el propósito general del servicio que se esconde tras el nombre de dominio. Los TLDs más genéricos (.com, .org, .net) no requieren que los servicios web cumplan ningún criterio particular, pero algunos TLDs hacen cumplir políticas más estrictas por lo que es más claro su propósito. Por ejemplo:</dd> + <dd><strong style="font-size: 1rem; font-weight: 700; letter-spacing: -0.00278rem;">Etiqueta (o componente)</strong></dd> + <dd>Las etiquetas son lo que siguen al TLD. Una etiqueta puede se cualquier cosa desde una letra hasta una oración completa. La etiqueta localizada a la derecha antes del TLD puede ser llamada también Dominio de Nivel Secundario, en inglés <em>Secondary Level Domain</em> (SLD). Un nombre de dominio puede tener muchas etiquetas (o componentes), no es obligatorio ni necesario tener tres etiquetas para formar un nombre de dominio. Por ejemplo, www.inf.ed.ac.uk es un nombre de dominio correcto. Para cualquier dominio sobre el que se tenga control (por ejemplo <a href="https://mozilla.org">mozilla.org</a>), uno puede crear otros nombres de dominio (a veces llamados "subdominios", por ejemplo <a href="https://developer.mozilla.org">developer.mozilla.org</a> o <a href="https://iot.mozilla.org/">iot.mozilla.org</a>).</dd> +</dl> + +<h3 id="Comprar_un_nombre_de_dominio">Comprar un nombre de dominio</h3> + +<h4 id="¿Quién_es_propietario_de_un_nombre_de_dominio">¿Quién es propietario de un nombre de dominio?</h4> + +<p>No se puede “comprar un nombre de dominio”. Se paga por el derecho de usar un nombre de dominio por uno o más años. Se pueden renovar los derechos y la renovación tiene prioridad sobre las aplicaciones de otras personas. Pero nuncá se podrá apropiar se un nombre de dominio. Una vez que deja de pagarlo queda libre para que otras personas puedan utilizarlo.</p> + +<p>Las compañías llamadas registradores utilizan los registros de nombres de dominio para realizar un seguimiento de la información técnica y administrativa que lo conecta con su nombre de dominio.</p> + +<div class="note"> +<p><strong>Nota : </strong>Para algunos nombres de dominio pudiera no ser un registrador quien esté a cargo de mantener el seguimiento. Por ejemplo, cada nombre de dominio bajo <code>.fire</code> es manejado por Amazon.</p> +</div> + +<h4 id="Encontrar_un_nombre_de_dominio_disponible">Encontrar un nombre de dominio disponible</h4> + +<p>Para encontrar si un nombre de dominio dado está disponible,</p> + +<ul> + <li>Ir a un sitio web de registro de nombres de dominio. La mayoría de ellos, tienen un servicio "whois" que te dice si un nombre de dominio está disponible.</li> + <li>Alternativamente, si usted usa un sistema con un shell incorporado, escriba el comando <code>whois</code>, como se muestra aquí para <code>mozilla.org</code>:</li> +</ul> + +<pre>$ whois mozilla.org +Domain Name:MOZILLA.ORG +Domain ID: D1409563-LROR +Creation Date: 1998-01-24T05:00:00Z +Updated Date: 2013-12-08T01:16:57Z +Registry Expiry Date: 2015-01-23T05:00:00Z +Sponsoring Registrar:MarkMonitor Inc. (R37-LROR) +Sponsoring Registrar IANA ID: 292 +WHOIS Server: +Referral URL: +Domain Status: clientDeleteProhibited +Domain Status: clientTransferProhibited +Domain Status: clientUpdateProhibited +Registrant ID:mmr-33684 +Registrant Name:DNS Admin +Registrant Organization:Mozilla Foundation +Registrant Street: 650 Castro St Ste 300 +Registrant City:Mountain View +Registrant State/Province:CA +Registrant Postal Code:94041 +Registrant Country:US +Registrant Phone:+1.6509030800 +</pre> + +<p>Como se observa, no se puede registrar <code>mozilla.org</code> porque la fundación de Mozilla ya ha sido registrada.</p> + +<p>Por otra parte, veamos si se puede registrar <code>afunkydomainname.org</code>:</p> + +<pre>$ whois afunkydomainname.org +NOT FOUND +</pre> + +<p>Como se observa, el dominio no existe en la base de datos de <code>whois</code> (en el momento que se escribió), por lo que pudiéramos pedir registrarlo. ¡Bueno para saber!</p> + +<h4 id="Obtener_un_nombre_de_dominio">Obtener un nombre de dominio</h4> + +<p>El proceso es bastante sencillo:</p> + +<ol> + <li>Ir a un sitio de registro.</li> + <li>Generalmente hay un letrero que llama la atención que dice “Get a domain name”. Hacer click en él.</li> + <li>Rellenar el formulario con todos los detalles requeridos. Asegúrese de no haber escrito incorrectamente el nombre de dominio deseado. ¡Una vez que esté pagado, es muy tarde!.</li> + <li>El registrador te permitirá conocer cuando un nombre de dominio esté correctamente registrado. Dentro de unas pocas horas, todos los servidores DNS habrán recibido su información de DNS.</li> +</ol> + +<div class="note"> +<p><strong>Nota:</strong> En este proceso se le pide su dirección real. Asegúrese de escribirla correctamente, ya que en algunos países los registradores pueden verse obligados a cerrar el dominio si no pueden proporcionar una dirección válida. </p> +</div> + +<h4 id="Actualización_de_DNS">Actualización de DNS </h4> + +<p>Las bases de datos DNS son almacenadas en cada servidor DNS del mundo, y todos ellos hacen referencia a unos pocos denominados "servidores de nombre autoritario" o "servidores DNS de primer nivel". Cuando su registrador crea o actualiza alguna información para un dominio dado, la información tiene que ser actualizada en cada base de datos DNS. Cada servidor DNS que conoce sobre un dominio dado almacena la información por algún tiempo antes de que sea automáticamente invalidada y luego actualizada ( el servidor DNS consulta un servidor autoritario nuevamente). De esta manera, a los servidores DNS que conocen este nombre de dominio les toma algún tiempo poner la información al día.</p> + +<div class="note"> +<p><strong>Nota :</strong> Este tiempo es amenudo llamado <strong>tiempo de propagación</strong> . Sin embargo, este término no es preciso puesto que la actualizaciónn no se está propagando en sí (primer nivel → nivel inferior). Los servidores DNS consultados por su computadora (nivel inferior) son los que obtienen la información del servidor autoritario(primer nivel) cuando lo necesitan. </p> +</div> + +<h3 id="¿Cómo_funciona_una_petición_DNS">¿Cómo funciona una petición DNS?</h3> + +<p>Como ya hemos visto, cuando usted quiere visualizar una página web en su navegador es más simple escribir un nombre de dominio que una dirección IP. Echemos un vistazo al proceso: </p> + +<ol> + <li>Escriba <code>mozilla.org</code> en la barra de direcciones de su navegador.</li> + <li>Su navegador le pregunta a su computadora si reconoce la dirección IP identificada por este nombre de dominio (usando una caché DNS local) Si lo hace, el nombre es traducido a la IP y el navegador gestiona el contenido con el servidor web. Fin de la historia.</li> + <li>Si la computadora no sabe qué IP está detrás del nombre <code>mozilla.org</code>, hay que pedírselo a un servidor DNS, cuyo trabajo es precisamente decirle a la computadora cuál es la dirección IP de cada nombre de dominio registrado.</li> + <li>Ahora que la computadora conoce la dirección IP requerida, su navegador puede gestionar contenidos con el servidor web.</li> +</ol> + +<p><img alt="Explanation of the steps needed to obtain the result to a DNS request" src="https://mdn.mozillademos.org/files/8961/2014-10-dns-request2.png" style="height: 702px; width: 544px;"></p> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<p>Bien, hemos hablado mucho sobre procesos y arquitectura. Es hora de seguir adelante.</p> + +<ul> + <li>Si quieres ponerte manos a la obra, es buen momento para comenzar a profundizar en el diseño y explorar <a href="/es/docs/Learn/Common_questions/dise%C3%B1os_web_comunes">la estructura de una página web</a>.</li> + <li>Vale la pena señalar que algunos aspectos de construcción de un sitio web cuestan dinero. Por favor, remítase a <a href="/en-US/docs/Learn/How_much_does_it_cost">cuánto cuesta construir un sitio web</a>.</li> + <li>O lea más sobre <a href="https://es.wikipedia.org/wiki/Dominio">Nombre de Dominio</a> en la Wikipedia.</li> + <li>Puede encontrar además <a href="https://howdns.works/">aquí</a> una explicación colorida y divertida de cómo los DNS trabajan.</li> +</ul> diff --git a/files/es/learn/como_contribuir/index.html b/files/es/learn/como_contribuir/index.html new file mode 100644 index 0000000000..6cc600f24d --- /dev/null +++ b/files/es/learn/como_contribuir/index.html @@ -0,0 +1,88 @@ +--- +title: ¿Cómo contribuir al Área de Aprendizaje en MDN? +slug: Learn/Como_Contribuir +tags: + - Aprender + - Documentación + - Guía + - MDN Meta + - Principiante + - contribuir + - 'l10n:priority' +translation_of: Learn/How_to_contribute +--- +<div>{{LearnSidebar}}</div> + +<p><br> + <span style="line-height: 1.5;">Si estás aqui, es probable que sea porque estas interesado en contribuir al área de aprendizaje de MDN. ¡Una noticia estupenda!</span></p> + +<p><span class="seoSummary">En esta página encontrarás todo lo que necesitas para comenzar ayudando a mejorar el contenido de aprendizaje en MDN. Hay muchas cosas que puedes hacer, dependiendo de cuanto tiempo tienes y de si eres <a href="/en-US/Learn/How_to_contribute#I'm_a_beginner">principiante</a>, <a href="/en-US/Learn/How_to_contribute#I'm_a_web_developer">desarrollador web</a>, o <a href="/en-US/Learn/How_to_contribute#I'm_a_teacher">profesor</a>.</span></p> + +<div class="note"> +<p><strong>Nota:</strong> Si ya eres colaborador de MDN, no dudes en volver a revisar la <a href="/en-US/docs/MDN/Doc_status/Learn">página de status de la documentación</a> para mantener un seguimiento del trabajo que se ha realizado y observar cuáles son nuestras prioridades de escritura.</p> +</div> + +<div class="note"> +<p><strong>Nota:</strong> Los colaboradores usan<a href="https://trello.com/b/LDggrYSV"> tableros de Trello</a> para organizar sus actividades. Si quieres usarlos, no tienes más que <a href="https://trello.com/signup">crearte una cuenta de Trello </a>y avisar a <a href="/en-US/docs/MDN/Contribute/Drivers_and_curators">Jeremie</a> para que te deje editar el tablero.</p> +</div> + +<h2 id="Soy_principiante">Soy principiante</h2> + +<p>¡Genial! Los principiantes son muy importantes y valiosos para crear y dar retroalimentación sobre el material de aprendizaje. Tú tienes una perspectiva única sobre estos artículos como miembro de la audiencia a la que están dirigidos, lo cual puede convertirte en un miembro de incalculable valor para nuestro equipo. De hecho, si estás aprendiendo algo de uno de nuestros artículos y te encuentras atascado, o tienes las sensación de que el artículo es algo confuso, puedes modificarlo tú mismo o simplemente informarnos para que podamos resolverlo.</p> + +<p>Colaborar es un gran modo de divertirse mientras se aprenden cosas nuevas. Si alguna vez te sientes perdido o tienes algunas preguntas, no dudes en contactarnos a través de <a href="/en-US/docs/MDN/Community#Join_our_mailing_lists">nuestra lista de correo </a>o <a href="/en-US/docs/MDN/Community#Get_into_IRC">nuestro canal IRC</a> (ve al final de la página para más detalles).</p> + +<p>A continuación puedes encontrar algunas formas de las que puedes contribuir:</p> + +<dl> + <dt><a href="/en-US/docs/MDN/Contribute/Howto/Tag">Añade etiquetas a nuestros artículos</a> (<em>5 min</em>)</dt> + <dd>Etiquetar contenido de MDN es una de las formas más sencillas de contribuir a MDN. Como muchas de las características de nuestra plataforma usan etiquetas para ayudar a presentar la información en contexto, la ayuda con el etiquetado es una contribución muy valiosa. Echa un vistazo a la lista de <a href="/en-US/docs/MDN/Doc_status/Glossary#No_tags">entradas del glosario</a> y a los <a href="/en-US/docs/MDN/Doc_status/Learn#No_tags">artículos de aprendizaje</a> sin etiquetas para comenzar.</dd> + <dt><a href="/en-US/docs/Glossary">Lee y revisa una entrada de glosario</a> (<em>15 min</em>)</dt> + <dd>Como principiante, necesitamos que tu vista fresca revise nuestro contenido. Si encuentras alguna entrada del glosario difícil de entender, significa que hay que mejorarla. No dudes en realizar cualquier cambio que estimes oportuno. Si crees que no tienes las habilidades adecuadas para editar la entrada, puedes contactarnos <span style="line-height: 1.5;">a través de </span><a href="/en-US/docs/MDN/Community#Join_our_mailing_lists" style="line-height: 1.5;">nuestra lista de correo</a>.</dd> + <dt><a href="/docs/MDN/Contribute/Howto/Write_a_new_entry_in_the_Glossary">Escribe una nueva entrada de glosario </a>(<em>1 hora</em>)</dt> + <dd>Esta es la forma más eficaz de aprender algo nuevo. Elige un concepto que quieras comprender y, mientras aprendes, escribe una entrada del glosario sobre dicho concepto. Explicar algo a otros es un buen modo de "fijar" el conocimiento a tu cerebro y de ayudarte a darle sentido a las cosas. Todo mientras ayudas a otras personas. ¡Gana todo el mundo!</dd> + <dt><a href="/en-US/Learn/Index">Lee y revisa un artículo de aprendizaje</a> (<em>2 horas</em>)</dt> + <dd>Esto es bastante similar a revisar entradas del glosario (ver arriba); aunque lleva más tiempo, ya que estos artículos son un poco más largos.</dd> +</dl> + +<h2 id="Soy_desarrollador_web">Soy desarrollador web</h2> + +<p>¡Fantástico! Tus habilidades técnicas son justo lo que necesitamos para asegurarnos de que proporcionamos contenido técnicamente preciso para los principiantes. Como esta parte específica de MDN está dedicada al aprendizaje de la web, asegúrate de explicar las cosas de la forma más sencilla posible. Pero procura no pasarte de sencillez, ya que entonces el contenido deja de ser útil. Es más importante que se comprenda a que sea innecesariamente preciso.</p> + +<dl> + <dt><a href="/en-US/docs/Glossary">Lee y revisa una entrada de glosario</a> (<em>15 min</em>)</dt> + <dd>Como desarrollador web, te necesitamos para asegurarnos de que nuestro contenido es técnicamente correcto sin ser demasiado pedante. No dudes en realizar cualquier cambio que creas necesario. Si quieres debatir sobre el contenido antes de editarlo, danos un toque<span style="line-height: 1.5;"> </span><a href="/en-US/docs/MDN/Community#Join_our_mailing_lists" style="line-height: 1.5;">a nuestra lista de correo</a> o al <a href="/en-US/docs/MDN/Community#Get_into_IRC">canal IRC</a>.</dd> + <dt><a href="/docs/MDN/Contribute/Howto/Write_a_new_entry_in_the_Glossary">Escribe una nueva entrada de glosario</a> (<em>1 hora</em>)</dt> + <dd>Clarificar nuestra jerga técnica es un muy buen modo de aprender y ser técnicamente preciso y simple. La gente con menos experiencia te lo agradecerá. Tenemos <a href="/en-US/docs/Glossary#Contribute">muchos términos indefinidos</a> que necesitan tu atención. Escoge uno y listo.</dd> + <dt><a href="/en-US/Learn/Index">Lee y revisa un artículo de aprendizaje</a> (<em>2 horas</em>)</dt> + <dd>Esto es lo mismo que revisar entradas del glosario (ver arriba); aunque lleva un poco más de tiempo, ya que estos artículos son un poco más largos.</dd> +</dl> + +<dl> + <dt><a href="/en-US/docs/MDN/Contribute/Howto/Write_an_article_to_help_learn_about_the_Web">Escribe un nuevo artículo de aprendizaje</a> (<em>4 horas</em>)</dt> + <dd>En MDN hacen falta artículos sencillos y prácticos sobre el uso de tecnologías web (<a href="/en-US/docs/Learn/CSS">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, <a href="/en-US/docs/Learn/JavaScript">JavaScript</a>, etc). Incluso tenemos contenido viejo en MDN que merece ser revisado y reformado. Lleva tus habilidades al límite para lograr que las tecnologías web puedan ser utilizadas incluso por principiantes.</dd> + <dt><a href="/en-US/docs/MDN/Contribute/Howto/Create_an_interactive_exercise_to_help_learning_the_web">Crea ejercicios, ejemplos de código o herramientas de aprendizaje interactivo</a> (<em>? horas</em>)</dt> + <dd>Todos nuestros artículos de aprendizaje requieren lo que nosotros llamamos materiales de "aprendizaje activo", porque la gente aprende mejor haciendo las cosas por sí mismos. Materiales como ejercicios o contenido interactivo que ayude a los usuarios a aplicar y manejar los conceptos detallados en un artículo. Hay muchas formas de crear contenido de aprendizaje activo, desde crear ejemplos de código con <a href="http://jsfiddle.net" rel="external">JSFiddle</a> o similares, hasta crear contenido interactivo completamente hackeable con <a href="https://thimble.webmaker.org/" rel="external">Thimble</a>. ¡Libera tu creatividad!</dd> +</dl> + +<h2 id="Soy_profesor">Soy profesor</h2> + +<p>MDN tiene un largo historial de excelencia técnica, pero necesitamos ayuda para mostrar el camino a los principiantes en conceptos técnicos. Aqué es donde entras tú, como profesor o educador. Puedes ayudarnos a asegurar que nuestro material se provee de forma adecuada y práctica para nuestros lectores.</p> + +<dl> + <dt><a href="/en-US/docs/Glossary">Lee y revisa una entrada en el glosario</a> (<em>15 min</em>)</dt> + <dd>Comprueba una entrada en el glosario y siéntete libre de hacer todos los cambios que creas que son necesarios. Si quieres discutir el contenido antes de editarlo, danos un toque en nuestra <a href="/en-US/docs/MDN/Community#Join_our_mailing_lists" style="line-height: 1.5;">lista de correo </a> or <a href="/en-US/docs/MDN/Community#Get_into_IRC">Canal de chat IRC</a>.</dd> + <dt><a href="/docs/MDN/Contribute/Howto/Write_a_new_entry_in_the_Glossary">Escribir una nueva entrada de glosario</a> (<em>1 hora</em>)</dt> + <dd><span id="result_box" lang="es"><span>Las definiciones simples y claras de los términos y las descripciones básicas de los conceptos en el glosario son fundamentales para satisfacer las necesidades de los principiantes.</span> <span>Su experiencia como educador puede ayudar a crear excelentes entradas de glosario;</span> <span>tenemos</span></span> <a href="/en-US/docs/Glossary#Contribute">muchos terminos indefinidos</a> que necesitan de su atención. Escoge uno y ve por él.</dd> + <dt><a href="/en-US/docs/tag/needsSchema">Añadir ilustraciones y/o esquemas a los artículos</a> (<em>1 hora</em>)</dt> + <dd>Como ya sabrás, Las ilustraciones son parte invaluable de cualquier contenido de aprendizaje. Esto es algo que generalmente falta en MDN y tus habilidades pueden haer la diferencia en esta área. Mira en los <a href="/en-US/docs/tag/needsSchema">artículos que le falan contenido ilustrativo</a> y escoge uno al que te gustaría crearle los gráficos.</dd> + <dt><a href="/en-US/Learn/Index">Leer y revisar un artículo de aprendizaje</a> (<em>2 horas</em>)</dt> + <dd><span id="result_box" lang="es"><span>Esto es similar a revisar las entradas del glosario (ver arriba), pero requiere más tiempo ya que los artículos son bastante más largos</span></span> .</dd> + <dt><a href="/en-US/docs/MDN/Contribute/Howto/Write_an_article_to_help_learn_about_the_Web">Escribir un nuevo artículo de aprendizaje</a> (<em>4 horas</em>)</dt> + <dd><span id="result_box" lang="es"><span title="We need simple, straightforward articles about the Web ecosystem and other functional topics around it.">Necesitamos artículos simples y directos sobre el ecosistema web y otros temas funcionales a su alrededor. </span><span title="Since these learning articles need to be educational rather than trying to literally cover everything there is to know, your experience in knowing what to cover and how will be a great asset. +">Dado que estos artículos de aprendizaje deben ser educativos en lugar de tratar de cubrir literalmente todo lo que hay que saber, su experiencia en saber qué cubrir y cómo será una gran ventaja</span></span>.</dd> + <dt><a href="/en-US/docs/MDN/Contribute/Howto/Create_an_interactive_exercise_to_help_learning_the_web">Crear ejercicios, cuestionarios o herramientas interactivas de aprendizaje</a> (<em>? horas</em>)</dt> + <dd><span id="result_box" lang="es"><span title='All our learning articles require what we call "active learning" materials.'>Todos nuestros artículos de aprendizaje requieren lo que llamamos materiales de "aprendizaje activo". </span><span title="Such materials are exercises or interactive content which help a user learn to use and expand upon the concepts detailed in an article.">Dichos materiales son ejercicios o contenido interactivo que ayudan al usuario a aprender a usar y ampliar los conceptos detallados en un artículo. </span><span title="There are lots of things you can do here, from creating quizzes to building fully hackable interactive content with Thimble.">Aquí puede hacer muchas cosas, desde crear concursos hasta crear contenido interactivo completamente pirateable con</span></span> <a href="https://thimble.webmaker.org/" rel="external">Thimble</a>. Da rienda suelta a tu creatividad!</dd> + <dt><a href="/en-US/docs/MDN/Contribute/Howto/Create_learning_pathways">Crea rutas de aprendizaje</a> (<em>? horas</em>)</dt> + <dd><span id="result_box" lang="es"><span title="In order to provide progressive and comprehensible tutorials, we need to shape our content into pathways.">Con el fin de proporcionar tutoriales progresivos y comprensibles, tenemos que dar forma a nuestro contenido en rutas. </span><span title="It's a way to gather existing content and figure out what is missing to create a learning article to write">Es una forma de recopilar contenido existente y descubrir lo que falta para crear un artículo de aprendizaje para escribir</span></span> .</dd> +</dl> diff --git a/files/es/learn/css/building_blocks/cascada_y_herencia/index.html b/files/es/learn/css/building_blocks/cascada_y_herencia/index.html new file mode 100644 index 0000000000..91a359181f --- /dev/null +++ b/files/es/learn/css/building_blocks/cascada_y_herencia/index.html @@ -0,0 +1,333 @@ +--- +title: Cascada y herencia +slug: Learn/CSS/Building_blocks/Cascada_y_herencia +translation_of: Learn/CSS/Building_blocks/Cascade_and_inheritance +--- +<div>{{LearnSidebar}}{{NextMenu("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks")}}</div> + +<p>El objetivo de este artículo es desarrollar la comprensión de algunos de los conceptos fundamentales de CSS (cascada, especificidad y herencia) que controlan cómo se aplica el CSS al HTML y cómo se resuelven los conflictos.</p> + +<p>A medida que avances en este apartado verás que puede resultar menos relevante y un poco más académico que otros artículos, pero la comprensión de estas cuestiones te ahorrará problemas más adelante. Te animamos a que trabajes meticulosamente este apartado y verifiques que entiendes los conceptos antes de continuar.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, HTML básico (véase <a href="https://developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y una idea de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender qué son la cascada y la especificidad, y cómo funciona la herencia en CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="Reglas_conflictivas">Reglas conflictivas</h2> + +<p>CSS significa <strong> hojas de estilo en cascada</strong> (cascading style sheets), y es muy importante entender la palabra <em>cascada</em>. La forma en que se comporta la cascada es la clave para comprender el CSS.</p> + +<p>En algún momento trabajarás en un proyecto y encontrarás que el CSS que pensabas que debería aplicarse a un elemento no funciona. Por lo general, el problema suele ser que has creado dos normas que podrían aplicarse al mismo elemento. La <strong>cascada</strong>, y el concepto estrechamente relacionado de <strong>especificidad</strong> son mecanismos que controlan qué regla se aplica cuando aparecen tales conflictos. Es posible que la regla que se apliuca finalmente a tu elemento no sea la que esperas, por lo que debes comprender cómo funcionan estos mecanismos.</p> + +<p>También es significativo el concepto de <strong>herencia</strong>, que significa que algunas propiedades CSS heredan por defecto los valores establecidos en el elemento padre, pero otras no. Esto también puede causar una respuesta diferente a la que esperas.</p> + +<p>Vamos a empezar por echar un vistazo rápido a los principales elementos que nos interesan, y a continuación veremos cómo interactúan entre sí y con tu CSS. Pueden resultar un poco difíciles de entender, pero a medida que practiques escribiendo CSS te resultará más fácil de entender la manera cómo funcionan.</p> + +<h3 id="Cascada">Cascada</h3> + +<p>En un primer nivel de simplicidad, la <strong>cascada</strong> en las hojas de estilo significa que el orden de las reglas importa en CSS: cuando dos reglas tienen la misma especificidad, se aplica la que aparece en último lugar en el CSS.</p> + +<p>En el ejemplo siguiente tenemos dos reglas que pueden aplicarse al <code>h1</code>. El <code>h1</code> acaba siendo de color azul porque estas normas tienen un selector idéntico y, por lo tanto, tienen la misma especificidad. Por esta razón, se aplica la última que aparece.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/cascade-simple.html", '100%', 400)}} </p> + +<h3 id="Especificidad">Especificidad</h3> + +<p>La especificidad es el modo que tiene el navegador de decidir qué regla se aplica si diversas reglas tienen selectores diferentes pero podrían aplicarse a un mismo elemento. Básicamente, la especificidad mide cuán específica es la selección de un selector:</p> + +<ul> + <li>Un selector de elemento es menos específico (selecciona todos los elementos de aquel tipo que aparecen en la página) por lo que presenta una puntuación más baja en especificidad.</li> + <li>Un selector de clase es más específico (selecciona solo los elementos de una página que tienen un valor de atributo <code>class</code> dado), y por tanto recibe una puntuación mayor.</li> +</ul> + +<p>Veamos un ejemplo. Aquí abajo encontrarás dos reglas que pueden aplicarse al elemento <code>h1</code>. Este elemento <code>h1</code> termina siendo de color rojo: el selector de clase confiere a esta regla una mayor especificidad, así que se aplicará a pesar de la regla para el selector de elemento que aparece más abajo en el orden del código.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/specificity-simple.html", '100%', 500)}} </p> + +<p>Profundizaremos en la especificidad más adelante.</p> + +<h3 id="Herencia">Herencia</h3> + +<p>La herencia también debe entenderse en este contexto: algunos valores de las propiedades CSS que se han establecido para los elementos padre los heredan los elementos hijo, pero otros no.</p> + +<p>Por ejemplo, si para un elemento se establece el color (<code>color</code>) y el tipo de letra (<code>font-family</code>), cada elemento que se encuentre dentro de él también se mostrará de ese color y con ese tipo de letra, a menos que les se haya aplicado un color y un tipo de letra diferentes directamente.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/inheritance-simple.html", '100%', 550)}} </p> + +<p>Algunas propiedades no se heredan. Por ejemplo, si para un elemento se establece un ancho {{cssxref("width")}} del 50%, sus descendientes no tendrán un 50% de ancho con respecto al de sus padres. Si este fuera el caso, ¡sería muy frustrante usar CSS!</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: En las páginas de referencia de las propiedades CSS de MDN encontrarás un cuadro con información técnica (por lo general, en la parte inferior de la sección de especificaciones) que enumera una serie de puntos sobre cada propiedad, incluyendo cuáles se heredan y cuáles no. Véase, por ejemplo, la <a href="/es/docs/Web/CSS/color#Especificaciones">sección de especificaciones de la propiedad color</a>.</p> +</div> + +<h2 id="Comprender_cómo_trabajan_juntos_estos_conceptos">Comprender cómo trabajan juntos estos conceptos</h2> + +<p>Estos tres conceptos controlan qué CSS se aplica a qué elemento. En las secciones siguientes veremos cómo funcionan en conjunto. A veces puede parecer un poco complicado, pero lo irás recordando a medida que ganes experiencia con el CSS, y siempre puedes consultar los detalles si se te olvidan. ¡Incluso los desarrolladores experimentados lo hacen!</p> + +<h2 id="Comprender_la_herencia">Comprender la herencia</h2> + +<p>Vamos a empezar con la herencia. En el ejemplo siguiente tenemos un elemento {{HTMLElement( "ul")}} con dos niveles de listas no ordenadas anidadas en él. Hemos establecido para el <code><ul></code> exterior un borde, un relleno y un color de fuente.</p> + +<p>El color se ha aplicado a los hijos directos y también a los hijos indirectos: los elementos hijo <code><li></code> inmediatos y los que están dentro de la primera lista. A continuación, hemos añadido a la segunda lista anidada una clase especial y le hemos aplicado un color diferente, que los elementos hijo de esta heredarán.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/inheritance.html", '100%', 700)}} </p> + +<p>La anchura (como se mencionó anteriormente), los márgenes, el relleno y los bordes no se heredan. Si los elementos hijo de nuestra lista heredaran los bordes, todas las listas y los elementos de lista ganarían un borde cada vez ¡y no es probable que vez quieras un efecto así!</p> + +<p>Las propiedades que se heredan por defecto y las que no son cuestión, en gran medida, de sentido común.</p> + +<h3 id="Control_de_la_herencia">Control de la herencia</h3> + +<p>CSS proporciona cuatro valores de propiedad universales especiales para el control de la herencia. Todas las propiedades CSS aceptan estos valores.</p> + +<dl> + <dt>{{cssxref("inherit")}}</dt> + <dd>Establece que el valor de la propiedad que se aplica a un elemento determinado sea exactamente igual al del elemento padre. En la práctica, esto "activa la herencia".</dd> + <dt>{{cssxref("initial")}}</dt> + <dd>Establece que el valor de la propiedad que se aplica a un elemento seleccionado tenga el mismo valor que esté establecido para esa propiedad en la hoja de estilo por defecto del navegador.</dd> + <dt>{{cssxref("unset")}}</dt> + <dd>Restablece la propiedad a su valor natural, lo que significa que si la propiedad se hereda de forma natural, actúa como <code>inherit</code>, y en caso contrario como <code>initial</code>.</dd> +</dl> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: También hay un valor más reciente, {{cssxref ("revert")}}, que todavía admiten pocos navegadores.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Véase la sección <a href="/en-US/docs/Web/CSS/Cascade#Origin_of_CSS_declarations" title="Este artículo explica qué es la cascada, el orden de la secuencia en cascada de las declaraciones CSS, y cómo esto afecta al desarrollador web.">El origen de las declaraciones CSS</a> en el artículo <a href="/en-US/docs/Web/CSS/Cascade" title=" Este artículo explica qué es la cascada, el orden de la secuencia en cascada de las declaraciones CSS, y cómo esto afecta al desarrollador web.">Introducción al concepto de cascada en CSS </a> para obtener más información sobre cada uno de estos valores y el modo en que funcionan.</p> +</div> + +<p>A continuación veremos una lista de enlaces y exploraremos cómo funcionan los valores universales. El ejemplo en vivo de abajo te permite jugar con el CSS y ver lo que sucede cuando se hacen cambios. Jugar con el código es la mejor forma de enfrentarse al HTML y el CSS.</p> + +<p>Por ejemplo:</p> + +<ol> + <li>Se ha aplicado la clase <code>my-class-1</code> al segundo elemento de lista. Esto establece por herencia el color del elemento <code><a></code> que está anidado en él. ¿Cómo cambia el color del enlace si quitamos esta regla?</li> + <li>¿Entiendes por qué el tercer y el cuarto enlace se ven de este color? En caso contrario, comprueba la descripción de los valores anteriores.</li> + <li>¿Cuál de los enlaces va a cambiar de color si se define un nuevo color para el elemento <code><a></code>, por ejemplo, <code>a { color: red; }</code>?</li> +</ol> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/keywords.html", '100%', 700)}} </p> + +<h3 id="Restablecer_todos_los_valores_de_propiedad">Restablecer todos los valores de propiedad</h3> + +<p>La propiedad CSS abreviada <code>all</code> se puede utilizar para aplicar uno de estos valores de herencia a (casi) todas las propiedades a la vez. Su valor puede ser cualquiera de los valores de herencia (<code>inherit</code>, <code>initial</code>, <code>unset</code>, o <code>revert</code>). Es una forma práctica de deshacer los cambios realizados respecto al estilo para que puedas volver a un punto de partida conocido antes de empezar a introducir cambios.</p> + +<p>En el ejemplo siguiente hay dos bloques de cita. El primero ya tiene un estilo aplicado al propio elemento de cita, mientras que el segundo tiene una clase aplicada al bloque de cita que establece el valor <code>all</code> en <code>unset</code>.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/all.html", '100%', 700)}} </p> + +<p>Prueba a establecer el valor de <code>all</code> al resto de valores disponibles y observa la diferencia.</p> + +<h2 id="Comprender_la_cascada">Comprender la cascada</h2> + +<p>Ahora entendemos por qué un párrafo que está anidado en la estructura del HTML es del mismo color que el CSS aplicado al cuerpo (<code>body</code>) del HTML y, a partir de los artículos de introducción sabemos cómo cambiar el CSS aplicado a algo en cualquier parte del documento, ya sea mediante la asignación de CSS a un elemento o la creación de una clase. Ahora vamos a echar un vistazo a la forma en que el concepto de cascada define qué reglas CSS se aplican cuando más de un elemento de estilo puede aplicar estilo a un elemento.</p> + +<p>Hay que considerar tres factores, que se enumeran a continuación en orden de importancia creciente. Los posteriores invalidan los anteriores:</p> + +<ol> + <li><strong>Orden en el código</strong></li> + <li><strong>Especificidad</strong></li> + <li><strong>Importancia</strong></li> +</ol> + +<p>Vamos a explicarlos para ver cómo los navegadores determinan exactamente que CSS deben aplicar.</p> + +<h3 id="Orden_en_el_código">Orden en el código</h3> + +<p>Ya hemos visto cómo el orden en el código es importante en el concepto de cascada. Si tienes más de una regla con exactamente el mismo peso, la que ocupa el último lugar en el CSS gana. Puedes entenderlo como que las reglas que están más cerca del elemento considerado sobreescriben las anteriores hasta que la última gana y da formato al elemento.</p> + +<h3 id="Especificidad_2">Especificidad</h3> + +<p>Una vez entendido el hecho de que el orden de los elementos en el código es importante, te encontrarás en alguna situación en la que sabes cuál es la última norma en la hoja de estilo, pero se aplica una regla anterior. Esto se debe a que la regla anterior tiene <strong>una especificidad mayor</strong>, es decir, es más específica y, por lo tanto, el navegador la escoge como la que debe dar forma al elemento.</p> + +<p>Como hemos visto anteriormente en este mismo artículo, un selector de clase tiene más peso que un selector de elemento, por lo que las propiedades que se definen en la clase tienen prioridad sobre las que se aplican directamente en el elemento.</p> + +<p>Un elemento que hay que tener en cuenta es que aunque pensamos en términos de selectores y reglas que se aplican a lo que estos seleccionan, no es toda la regla lo que se sobrescribe, sino solo las propiedades que entran en conflicto.</p> + +<p>Este comportamiento ayuda a evitar repeticiones en el CSS. Una práctica común es definir estilos genéricos para los elementos básicos y luego, crear clases para los elementos que son diferentes. Por ejemplo, en la hoja de estilo que mostramos a continuación hemos definido estilos genéricos para los encabezados de nivel 2; posteriormente hemos creado algunas clases que solo cambian algunas de las propiedades y los valores. Los valores definidos inicialmente se aplican a todos los encabezados, y entonces los valores más específicos se aplican a los encabezados con las clases.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/mixing-rules.html", '100%', 700)}} </p> + +<p>Ahora vamos a echar un vistazo a cómo el navegador calcula la especificidad. Ya sabemos que un selector de elemento tiene una especificidad baja y se puede sobrescribir con un elemento de clase. Esencialmente se otorga un valor de puntos a los diferentes tipos de selectores y la suma de estos establece la importancia de ese selector en particular, que a continuación puede evaluarse ante otras posibles coincidencias.</p> + +<p>La cantidad de especificidad de un selector se mide usando cuatro valores diferentes (o componentes), que pueden describirse como millares, centenas, decenas y unidades (cuatro dígitos individuales dispuestos en cuatro columnas):</p> + +<ol> + <li><strong>Millares</strong>: Se suma un punto en esta columna si la declaración está en un atributo de {{htmlattrxref ("style")}} o, como suelen denominarse, estilos en línea. Tales declaraciones no tienen selectores, por lo que su especificidad siempre es 1000.</li> + <li><strong>Centenas</strong>: Se suma un punto en esta columna por cada selector con ID particular que esté contenido en el selector general.</li> + <li><strong>Decenas</strong>: Se suma un punto en esta columna por cada selector de clase, de atributo o pseudoclase que estén contenidos en el selector general.</li> + <li><strong>Unidades</strong>: Se suma un punto en esta columna por cada selector o pseudoelemento que esté contenido en el selector general.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: El selector universal (<code>*</code>), los operadores de combinación (<code>+</code>, <code>></code>, <code>~</code>, ' ') y la pseudo-clase de negación (<code>:not</code>) no tienen ningún efecto sobre la especificidad.</p> +</div> + +<p>La tabla siguiente muestra algunos ejemplos concretos para ayudarte a entenderlo mejor. Analízalos y trata de entender por qué tienen la especificidad que les hemos dado. Aun no hemos explicado los selectores de forma detallada, pero puedes encontrar detalles de cada selector en los <a href="/es/docs/Web/CSS/Selectores_CSS">selectores de referencia</a> de MDN.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Millares:</th> + <th scope="col">Centenas:</th> + <th scope="col">Decenas:</th> + <th scope="col">Unidades:</th> + <th scope="col">Especificidad total</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>h1</code></td> + <td>0</td> + <td>0</td> + <td>0</td> + <td>1</td> + <td>0001</td> + </tr> + <tr> + <td><code>h1 + p::first-letter</code></td> + <td>0</td> + <td>0</td> + <td>0</td> + <td>3</td> + <td>0003</td> + </tr> + <tr> + <td><code>li > a[href*="en-US"] > .inline-warning</code></td> + <td>0</td> + <td>0</td> + <td>2</td> + <td>2</td> + <td>0022</td> + </tr> + <tr> + <td><code>#identifier</code></td> + <td>0</td> + <td>1</td> + <td>0</td> + <td>0</td> + <td>0100</td> + </tr> + <tr> + <td>Sin selector, con una regla en el atributo de un elemento {{htmlattrxref("style")}}</td> + <td>1</td> + <td>0</td> + <td>0</td> + <td>0</td> + <td>1000</td> + </tr> + </tbody> +</table> + +<p>Antes de continuar, vamos a ver un ejemplo:</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/specificity-boxes.html", '100%', 700)}} </p> + +<p>¿Qué pasa aquí? En primer lugar, estamos interesados solo en las primeras siete reglas de este ejemplo y, como te habrás dado cuenta, hemos incluido sus valores de especificidad en un comentario antes de cada una.</p> + +<ul> + <li>Los dos primeros selectores compiten sobre el estilo del color del fondo del vínculo (el segundo gana y por eso el color de fondo es azul, porque en la cadena hay un selector con ID particular extra: la especificidad es de 201 contra 101).</li> + <li>El tercer y el cuarto selector compiten sobre el estilo del color del texto del enlace (el segundo gana y hace que el texto sea blanco porque, aunque tiene un selector de elemento de menos, el selector que falta se sustituye por un selector de clase, con un valor de decena en vez de un valor de unidad). Así que la especificidad es de 113 contra 104.</li> + <li>Los selectores 5-7 compiten por el estilo del borde del vínculo cuando el cursor se desplaza sobre estos. El sexto selector pierde claramente ante el quinto con una especificidad de 23 contra 24. En la cadena hay un selector de elemento de menos. El séptimo selector, sin embargo, los supera a ambos: en la cadena hay el mismo número de estos subselectores que en el quinto, pero se ha intercambiado un elemento por un selector de clase. Así que la especificidad es de 33 contra 23 y 24.</li> +</ul> + +<ol> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Esto solo es un ejemplo aproximado para facilitar la comprensión. En realidad, cada tipo de selector tiene su nivel de especificidad propio, que no pueden sobrescribir los selectores con un nivel de especificidad menor. Por ejemplo, un <em>millar</em> de selectores de <strong>clase</strong> combinados no serían capaces de sobrescribir las reglas de <em>un</em> selector <strong>ID</strong>.</p> + +<p>Una forma más precisa de evaluar la especificidad sería anotar los niveles de especificidad individualmente de mayor a menor. Solo cuando hay empate entre las puntuaciones de los selectores dentro de un nivel especifico será necesario evaluar el nivel inferior siguiente; de lo contrario, puedes prescindir de los selectores de especificidad de los niveles inferiores, ya que nunca pueden sobrescribir los niveles de especificidad más altos.</p> +</div> + +<h3 id="Propiedad_!important">Propiedad <code>!important</code></h3> + +<p>Hay una pieza especial de CSS que se puede utilizar para anular todos los cálculos anteriores, sin embargo se debe tener mucho cuidado con su uso: <code>!important</code>. Se utiliza para convertir una propiedad y un valor particular en el elemento más específico, de modo que se invalidan las reglas normales de la cascada.</p> + +<p>Echa un vistazo a este ejemplo en el que se muestran dos párrafos, uno de los cuales tiene un elemento ID.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/cascade/important.html", '100%', 700)}} </p> + +<p>Vamos a observarlo con detenimiento para ver qué sucede. Elimina algunas de las propiedades para ver lo que sucede si te cuesta entender lo que ocurre:</p> + +<ol> + <li>Verás que se han aplicado los valores de {{cssxref("color")}} y {{cssxref("padding")}} de la tercera regla pero no el de {{cssxref("background-color")}}. ¿Por qué? Deberían haberse aplicado para los tres porque las reglas que se encuentran más adelante en el orden en el código fuente prevalecen sobre las reglas anteriores.</li> + <li>Sin embargo, ganan las reglas que están antes porque los selectores de clase tienen mayor especificidad que selectores de elemento.</li> + <li>En ambos bloques de código hay una clase {{htmlattrxref("class")}} con el valor <code>better</code>, pero en el segundo bloque de código hay un {{htmlattrxref("id")}} con el valor <code>winning</code>. Puesto que los identificadores tienen una especificidad <em>incluso mayor</em> que las clases (solo puede haber un elemento con un determinado ID en cada página, mientras que puede haber muchos elementos de la misma clase: los selectores ID son <em>muy específicos</em> con lo que delimitan), el primer bloque de código tendría un fondo de color gris y ningún borde, según lo que especifica la clase, mientras que al segundo bloque de código se aplicarían tanto el color de fondo rojo como el borde negro de 1 píxel.</li> + <li>El segundo elemento, en cambio, se muestra con el fondo de color rojo pero sin borde. ¿Por qué? Porque la declaración <code>!important</code> que hay en la segunda regla, después de <code>border: none</code> significa que esta declaración tendrá más valor que la regla anterior, aunque el ID de esta tenga mayor especificidad.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: La única manera de anular la declaración <code>!important</code> sería incluir otra declaración <code>!important</code> en una declaración con la <em>misma especificidad</em> que aparezca más adelante en el orden del código fuente, o con una especificidad superior.</p> +</div> + +<p>Es útil saber que <code>!important</code> existe para que sepas qué es cuando te lo encuentres en el código de otras personas. <strong>Sin embargo, te recomendamos encarecidamente que no lo utilices a menos que sea absolutamente necesario.</strong> <code>!important</code> cambia el modo en que suele funcionar la cascada, por lo que puede dificultar mucho la depuración de problemas en el CSS, especialmente en una hoja de estilo grande.</p> + +<p>Una situación en la que puede que tengas que utilizarlo es si trabajas en un CMS en el que no es posible editar los módulos básicos de CSS y realmente tienes que anular un estilo que no puede anularse de ninguna otra forma. Aun así, te recomendamos encarecidamente que evites su uso.</p> + +<h2 id="El_efecto_de_la_ubicación_del_CSS">El efecto de la ubicación del CSS</h2> + +<p>Por último, resulta útil señalar que la importancia de una declaración CSS depende de la hoja de estilo en que se especifica (es posible que los usuarios configuren hojas de estilo personalizadas para anular los estilos de los desarrolladores, por ejemplo, porque el usuario podría tener alguna discapacidad visual, o bien porque desea configurar el tamaño de letra de todas las páginas web que visita para que sea el doble de grande y le proporcione una mayor facilidad de lectura).</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Las declaraciones contradictorias se aplicarán en el orden siguiente (recuerda que las últimas prevalecen sobre las anteriores):</p> + +<ol> + <li>Declaraciones en las hojas de estilo de agente de usuario (por ejemplo, estilos predeterminados del navegador, que se utilizan cuando no hay otro estilo).</li> + <li>Declaraciones normales en las hojas de estilo del usuario (estilos personalizados creados por un usuario).</li> + <li>Declaraciones normales en las hojas de estilo de autor (los estilos que creamos nosotros, los desarrolladores web).</li> + <li>Declaraciones <code>!important</code> en las hojas de estilo de autor</li> + <li>Declaraciones <code>!important</code> en las hojas de estilo del usuario</li> +</ol> + +<p>Para los desarrolladores tiene sentido que sus hojas de estilo anulen a las de usuario para mantener el diseño según lo previsto, pero, como hemos visto, a veces los usuarios tienen buenas razones para anular las directrices de los desarrolladores web. Esto puede lograrse con el uso de <code>!important</code> en sus reglas.</p> + +<h2 id="Pon_a_prueba_tus_habilidades">Pon a prueba tus habilidades</h2> + +<p>Hemos cubierto mucho terreno en este artículo. ¿Recuerdas la información más importante? Encontrarás más pruebas para verificar que retienes esa einformación en <a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_tasks">Test your skills: the Cascade</a>.</p> + +<h2 id="¿Qué_sigue">¿Qué sigue?</h2> + +<p>Si has entendido la mayor parte de este artículo, ¡enhorabuena! Has comenzado a familiarizarte con la mecánica fundamental del CSS. En el artículo siguiente vamos a ver con detalle los selectores.</p> + +<p>Si todavía no tienes una comprensión completa de los conceptos de cascada, especificidad y herencia, ¡no te preocupes! Es, sin duda, lo más complejo que hemos expuesto hasta ahora y es algo que incluso los desarrolladores web profesionales encuentran difícil. Te aconsejamos que regreses a este artículo cuantas veces necesites a medida que avances con el curso.</p> + +<p>Regresa a esta página si empiezas a toparte con problemas extraños o con que los estilos no se aplican de la forma que esperas. Podría ser un problema de especificidad.</p> + +<p>{{NextMenu("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">La cascada y la herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudo-clases y los pseudo-elementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Operadores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de caja</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario </a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/contenido_desbordado/index.html b/files/es/learn/css/building_blocks/contenido_desbordado/index.html new file mode 100644 index 0000000000..808a519c12 --- /dev/null +++ b/files/es/learn/css/building_blocks/contenido_desbordado/index.html @@ -0,0 +1,123 @@ +--- +title: Contenido desbordado +slug: Learn/CSS/Building_blocks/Contenido_desbordado +translation_of: Learn/CSS/Building_blocks/Overflowing_content +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Handling_different_text_directions", "Learn/CSS/Building_blocks/Values_and_units", "Learn/CSS/Building_blocks")}}</div> + +<p>En este artículo veremos otro concepto importante en CSS: el <strong>desbordamiento</strong>. El desbordamiento es lo que sucede cuando hay demasiado contenido para que pueda caber cómodamente en una caja. En esta guía aprenderás qué es y cómo administrarlo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, conocimientos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con el CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender el desbordamiento y cómo gestionarlo.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_el_desbordamiento">¿Qué es el desbordamiento?</h2> + +<p>Ya sabemos que todo en CSS está dentro de una caja, y que podemos restringir el tamaño de estas cajas asignándoles los valores {{cssxref ("width")}} y {{cssxref ("height")}} (o {{cssxref("inline-size")}} y {{cssxref("block-size")}}). <strong>El desbordamiento es lo que sucede cuando hay demasiado contenido en una caja, y no cabe cómodamente en ella.</strong> El CSS te proporciona varias herramientas para administrar este desbordamiento, y además es un concepto que resulta útil de conocer desde las primeras etapas. Te encontrarás con situaciones de desbordamiento con bastante frecuencia al escribir CSS, especialmente cuando profundices en compaginación con CSS.</p> + +<h2 id="El_CSS_trata_de_evitar_«la_pérdida_de_datos»">El CSS trata de evitar «la pérdida de datos»</h2> + +<p>Vamos a comenzar con dos ejemplos que demuestran cómo se comporta el CSS por defecto cuando ocurre un desbordamiento.</p> + +<p>El primero consiste en una caja que a la que se le ha restringido la dimensión al darle una altura. Luego hemos añadido más contenido del que cabe en la caja. El contenido se desborda y se distribuye desordenadamente sobre el párrafo que hay debajo de la caja.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/overflow/block-overflow.html", '100%', 600)}}</p> + +<p>El segundo consiste en una palabra dentro de una caja cuya dimensión en línea está restringida. La caja se ha hecho demasiado pequeña para que esa palabra quepa, y se desborda.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/overflow/inline-overflow.html", '100%', 500)}}</p> + +<p>Te debes estar preguntando por qué el CSS ha tomado por defecto el enfoque más bien desarreglado de provocar el desbordamiento desordenado del contenido. ¿Por qué no ocultar el contenido adicional o hacer crecer la caja?</p> + +<p>Siempre que sea posible, el CSS no oculta su contenido; hacerlo provocaría la pérdida de datos, que generalmente es un problema. En términos de CSS, esto significa que una parte del contenido desaparece. El problema con que desaparezca contenido es que podría ser que no notaras que ha desaparecido. Tus visitantes podrían no darse cuenta de que ha desaparecido contenido. Si se trata del botón de envío de datos en un formulario, nadie podría completar el formulario, y ¡eso es un gran problema! Así que, en vez de esto, el CSS tiende a desbordarse de un modo que sea visible. Es probable que te des cuenta de ese desarreglo, o en el peor de los casos, que un visitante de tu sitio web te informe de que una parte del contenido se superpone y debas arreglarlo.</p> + +<p>Si has restringido el tamaño de una caja con una anchura o una altura determinadas, el CSS asume que sabes lo que haces y que gestionas correctamente el potencial de desbordamiento. En general, restringir el tamaño de un bloque es problemático cuando el texto se va a poner en una caja, porque puede haber más texto del que te esperabas al diseñar el sitio o el tamaño del texto puede ser mayor, por ejemplo, si el usuario lo aumenta.</p> + +<p>En los artículos siguientes veremos diferentes modos de controlar el tamaño que podrían ser menos propensos a desbordarse. Sin embargo, si necesitas un tamaño fijo, también puedes controlar cómo se comporta el desbordamiento. ¡Sigue leyendo!</p> + +<h2 id="La_propiedad_overflow">La propiedad <code>overflow</code></h2> + +<p>La propiedad {{cssxref ("overflow")}} es el modo como tomas el control del desbordamiento de un elemento y le dices al navegador cómo desea que se comporte. El valor predeterminado para la propiedad <code>overflow</code> es <code>visible</code>, por lo que, de forma predeterminada vamos a poder ver cuándo se desborda nuestro contenido.</p> + +<p>Si deseas cortar el contenido cuando se desborda, puedes establecer el valor <code>overflow: hidden</code> en tu caja, que hace exactamente lo que dice: ocultar el desbordamiento. Esto puede hacer que las cosas desaparezcan, por lo que solo debes utilizar esta opción si ocultar contenido no te va a causar ningún problema.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/overflow/hidden.html", '100%', 600)}}</p> + +<p>Quizás te gustaría añadir barras de desplazamiento cuando el contenido se desborde. Si usas <code>overflow: scroll</code>, tu navegador siempre mostrará barras de desplazamiento, incluso cuando no haya suficiente contenido para que pueda desbordarse. Es posible que desees hacer esto, porque evita que aparezcan y desaparezcan barras de desplazamiento según el contenido.</p> + +<p><strong>Si en la caja siguiente eliminas parte del contenido, observarás que las barras de desplazamiento permanecen aun sin que haya nada que desplazar (o, como mucho, solo las pistas de la barra de desplazamiento).</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/overflow/scroll.html", '100%', 600)}}</p> + +<p>En el ejemplo anterior solo necesitamos desplazarnos en el eje <code>y</code>, sin embargo, obtenemos barras de desplazamiento en ambos ejes. En su lugar, puedes usar la propiedad {{cssxref ("overflow-y")}}, y establecer <code>overflow-y: scroll</code> para poder desplazarte solo por el eje <em>y</em>.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/overflow/scroll-y.html", '100%', 600)}}</p> + +<p>También puedes desplazarte por el eje <em>x</em> usando {{cssxref ("overflow-x")}}, aunque esta no es una forma recomendada para manejar palabras largas. Si necesitas lidiar con una palabra larga en una caja pequeña, puedes consultar las propiedades {{cssxref ("word-break")}} o {{cssxref ("overflow-wrap")}}. Además, algunos de los métodos expuestos en el artículo <a href="/es/docs/Learn/CSS/Building_blocks/Dimensionar_elementos_en_CSS">Elementos de dimensionado en CSS</a> pueden ayudarte a crear cuadros que se adapten mejor a cantidades variables de contenido.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/overflow/scroll-x.html", '100%', 500)}}</p> + +<p>Al igual que con el desplazamiento, obtendrás una barra de desplazamiento en la dimensión de desplazamiento independientemente de si hay suficiente contenido para provocar una barra de desplazamiento.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: observa que puedes especificar un desplazamiento en <em>x</em> y en <em>y</em> utilizando la propiedad <code>overflow</code> y pasando dos valores. Si especificas dos palabras clave, la primera se aplica a <code>overflow-x</code> y la segunda a <code>overflow-y</code>. De lo contrario, tanto <code>overflow-x</code> como <code>overflow-y</code> se fijan en el mismo valor. Por ejemplo, <code>overflow: scroll hidden</code> establece <code>overflow-x</code> en <code>scroll</code> y <code>overflow-y</code> en <code>hidden</code>.</p> +</div> + +<p>Si deseas que aparezcan barras de desplazamiento solo si hay más contenido del que cabe en la caja, utiliza <code>overflow: auto</code>. En este caso, el navegador decide si muestra las barras de desplazamiento o no. Los navegadores de escritorio solo suelen hacerlo cuando hay contenido suficiente para causar desbordamiento.</p> + +<p><strong>En el ejemplo siguiente, elimina parte del contenido hasta que quepa en la caja y observarás que las barras de desplazamiento desaparecen.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/overflow/auto.html", '100%', 600)}}</p> + +<h2 id="overflow_establece_un_contexto_de_formato_de_bloque"><code>overflow</code> establece un contexto de formato de bloque</h2> + +<p>En CSS hay un concepto conocido como <strong>block formatting context</strong> o BFC (<em>contexto de formato de bloque</em>). No es algo de lo que debas preocuparte demasiado en este momento, pero es útil saber que cuando usas un valor de <code>overflow</code>, como <code>scroll</code> o <code>auto</code>, creas un BFC. El resultado es que el contenido de la caja al que acabas de cambiar el valor <code>overflow</code> se convierte en un minidiseño propio. Las cosas que están fuera del contenedor no pueden meterse en él, y nada puede sobresalir de esa caja hacia el diseño circundante. Esto es para permitir un comportamiento con desplazamiento, porque para poder crear una experiencia de desplazamiento consistente todo el contenido de tu caja ha de estar contenido en algo, y no puede superponerse con otros elementos de la página.</p> + +<h2 id="Desbordamiento_no_deseado_en_diseño_web">Desbordamiento no deseado en diseño web</h2> + +<p>Los métodos de diseño modernos (explicados en el módulo <a href="/es/docs/Learn/CSS/CSS_layout">Diseñar con el CSS</a>) gestionan muy bien el desbordamiento. Han sido diseñados para hacer frente al hecho de que tendemos a no poder predecir cuánto contenido habrá en la web. Sin embargo, en el pasado, los desarrolladores a menudo usaban alturas fijas para tratar de alinear los fondos de cajas que en realidad no tenían relación entre sí. Este método era frágil y, en una aplicación heredada, ocasionalmente puede aparecer una caja en que el contenido se superpone a otro contenido de la página. Si ves esto, sabrás que se trata de desbordamiento. Lo ideal sería volver a calcular el diseño para no tener que confiar tamaños de caja fijos.</p> + +<p>Al desarrollar un sitio web, siempre debes tener en cuenta los problemas de desbordamiento. Debes probar diseños con cantidades grandes y pequeñas de contenido, aumentar el tamaño de letra... y asegurarte de que tu CSS puede hacerle frente sin ningún problema. Es probable que cambiar el valor de <code>overflow</code> para ocultar contenido o añadir barras de desplazamiento sea algo que debas reservar solo para unos pocos casos especiales, en que realmente desees una caja con barra de desplazamiento, por ejemplo.</p> + +<h2 id="Pon_a_prueba_tus_conocimientos">Pon a prueba tus conocimientos</h2> + +<p>Hay mucho que absorber en esta lección. ¿Recuerdas la información más importante? Para comprobarlo, ve a <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Overflow_Tasks">Test your skills: overflow</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Este breve artículo ha introducido el concepto de desbordamiento; ahora comprendes que el CSS intenta no hacer invisible el desbordamiento de contenido, porque esto provoca la pérdida de datos. Has descubierto que puedes gestionar el desbordamiento potencial y también que debes probar tu trabajo para asegurarte de que no causa un desbordamiento problemático accidentalmente.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Handling_different_text_directions", "Learn/CSS/Building_blocks/Values_and_units", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascada y herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Selectores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de cajas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Valores y unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Estilo de las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/depurar_el_css/index.html b/files/es/learn/css/building_blocks/depurar_el_css/index.html new file mode 100644 index 0000000000..5f04fdd756 --- /dev/null +++ b/files/es/learn/css/building_blocks/depurar_el_css/index.html @@ -0,0 +1,198 @@ +--- +title: Depurar el CSS +slug: Learn/CSS/Building_blocks/Depurar_el_CSS +translation_of: Learn/CSS/Building_blocks/Debugging_CSS +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Styling_tables", "Learn/CSS/Building_blocks/Organizing", "Learn/CSS/Building_blocks")}}</div> + +<p>Al escribir CSS te puedes encontrar que, a veces, alguna parte de tu CSS no hace lo que esperas. Tal vez creas que cierto selector debería coincidir con un elemento, pero no sucede nada; o una caja tiene un tamaño diferente al que esperabas. Este artículo te orientará sobre cómo solucionar un problema de CSS y te mostrará cómo las DevTools incluidas en todos los navegadores modernos pueden ayudarte a descubrir qué sucede.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, HTML básico (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con el CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Conocer los conceptos básicos de las DevTools que hay en los navegadores y de cómo inspeccionar y editar el CSS de un modo fácil.</td> + </tr> + </tbody> +</table> + +<h2 id="Cómo_acceder_a_las_DevTools_de_los_navegadores">Cómo acceder a las DevTools de los navegadores</h2> + +<p>El artículo <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">¿Qué son las herramientas de desarrollo de los navegadores?</a> es una guía actualizada que explica cómo acceder a las herramientas en varios navegadores y plataformas. Si bien puedes optar por desarrollar principalmente en un navegador en particular y, por lo tanto, te familiarizarás más con las herramientas incluidas en ese navegador, vale la pena saber cómo acceder a ellas en otros navegadores. Esto ayudará si haces pruebas de las representaciones que dan diferentes navegadores.</p> + +<p>También te darás cuenta de que los diversos navegadores han optado por centrarse en áreas diferentes al crear sus DevTools. Por ejemplo, en Firefox hay algunas herramientas excelentes para trabajar visualmente con la compaginación con CSS, que te permiten inspeccionar y editar <a href="/es/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts">Compaginaciones de cuadrícula</a>, <a href="/en-US/docs/Tools/Page_Inspector/How_to/Examine_Flexbox_layouts">Flexbox</a> y <a href="/en-US/docs/Tools/Page_Inspector/How_to/Edit_CSS_shapes">formas</a>. Sin embargo, todos los navegadores tienen herramientas fundamentales similares. Por ejemplo, para inspeccionar las propiedades y los valores que se aplican a los elementos de tu página, y hacer cambios desde el editor.</p> + +<p>En este artículo veremos algunas características útiles de Firefox DevTools para trabajar con CSS. Para hacerlo, usaremos <a href="https://mdn.github.io/css-examples/learn/inspecting/inspecting.html">un archivo de ejemplo</a>. Carga esto en una pestaña nueva si deseas seguir adelante y abre tus DevTools como se describe en el artículo del enlace anterior.</p> + +<h2 id="El_DOM_y_View_Source">El DOM y "View Source"</h2> + +<p>Algo que puede hacer tropezar a los recién llegados a DevTools es la diferencia entre lo que ves cuando <a href="/es/docs/Tools/View_source">miras el código fuente</a> de una página web, o miras el archivo HTML que colocas en el servidor, y lo que puedes ver en la <a href="/es/docs/Tools/Page_Inspector/UI_Tour#Panel_HTML">ventana HTML</a> de DevTools. Aunque ves más o menos lo mismo que puedes ver desde View Source (Ver código fuente de la página), hay algunas diferencias.</p> + +<p>En el DOM procesado, el navegador puede haber corregido algunos HTML mal escritos por ti. Si cerraste un elemento incorrectamente, por ejemplo, por abrir con un <code><h2></code> y cerrar con un <code></h3></code>, el navegador descubre lo que ibas a hacer y el HTML del DOM cerrará ese <code><h2></code> de apertura correctamente con un <code></h2></code>. El navegador también normaliza todo el HTML, y el DOM también muestra los cambios que hace JavaScript.</p> + +<p>En comparación, View Source es simplemente el código fuente HTML tal como está almacenado en el servidor. El <a href="/es/docs/Tools/Page_Inspector/How_to/Examinar_y_editar_HTML#%C3%81rbol_HTML">árbol HTML</a> de tus DevTools muestra exactamente lo que el navegador representa en un momento dado, y te da una idea de lo que sucede en realidad.</p> + +<h2 id="Inspección_del_CSS_aplicado">Inspección del CSS aplicado</h2> + +<p>Selecciona un elemento de tu página, ya sea haciendo clic con el botón derecho o pulsando la tecla ctrl para seleccionar la opción <em>Inspect</em>, o seleccionándolo del árbol HTML que hay a la izquierda de la pantalla de la interfaz DevTools. Selecciona el elemento con la clase <code>box1</code>; este es el primer elemento de la página con una caja alrededor.</p> + +<p><img alt="La página de ejemplo para este tutorial con DevTools abiertas." src="https://mdn.mozillademos.org/files/16606/inspecting1.png" style="border-style: solid; border-width: 1px; height: 1527px; width: 2278px;"></p> + +<p>Si observasla <a href="/es/docs/Tools/Page_Inspector/UI_Tour#Panel_CSS">vista de reglas</a>, que está a la derecha de tu HTML, deberías poder ver las propiedades y los valores CSS aplicados sobre ese elemento. Verás las reglas aplicadas directamente a la clase <code>box1</code> y también el CSS que la caja hereda de su elemento padre, en este caso <code><body></code>. Esto es útil para cuando ves que se aplica un CSS que no esperabas. Tal vez se esté heredando de un elemento padre y necesites añadir una regla para sobrescribirlo en el contexto de este elemento.</p> + +<p>También es útil la capacidad de expandir las propiedades abreviadas. En nuestro ejemplo se usa la abreviación <code>margin</code>.</p> + +<p><strong>Haz clic en la pequeña flecha para expandir la vista, que muestra las diferentes propiedades sin abreviar y sus valores.</strong></p> + +<p><strong>Puedes activar y desactivar los valores en la vista de reglas, cuando ese panel esté activo; si mantienes el ratón sobre él, aparecerán casillas de verificación. Desmarca la casilla de verificación de una regla, por ejemplo <code>border-radius</code>, y el CSS dejará de aplicarse.</strong></p> + +<p>Puedes usar esto para hacer una comparación entre A y B, decidir si algo se ve mejor con una regla aplicada o sin aplicar, y también para ayudar a depurarlo. Por ejemplo, si un diseño falla e intentas determinar qué propiedad causa el problema.</p> + +<h2 id="Editar_valores">Editar valores</h2> + +<p>Además de activar y desactivar las propiedades, puedes editar sus valores. ¿Quieres ver si quizá otro color se ve mejor, o deseas modificar algún tamaño? Las DevTools pueden ahorrarte mucho tiempo a la hora de editar una hoja de estilo y volver a cargar la página.</p> + +<p><strong>Selecciona <code>box1</code> y haz clic en la muestra (el pequeño círculo de color) que muestra el color aplicado al borde. Se abrirá un selector de color y puedes probar con colores diferentes, que se actualizarán en tiempo real en la página. De manera similar puedes cambiar el ancho o el estilo del borde.</strong></p> + +<p><img alt="Ventana de aplicación de estilos de DevTools con un selector de color abierto." src="https://mdn.mozillademos.org/files/16607/inspecting2-color-picker.png" style="border-style: solid; border-width: 1px; height: 1173px; width: 2275px;"></p> + +<h2 id="Añadir_una_propiedad_nueva">Añadir una propiedad nueva</h2> + +<p>Puedes añadir propiedades usando las DevTools. ¿Te has dado cuenta de que quizá no quieres que tu caja herede el tamaño de letra del elemento <code><body></code> y quieres establecer tu propio tamaño de letra específico? Pruébalo en DevTools antes de añadirlo a tu archivo CSS.</p> + +<p><strong>Puedes hacer clic en la llave de cierre de la regla para comenzar a introducir una declaración nueva, y en ese momento puedes comenzar a escribir la nueva propiedad y DevTools te mostrará una lista de propiedades coincidentes que se completará automáticamente. Después de seleccionar <code>font-size</code>, introduce el valor que deseas probar. También puede hacer clic en el botón + para añadir una regla adicional con el mismo selector y tus reglas nuevas.</strong></p> + +<p><img alt="La ventana DevTools, que añade una propiedad nueva a las reglas, con el autocompletado para font-open" src="https://mdn.mozillademos.org/files/16608/inspecting3-font-size.png" style="border-style: solid; border-width: 1px; height: 956px; width: 2275px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: También hay otras funciones útiles en la vista de reglas; por ejemplo, las declaraciones con valores no válidos están tachadas. Puedes obtener más información en <a href="/es/docs/Tools/Page_Inspector/How_to/Examine_and_edit_CSS">Examinar y editar CSS</a>.</p> +</div> + +<h2 id="Comprender_el_modelo_de_cajas">Comprender el modelo de cajas</h2> + +<p>En artículos anteriores hemos expuesto el <a href="/es/docs/Learn/CSS/Building_blocks/El_modelo_de_caja">modelo de cajas</a>, y el hecho de que tengamos un modelo de cajas alternativo que cambia la forma en que se calcula el tamaño de los elementos en función del tamaño que les asignas, más el relleno y los bordes. Las DevTools realmente pueden ayudarte a comprender cómo se calcula el tamaño de un elemento.</p> + +<p><a href="/es/docs/Tools/Page_Inspector/UI_Tour#Panel_CSS">El panel de disposición</a> muestra un diagrama del modelo de cajas en el elemento seleccionado, junto con una descripción de las propiedades y los valores que cambian la forma en que el elemento se presenta. Esto incluye una descripción de las propiedades que puedes no haber utilizado explícitamente en el elemento, pero que tienen valores iniciales establecidos.</p> + +<p>En esta ventana, una de las propiedades que se detallan es la propiedad <code>box-sizing</code>, que controla qué modelo de cajas usa el elemento.</p> + +<p><strong>Compara las dos cajas con las clases <code>box1</code> y <code>box2</code>. Ambas tienen el mismo ancho aplicado (400 px), sin embargo, <code>box1</code> es visualmente más ancha. En la ventana de diseño puedes ver que usa <code>content-box</code>. Este es el valor que toma el tamaño que asignas al elemento y luego añade el área de relleno y el ancho del borde.</strong></p> + +<p>El elemento con una clase <code>box2</code> usa <code>border-box</code>, por lo que aquí el área de relleno y el borde se restan del tamaño que has asignado al elemento. Esto significa que el espacio que la caja ocupa en la página es el tamaño exacto que se ha especificado, en nuestro caso <code>width: 400px</code>.</p> + +<p><img alt="La ventana de diseño de DevTools" src="https://mdn.mozillademos.org/files/16609/inspecting4-box-model.png" style="border-style: solid; border-width: 1px; height: 1532px; width: 2275px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Descubre más en <a href="/es/docs/Tools/Page_Inspector/How_to/Examinar_y_editar_el_modelo_de_cajasmodel">Examinar e inspeccionar el modelo de cajas</a>.</p> +</div> + +<h2 id="Resolver_problemas_de_especificidad">Resolver problemas de especificidad</h2> + +<p>A veces, durante el desarrollo, pero en particular cuando necesitas editar el CSS de un sitio ya publicado, te resultará difícil conseguir que se aplique un determinado CSS. No importa lo que hagas, el elemento simplemente no parece aceptar tu CSS. Lo que suele suceder aquí es que un selector más específico anula tus cambios, y en este caso DevTools te será de gran ayuda.</p> + +<p>En nuestro archivo de ejemplo hay dos palabras incluidas en un elemento <code><em></code>. Uno se muestra en color naranja y el otro en rosa. En el CSS hemos aplicado:</p> + +<pre class="brush: css notranslate">em { + color: hotpink; + font-weight: bold; +}</pre> + +<p>Sin embargo, un poco más arriba en la hoja de estilo hay una regla con un selector <code>.special</code>:</p> + +<pre class="brush: css notranslate">.special { + color: orange; +}</pre> + +<p>Como recordarás del artículo sobre <a href="/es/docs/Learn/CSS/Building_blocks/Cascada_y_herencia"> cascada y herencia</a>, en que hablamos sobre la especificidad, los selectores de clase son más específicos que los selectores de elemento, por lo que este es el valor que se aplica. DevTools puede ayudarte a encontrar estos problemas, especialmente si la información está oculta en algún lugar de una extensa hoja de estilo.</p> + +<p><strong>Inspecciona <code><em></code> con la clase <code>.special</code> y DevTools te mostrará que el naranja es el color que se aplica, y también te muestra la propiedad <code>color</code> aplicada al em tachado. Aquí puedes ver que la clase anula el selector de elemento.</strong></p> + +<p><img alt="Selecciona un em y mira en DevTools qué solapa el color." src="https://mdn.mozillademos.org/files/16610/inspecting5-specificity.png" style="border-style: solid; border-width: 1px; height: 1161px; width: 2275px;"></p> + +<h2 id="Descubre_más_sobre_las_DevTools_de_Firefox">Descubre más sobre las DevTools de Firefox</h2> + +<p>Hay mucha información aquí en MDN sobre las DevTools de Firefox. Echa un vistazo a la <a href="/es/docs/Tools">sección principal de las DevTools</a>, y consulta las <a href="/es/docs/Tools/Page_Inspector#How_to">Guías prácticas</a> para obtener información más detallada sobre las cosas que hemos expuesto brevemente en este artículo.</p> + +<h2 id="Problemas_al_depurar_en_CSS">Problemas al depurar en CSS</h2> + +<p>Las DevTools pueden ser de gran ayuda a la hora de resolver problemas con el CSS, pero ¿cómo resuelves una situación en la que el CSS no se comporta como esperas? Los siguientes pasos deberían ayudarte.</p> + +<h3 id="Aléjate_del_problema">Aléjate del problema</h3> + +<p>Cualquier problema de código puede ser frustrante, especialmente los problemas de CSS, porque a menudo no recibes un mensaje de error que buscar en línea para ayudarte a encontrar una solución. Si te sientes frustrado, aléjate del problema por un tiempo: sal a caminar, tómate una copa, habla con un compañero de trabajo o trabaja en otra cosa por un tiempo. A veces, la solución aparece mágicamente cuando dejas de pensar en el problema, e incluso si no llega, trabajar en ello cuando te sientas más fresco te será mucho más fácil.</p> + +<h3 id="¿Tu_HTML_y_CSS_son_válidos">¿Tu HTML y CSS son válidos?</h3> + +<p>Los navegadores esperan que tu CSS y HTML estén escritos correctamente, sin embargo, los navegadores también son muy indulgentes y harán todo lo posible para mostrar tus páginas web incluso si tiene errores en el marcado o en la hoja de estilo. Si tienes errores en el código, el navegador trata de adivinar lo que quieres decir, y podría tomar una decisión diferente a lo que tenías en mente. Además, dos navegadores diferentes pueden hacer frente al problema de dos maneras diferentes. Por lo tanto, un buen primer paso es pasar tu HTML y CSS por un validador, que detectar cualquier error.</p> + +<ul> + <li><a href="https://jigsaw.w3.org/css-validator/">Validador de CSS</a></li> + <li><a href="https://validator.w3.org/">Validador de HTML</a></li> +</ul> + +<h3 id="¿La_propiedad_y_el_valor_son_compatibles_con_el_navegador">¿La propiedad y el valor son compatibles con el navegador?</h3> + +<p>Los navegadores simplemente ignoran el CSS que no entienden. Si la propiedad o el valor que utilizas no es compatible con el navegador en el que lo pruebas, no se romperá nada, pero ese CSS no se aplicará. Las DevTools en general destacan de alguna manera las propiedades y los valores que no son compatibles. En la captura de pantalla siguiente, el navegador no admite el valor de subcuadrícula {{cssxref ("grid-template-columns")}}.</p> + +<p><img alt="Imagen de las DevTools del navegador con la cuadrícula-plantilla-columnas: subcuadrícula tachada porque el valor de la subcuadrícula no es compatible." src="https://mdn.mozillademos.org/files/16641/no-support.png" style="height: 397px; width: 1649px;"></p> + +<p>También puedes echar un vistazo a las tablas de compatibilidad de navegadores en la parte inferior de cada página de propiedades del proyecto MDN. Te muestran la compatibilidad de cada navegador para esa propiedad, a menudo desglosado si hay compatibilidad para un uso de la propiedad y no para otros. La tabla siguiente muestra los datos de compatibilidad para la propiedad {{cssxref ("shape-outside")}}.</p> + +<p>{{compat("css.shape-outside")}}</p> + +<h3 id="¿Hay_algo_más_que_anule_tu_CSS">¿Hay algo más que anule tu CSS?</h3> + +<p>Aquí es donde la información que has aprendido sobre la especificidad será muy útil. Si tienes algo más específico que anula lo que intentas hacer, puedes entrar en un juego muy frustrante de tratar de resolverlo sin saber qué tienes que resolver. Sin embargo, como hemos dicho, las DevTools te mostrarán qué CSS se ha aplicado y así puedes averiguar cómo hacer que el nuevo selector sea lo suficientemente específico como para anularlo.</p> + +<h3 id="Haz_un_caso_de_prueba_reducido_del_problema">Haz un caso de prueba reducido del problema</h3> + +<p>Si el problema no se resuelve con los pasos anteriores, deberás investigar un poco más. Lo mejor que puedes hacer en este momento es crear lo que se conoce como un caso de prueba reducido. Ser capaz de «reducir un problema» es una habilidad muy útil. Te ayudará a encontrar problemas en tu propio código y en el de tus colegas, y también te permitirá informar de errores y solicitar ayuda de manera más efectiva.</p> + +<p>Un caso de prueba reducido es un ejemplo de código que muestra el problema de la manera más simple posible, sin contenido ni estilo circundante. Esto significa a menudo sacar el código problemático de tu diseño para hacer un pequeño ejemplo que solo muestre ese código o característica.</p> + +<p>Para crear un caso de prueba reducido:</p> + +<ol> + <li>Si tu marcado se genera dinámicamente, por ejemplo desde un CMS, crea una versión estática de la salida que muestre el problema. Un sitio para compartir código como <a href="https://codepen.io/">CodePen</a> es útil para alojar casos de prueba reducidos, porque son accesibles en línea y puedes compartirlos fácilmente con tus colegas. Puedes comenzar por hacer un View Source de la página y copiar el HTML en CodePen, luego toma cualquier CSS y JavaScript relevante e inclúyelo también. Después de eso, puedes verificar si el problema sigue ahí.</li> + <li>Si eliminar el JavaScript no soluciona el problema, no incluyas el JavaScript. Si eliminar el JavaScript hace desaparecer el problema, elimina la mayor cantidad de JavaScript que puedas; deja solo las causas del problema.</li> + <li>Elimina cualquier HTML que no contribuya al problema. Elimina componentes o incluso elementos principales del diseño. Nuevamente, intenta reducir al mínimo la cantidad de código que aún muestra el problema.</li> + <li>Elimina cualquier CSS que no afecte al problema.</li> +</ol> + +<p>En el proceso, puedes descubrir qué causa el problema, o al menos ser capaz de ponerlo o quitarlo al eliminar algo específico. Vale la pena añadir algunos comentarios a tu código a medida que vas descubriendo cosas. Si tienes que pedir ayuda, estos comentarios indicarán a la persona que te ayuda lo que ya has intentado. Esto puede proporcionarte bastante información para permitirte buscar posibles problemas por sondeo y soluciones alternativas.</p> + +<p>Si todavía tienes dificultades para solucionar el problema, tener un caso de prueba reducido te ofrece algo con lo que pedir ayuda, publicarlo en un foro o mostrarlo a un compañero de trabajo. Es mucho más probable que obtengas ayuda si antes de pedir la ayuda muestras que has hecho el trabajo de reducir el problema e identificar dónde sucede exactamente. Un desarrollador más experimentado va a poder detectar el problema con rapidez y orientarte en la dirección correcta, y aunque no sea así, echarle un vistazo rápido a tu caso de prueba reducido y, con suerte, ofrecerte al menos algo de ayuda.</p> + +<p>En el caso de que tu problema sea en realidad un error en un navegador, también puedes usar un caso de prueba reducido para presentar un informe de error al proveedor del navegador correspondiente (por ejemplo, en el sitio de <a href="https://bugzilla.mozilla.org">Bugzilla</a> de Mozilla).</p> + +<p>A medida que adquieras más experiencia con CSS, descubrirás que vas adquiriendo rapidez para descubrir de dónde vienen los problemas. Sin embargo, incluso los más experimentados a veces nos preguntamos qué pasa. Adoptar un enfoque metódico, hacer un caso de prueba reducido y explicar el problema a otra persona suele dar un buen resultado para encontrar una solución.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Styling_tables", "Learn/CSS/Building_blocks/Organizing", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascada y herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Selectores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de cajas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/dimensionar_elementos_en_css/index.html b/files/es/learn/css/building_blocks/dimensionar_elementos_en_css/index.html new file mode 100644 index 0000000000..81759abccc --- /dev/null +++ b/files/es/learn/css/building_blocks/dimensionar_elementos_en_css/index.html @@ -0,0 +1,129 @@ +--- +title: Dimensionar elementos en CSS +slug: Learn/CSS/Building_blocks/Dimensionar_elementos_en_CSS +translation_of: Learn/CSS/Building_blocks/Sizing_items_in_CSS +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Values_and_units", "Learn/CSS/Building_blocks/Images_media_form_elements", "Learn/CSS/Building_blocks")}}</div> + +<p>En los diversos artículos vistos hasta ahora, has aprendido varias formas de dimensionar elementos en una página web utilizando CSS. Es importante que comprendas qué tamaños van a tener los diferentes elementos de tu diseño, y en este artículo vamos a resumir las diversas formas en que puedes asignar tamaños a los elementos con CSS y definir algunos términos relativos al dimensionado que te ayudarán en el futuro.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, HTML básico (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender las diferentes formas en que podemos dimensionar las cosas en CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="El_tamaño_natural_o_intrínseco_de_las_cosas">El tamaño natural o intrínseco de las cosas</h2> + +<p>Los elementos HTML tienen un tamaño natural, establecido antes de que se vean afectados por cualquier código CSS. Un ejemplo sencillo es una imagen. Una imagen tiene un ancho y una altura que están definidos en el archivo de imagen que está incrustando en la página. Este tamaño se describe como el <strong>tamaño intrínseco</strong>, que proviene de la imagen misma.</p> + +<p>Si colocas una imagen en una página y no cambias su altura y ancho, ya sea usando atributos en la etiqueta <code><img></code> o el CSS, se mostrará con ese tamaño intrínseco. En el ejemplo siguiente le hemos dado un borde a la imagen para que puedas ver la extensión del archivo.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/sizing/intrinsic-image.html", '100%', 600)}}</p> + +<p>Sin embargo, un elemento {{htmlelement ("div")}} vacío no tiene tamaño propio. Si añades un elemento {{htmlelement ("div")}} sin contenido a tu HTML, entonces debes darle un borde como hemos hecho con la imagen y verás una línea en la página. Se trata del borde del elemento replegado sobre sí mismo porque no hay contenido para mantenerlo abierto. En nuestro ejemplo siguiente, ese borde se extiende por todo el ancho del contenedor, porque es un elemento de nivel de bloque, un comportamiento con el que deberías comenzar a familiarizarte. No tiene altura (o tamaño en la dimensión de bloque) porque no hay contenido.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/sizing/intrinsic-text.html", '100%', 500)}}</p> + +<p>En el ejemplo anterior, añade texto al elemento vacío. Ahora el borde contiene ese texto porque la altura del elemento queda definida por el contenido. Por lo tanto, el tamaño de este elemento <code><div></code> en la dimensión del bloque proviene del tamaño del contenido. Nuevamente, este es el tamaño intrínseco del elemento: su tamaño está definido por su contenido.</p> + +<h2 id="Configurar_un_tamaño_específico">Configurar un tamaño específico</h2> + +<p>Por supuesto, podemos dar a los elementos de nuestro diseño un tamaño específico. Cuando asignas un tamaño a un elemento (al cual deberá ajustarse el contenido del elemento) nos referimos a este como <strong>tamaño extrínseco</strong>. Toma nuestro elemento <code><div></code> del ejemplo anterior: podemos darle valores específicos como {{cssxref ("width")}} y {{cssxref ("height")}}, y así tendrá ese tamaño sea cual sea su contenido. Como descubrimos en <a href="/es/docs/Learn/CSS/Building_blocks/Contenido_desbordado">nuestro artículo anterior sobre el desbordamiento</a>, una altura establecida puede causar el desbordamiento del contenido si hay más contenido del que cabe en el elemento.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/sizing/height.html", '100%', 600)}}</p> + +<p>Debido a este problema de desbordamiento, fijar la altura de los elementos con longitudes o porcentajes es algo que debemos hacer con mucho cuidado en la web.</p> + +<h3 id="El_uso_de_porcentajes">El uso de porcentajes</h3> + +<p>En muchos sentidos, los porcentajes actúan como unidades de longitud, y como discutimos en el <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS#Porcentajes">artículo sobre valores y unidades</a>, a menudo se pueden usar indistintamente con longitudes. Cuando usas un porcentaje, debes tener claro de qué es porcentaje. En el caso de una caja dentro de otro contenedor, si a la caja secundaria le asignas un porcentaje al ancho, será un porcentaje del ancho del contenedor principal.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/sizing/percent-width.html", '100%', 600)}}</p> + +<p>Esto se debe a que los porcentajes se refieren al tamaño del bloque contenedor. Sin un porcentaje aplicado, nuestro elemento <code><div></code> ocuparía el 100% del espacio disponible, porque es un elemento de nivel de bloque. Si le damos un ancho porcentual, este se convierte en un porcentaje del espacio que normalmente ocuparía.</p> + +<h3 id="Porcentaje_de_márgenes_y_áreas_de_relleno">Porcentaje de márgenes y áreas de relleno</h3> + +<p>Si configuras <code>margins</code> y <code>padding</code> como un porcentaje, puede que observes un comportamiento extraño. En el ejemplo siguiente hay una caja. Hemos asignado a la caja interna un margen ({{cssxref ("margin")}}) del 10% y una área de relleno ({{cssxref ("padding")}}) del 10%. El área de relleno y el margen de la parte superior e inferior de la caja son del mismo tamaño que el margen de la izquierda y de la derecha.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/sizing/percent-mp.html", '100%', 700)}}</p> + +<p>Podrías esperar, por ejemplo, que el porcentaje de los márgenes superior e inferior sea un porcentaje de la altura del elemento, y el porcentaje de los márgenes izquierdo y derecho sea un porcentaje del ancho del elemento. Sin embargo, ¡este no es el caso!</p> + +<p>Cuando utilizas el margen y el área de relleno en porcentajes, el valor se calcula a partir del <strong>tamaño en línea</strong> del elemento, es decir, el ancho del elemento cuando se trabaja en un lenguaje horizontal. En nuestro ejemplo, todos los márgenes y el área de relleno son del 10% del ancho del elemento. Esto significa que puedes tener márgenes y relleno alrededor de la caja del mismo tamaño. Este es un hecho que vale la pena recordar si utilizas porcentajes de esta manera.</p> + +<h2 id="Tamaños_mínimo_y_máximo">Tamaños mínimo y máximo</h2> + +<p>Además de asignar a las cosas un tamaño fijo, podemos pedirle al CSS que asigne a un elemento un tamaño mínimo o máximo. Si tienes una caja que puede contener una cantidad variable de contenido y deseas que tenga siempre <em>al menos</em> una altura determinada, puedes establecer la propiedad {{cssxref ("min-height")}}. La caja siempre tendrá al menos esta altura, pero crecerá si hay más contenido del que la caja puede contener.</p> + +<p>En el ejemplo siguiente puedes ver dos cuadros, ambos con una altura definida de 150 píxeles. La caja de la izquierda tiene 150 píxeles de alto; la de la derecha contiene contenido que necesita más espacio, por lo que su tamaño supera los 150 píxeles.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/sizing/min-height.html", '100%', 800)}}</p> + +<p>Esto es muy útil para trabajar con cantidades de contenido variables y asimismo evitar desbordamientos.</p> + +<p>Un uso común de {{cssxref ("max-width")}} es para reducir el tamaño de las imágenes si no hay suficiente espacio para mostrarlas en su ancho intrínseco, al asegurarte de que no serán mayores que ese ancho.</p> + +<p>A modo de ejemplo, si para una imagen tienes que establecer <code>width: 100%</code> y su ancho intrínseco es menor que su contenedor, la imagen se verá obligada a expandirse y agrandarse, y se pixelará. Si su ancho intrínseco es mayor que su contenedor, se desbordará. No es probable que desees que suceda ninguno de estos casos.</p> + +<p>Si en lugar de ello usas <code>max-width: 100%</code>, la imagen puede encogerse con respecto a su tamaño intrínseco, pero no se agranda más allá del 100% de su tamaño.</p> + +<p>En el ejemplo siguiente hemos utilizado la misma imagen dos veces. La primera imagen tiene <code>width: 100%</code> y está en un contenedor que es más grande, por lo que se extiende hasta el ancho del contenedor. La segunda imagen tiene <code>max-width: 100%</code> y, por lo tanto, no se estira para llenar el recipiente. La tercera caja contiene la misma imagen de nuevo, también con <code>max-width: 100%</code>; pero en este caso puedes ver cómo se ha reducido para encajar en la caja.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/sizing/max-width.html", '100%', 800)}}</p> + +<p>Esta técnica se utiliza para dar a las imágenes una respuesta <em>adaptativa</em>, de modo que se reduzcan adecuadamente cuando se visualizan en un dispositivo más pequeño. Sin embargo, no es conveniente usar esta técnica para cargar imágenes demasiado grandes y luego reducirlas en el navegador. Las imágenes deben tener el tamaño adecuado, no deben ser más grandes de lo que sea necesario para el tamaño más grande que se muestran en el diseño. Descargar imágenes muy grandes ralentizará tu sitio y puede costarles más dinero a los usuarios si tienen una conexión tarifada.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Obtén más información sobre las <a href="/es/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">técnicas adaptativas para las imágenes</a>.</p> +</div> + +<h2 id="Unidades_de_ventana_gráfica">Unidades de ventana gráfica</h2> + +<p>La ventana gráfica es el área visible de tu página en el navegador que utilizas para ver un sitio, y también tiene un tamaño. En CSS hay unidades que asociadas con el tamaño de la ventana gráfica: las unidades <code>vw</code> para el ancho y <code>vh</code> para la altura. Con estas unidades puedes establecer tamaños relativos a la ventana gráfica del usuario.</p> + +<p><code>1vh</code> es igual al 1% de la altura de visualización, y <code>1vw</code> es igual al 1% de la anchura. Puedes usar estas unidades para dimensionar cajas, pero también texto. En el ejemplo siguiente hay un cuadro que tiene un tamaño de 20vh y 20vw. La caja contiene una letra <code>A</code>, a la que se le ha dado un valor para {{cssxref ("font-size")}} de 10vh.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/sizing/vw-vh.html", '100%', 600)}}</p> + +<p><strong>Si cambias los valores <code>vh</code> y <code>vw</code>, cambia el tamaño de la caja o de la letra; cambiar el tamaño de la ventana gráfica también cambia esos tamaños porque están dimensionados en relación con el de la ventana gráfica. Para ver el cambio del ejemplo cuando cambias el tamaño de la ventana gráfica, debes cargar el ejemplo en una ventana nueva del navegador, que pueda cambiar de tamaño (ya que tu ventana gráfica es el <code><iframe></code> incrustado que contiene el ejemplo que se muestra arriba). <a href="https://mdn.github.io/css-examples/learn/sizing/vw-vh.html">Abre el ejemplo</a>, cambia el tamaño de la ventana del navegador y observa lo que ocurre con el tamaño de la caja y el texto.</strong></p> + +<p>Cambiar los tamaños según la ventana gráfica puede ser útil en tus diseños. Por ejemplo, si deseas mostrar una sección principal a pantalla completa antes del resto del contenido, haz que esa parte de tu página de 100vh empuje el resto del contenido por debajo de la ventana gráfica, de modo que solo aparezca cuando desplacen los contenidos del documento con la barra de desplazamiento.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Este artículo te ha dado un resumen de algunos problemas clave con los que puedes encontrarte al dimensionar cosas en la web. Cuando llegues al artículo <a href="/es/docs/Learn/CSS/CSS_layout">Compaginar con CSS</a>, el tamaño va a ser un aspecto muy importante para dominar los diferentes métodos de compaginación, por lo que, antes de continuar, vale la pena comprender los conceptos que hemos expuesto en este artículo.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Values_and_units", "Learn/CSS/Building_blocks/Images_media_form_elements", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascada y herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Selectores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de cajas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/el_modelo_de_caja/index.html b/files/es/learn/css/building_blocks/el_modelo_de_caja/index.html new file mode 100644 index 0000000000..dbc0d644f8 --- /dev/null +++ b/files/es/learn/css/building_blocks/el_modelo_de_caja/index.html @@ -0,0 +1,343 @@ +--- +title: El modelo de caja +slug: Learn/CSS/Building_blocks/El_modelo_de_caja +translation_of: Learn/CSS/Building_blocks/The_box_model +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks/Backgrounds_and_borders", "Learn/CSS/Building_blocks")}}</div> + +<p>Todo en CSS tiene una caja alrededor, y comprender estas cajas es clave para poder crear diseños con CSS o para alinear elementos con otros elementos. En este artículo, echaremos un vistazo más de cerca al <em>modelo de cajas</em> en CSS con el que vas a poder crear diseños de compaginación más complejos con una comprensión de cómo funciona y la terminología relacionada.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de cómo <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, conocimientos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender sobre el modelo de cajas en CSS, en qué consiste el modelo de cajas y cómo cambiar al modelo alternativo.</td> + </tr> + </tbody> +</table> + +<h2 id="Cajas_en_bloque_y_en_línea">Cajas en bloque y en línea</h2> + +<p>En CSS, en general, hay dos tipos de cajas: <strong>cajas en bloque</strong> y <strong>cajas en línea</strong>. Estas características se refieren al modo como se comporta la caja en términos de flujo de página y en relación con otras cajas de la página:</p> + +<p>Si una caja se define como un bloque, se comportará de las maneras siguientes:</p> + +<ul> + <li>La caja fuerza un salto de línea al llegar al final de la línea.</li> + <li>La caja se extenderá en la dirección de la línea para llenar todo el espacio disponible que haya en su contenedor. En la mayoría de los casos, esto significa que la caja será tan ancha como su contenedor, y llenará el 100% del espacio disponible.</li> + <li>Se respetan las propiedades {{cssxref ("width")}} y {{cssxref ("height")}}.</li> + <li>El relleno, el margen y el borde mantienen a los otros elementos alejados de la caja.</li> +</ul> + +<p>A menos que decidamos cambiar el tipo de visualización a en línea, elementos como los encabezados (por ejemplo, <code><h1></code>) y todos los elementos <code><p></code> usan por defecto <code>block</code> como tipo de visualización externa.</p> + +<p>Si una caja tiene una visualización externa de tipo <code>inline</code>, entonces:</p> + +<ul> + <li>La caja no fuerza ningún salto de línea al llegar al final de la línea.</li> + <li>Las propiedades {{cssxref ("width")}} y {{cssxref ("height")}} no se aplican.</li> + <li>Se aplican relleno, margen y bordes verticales, pero no mantienen alejadas otras cajas en línea.</li> + <li>Se aplican relleno, margen y bordes horizontales, y mantienen alejadas otras cajas en línea.</li> +</ul> + +<p>El elemento <code><a></code>, que se utiliza para los enlaces, y los elementos <code><span></code>, <code><em></code> y <code><strong></code> son ejemplos de elementos que se muestran en línea por defecto.</p> + +<p>El tipo de caja que se aplica a un elemento está definido por los valores de propiedad {{cssxref ("display")}}, como <code>block</code> y <code>inline</code>, y se relaciona con el valor <strong>externo</strong> (<em>outer</em>) de visualización (<code>display</code>).</p> + +<h2 id="Aparte_tipos_de_visualización_interna_y_externa">Aparte: tipos de visualización interna y externa</h2> + +<p>En este punto, será mejor que también expliquemos los tipos de visualización <strong>interna</strong> y <strong>externa</strong>. Como se mencionó anteriormente, las cajas en CSS tienen un tipo de visualización <em>externa</em>, que define si se trata de una caja en bloque o en línea.</p> + +<p>Sin embargo, las cajas también tienen un tipo de visualización <em>interna</em>, que determina cómo se disponen los elementos dentro de esa caja. De forma predeterminada, los elementos dentro de una caja se presentan en <strong><a href="/es/docs/Learn/CSS/CSS_layout/Flujo_normal">flujo normal</a></strong>, lo que significa que se comportan como otros elementos de tipo en bloque o en línea (como se explicó anteriormente).</p> + +<p>Sin embargo, podemos cambiar el tipo de visualización interna utilizando valores de <code>display</code>, como <code>flex</code>. Si en un elemento establecemos <code>display: flex;</code>, el tipo de visualización externa es de tipo bloque (<code>block</code>), pero el tipo de visualización interna cambia a flexible (<code>flex</code>). Cualquier elemento que sea hijo directo de esta caja pasará a comportarse como un elemento de tipo flex, de acuerdo con las reglas que se establecen en la especificación de <a href="/es/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a>, tema que veremos más adelante.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Para obtener más información acerca de los valores de visualización y el modo como funcionan las cajas en las disposiciones en bloque y en línea, echa un vistazo a la guía <a href="/en-US/docs/Web/CSS/CSS_Flow_Layout/Block_and_Inline_Layout_in_Normal_Flow">Disposiciones en bloque y en línea</a> de MDN.</p> +</div> + +<p>A medida que vayas aprendiendo más detalles sobre el diseño CSS, te irás encontrando con el valor <code>flex</code> y con otros valores internos que puedan presentar tus cajas, por ejemplo, <code><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">grid</a></code>.</p> + +<p>Sin embargo, la disposición en bloque y en línea es la forma predeterminada cómo se comportan las cosas en la web; como ya dijimos, a veces esto se conoce como <em>flujo normal</em>, porque nuestras cajas se dispondrán en bloque o en línea, si no reciben ninguna otra instrucción.</p> + +<h2 id="Ejemplos_de_diferentes_tipos_de_visualización">Ejemplos de diferentes tipos de visualización</h2> + +<p>Sigamos adelante y veamos algunos ejemplos. A continuación tenemos tres elementos HTML diferentes, todos con visualización externa de tipo <code>block</code>. El primero es un párrafo, que tiene un borde añadido con CSS. El navegador representa esto como una caja en bloque, por lo que el párrafo comienza en una línea nueva y se expande por todo el ancho disponible.</p> + +<p>El segundo es una lista, que se presenta usando <code>display: flex</code>. Esto establece una disposición flexible para los elementos que están dentro del contenedor; sin embargo, la lista en sí misma es una caja que se comporta en bloque y, como el párrafo, se expande por todo el ancho del contenedor y fuerza un salto de línea al llegar al final de línea.</p> + +<p>Debajo hay un párrafo a nivel de bloque, dentro del cual hay dos elementos <code><span></code>. Estos elementos normalmente serían de tipo <code>inline</code>; sin embargo, uno de los elementos tiene una clase de bloque, y lo hemos establecido como <code>display: block</code>.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/block.html", '100%', 1000)}} </p> + +<p>Podemos ver cómo se comportan los elementos <code>inline</code> en el ejemplo siguiente. Los elementos <code><span></code> del primer párrafo están en línea de manera predeterminada y, por lo tanto, no fuerzan ningún salto de línea.</p> + +<p>También hay un elemento <code><ul></code> que se establece como <code>display: inline-flex</code>, que crea una caja con un comportamiento de tipo en línea alrededor de algunos elementos de tipo <code>flex</code>.</p> + +<p>Finalmente, hay dos párrafos configurados con <code>display: inline</code>. El contenedor flexible en línea y los párrafos fluyen todos juntos en línea, en lugar de dividirse en líneas nuevas como lo harían si se mostraran como elementos de bloque.</p> + +<p><strong>En el ejemplo puedes cambiar <code>display: inline</code> por <code>display: block</code> o <code>display: inline-flex</code> y por <code>display: flex</code> para alternar entre estos modos de visualización.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/inline.html", '100%', 1000)}} </p> + +<p>En artículos posteriores encontrarás cosas como el diseño flexible. El aspecto clave a recordar aquí es que cambiar el valor de la propiedad <code>display</code> puede cambiar entre el modo de visualización exterior en bloque y en línea de una caja, que cambia la forma en que se presenta junto con otros elementos en la disposición en pantalla.</p> + +<p>En el resto de este artículo, nos concentraremos en el tipo de visualización externa.</p> + +<h2 id="¿Qué_es_el_modelo_de_cajas_CSS">¿Qué es el modelo de cajas CSS?</h2> + +<p>El modelo de cajas CSS completo se aplica a cajas que presentan comportamiento en bloque; las cajas con comportamiento en línea solo usan una parte del comportamiento definido en el modelo de cajas. El modelo define cómo funcionan juntas las diferentes partes de una caja (margen, borde, relleno y contenido) para crear una caja que puedas ver en tu página. Para complicarlo un poco más, hay un modelo de cajas estándar y un modelo de cajas alternativo.</p> + +<h3 id="Partes_de_una_caja">Partes de una caja</h3> + +<p>Al hacer una caja de tipo bloque en CSS tenemos los elementos siguientes:</p> + +<ul> + <li>El <strong>contenido de la caja</strong> (o <em>content box</em>): El área donde se muestra el contenido, cuyo tamaño puede cambiarse utilizando propiedades como {{cssxref ("width")}} y {{cssxref ("height")}}.</li> + <li>El <strong>relleno de la caja</strong> (o <em>padding box</em>): El relleno es espacio en blanco alrededor del contenido; es posible controlar su tamaño usando la propiedad {{cssxref ("padding")}} y otras propiedades relacionadas.</li> + <li>El <strong>borde de la caja</strong> (o <em>border box</em>): El borde de la caja envuelve el contenido y el de relleno. Es posible controlar su tamaño y estilo utilizando la propiedad {{cssxref ("border")}} y otras propiedades relacionadas.</li> + <li>El <strong>margen de la caja</strong> (o <em>margin box</em>): El margen es la capa más externa. Envuelve el contenido, el relleno y el borde como espacio en blanco entre la caja y otros elementos. Es posible controlar su tamaño usando la propiedad {{cssxref ("margin")}} y otras propiedades relacionadas.</li> +</ul> + +<p>El diagrama siguiente muestra estas capas:</p> + +<p><img alt="Diagrama del modelo de cajas" src="https://mdn.mozillademos.org/files/16558/box-model.png" style="height: 300px; width: 544px;"></p> + +<h3 id="El_modelo_de_cajas_CSS_estándar">El modelo de cajas CSS estándar</h3> + +<p>En el modelo de cajas estándar, cuando estableces los atributos <code>width</code> y <code>height</code> para una caja, defines el ancho y el alto del <em>contenido de la caja</em>. Cualquier área de relleno y borde se añade a ese ancho y alto para obtener el tamaño total que ocupa la caja. Esto se muestra en la imagen que encontrarás a continuación.</p> + +<p>Si suponemos que la caja tiene el CSS siguiente, que establece los valores para las propiedades <code>width</code>, <code>height</code>, <code>margin</code>, <code>border</code>, y <code>padding</code>:</p> + +<pre class="brush: css notranslate">.box { + width: 350px; + height: 150px; + margin: 10px; + padding: 25px; + border: 5px solid black; +} +</pre> + +<p>El espacio que ocupa nuestra caja usando el modelo de cajas estándar será en realidad de 410 px (350 + 25 + 25 + 5 + 5); y su altura, de 210 px (150 + 25 + 25 + 5 + 5), porque el área de relleno y el borde se añaden al ancho que se utiliza para el contenido de la caja.</p> + +<p><img alt="Mostrar el tamaño de la caja cuando se usa el modelo de cajas estándar." src="https://mdn.mozillademos.org/files/16559/standard-box-model.png" style="height: 300px; width: 500px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: El margen no se cuenta para el tamaño real de la caja; por supuesto, afecta al espacio total que la caja ocupa en la página, pero solo al espacio de fuera de la caja. El área de la caja se termina en el borde, no se extiende hasta el margen.</p> +</div> + +<h3 id="El_modelo_de_cajas_CSS_alternativo">El modelo de cajas CSS alternativo</h3> + +<p>Podrías pensar que es más bien incómodo tener que sumar el borde y el área de relleno para obtener el tamaño real de la caja, ¡y tienes razón! Por este motivo, CSS introdujo un modelo de caja alternativo algún tiempo después del modelo de cajas estándar. Con este modelo, cualquier ancho es el ancho de la caja visible en la página, por lo tanto, el ancho del área de contenido es ese ancho menos el ancho para el relleno y el borde. El mismo CSS que hemos usado antes daría entonces el resultado siguiente (ancho = 350 px, altura = 150 px).</p> + +<p><img alt="Mostrar el tamaño de la caja cuando se usa el modelo de cajas alternativo." src="https://mdn.mozillademos.org/files/16557/alternate-box-model.png" style="height: 240px; width: 440px;"></p> + +<p>Por defecto, los navegadores usan el modelo de cajas estándar. Si deseas activar el modelo de cajas alternativo para un elemento, hazlo configurando <code>box-sizing: border-box</code>. Con ello, le dices al navegador que tome como el borde de la caja el área definida por cualquier tamaño que establezcas.</p> + +<pre class="brush: css notranslate"><code>.box { + box-sizing: border-box; +} </code></pre> + +<p>Si quieres que todos tus elementos usen el modelo de cajas alternativo (opción común entre los desarrolladores) debes establecer la propiedad <code>box-sizing</code> en el elemento <code><html></code>. Luego debes configurar todos los demás elementos para que hereden ese valor, como se ve en el fragmento de código siguiente. Si deseas comprender qué hay detrás, consulta el <a href="https://css-tricks.com/inheriting-box-sizing-probably-slightly-better-best-practice/">artículo de <em>CSS-Tricks</em> sobre el tamaño de las cajas</a>.</p> + +<pre class="brush: css notranslate"><code class="language-css"><span class="selector token">html</span> <span class="punctuation token">{</span> + <span class="property token">box-sizing</span><span class="punctuation token">:</span> border-box<span class="punctuation token">;</span> +<span class="punctuation token">}</span> +<span class="selector token">*, *<span class="pseudo-element token">::before</span>, *<span class="pseudo-element token">::after</span></span> <span class="punctuation token">{</span> + <span class="property token">box-sizing</span><span class="punctuation token">:</span> inherit<span class="punctuation token">;</span> +<span class="punctuation token">}</span></code></pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Un dato curioso es que Internet Explorer usaba por defecto el modelo de cajas alternativo, y no disponía de ningún mecanismo para cambiarlo.</p> +</div> + +<h2 id="Jugar_con_los_modelos_de_cajas">Jugar con los modelos de cajas</h2> + +<p>En el ejemplo siguiente puedes ver dos cajas. Ambas tienen una clase <code>.box</code>, lo que les da los mismos atributos <code>width</code>, <code>height</code>, <code>margin</code>, <code>border</code> y <code>padding</code>. La única diferencia es que la segunda caja se ha configurado para utilizar el modelo de cajas alternativo.</p> + +<p><strong>¿Puedes cambiar el tamaño de la segunda caja (añadiendo CSS a la clase <code>.alternate</code>) para que su anchura y altura coincidan con las de la primera caja?</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/box-models.html", '100%', 1000)}} </p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar la solución <a href="https://github.com/mdn/css-examples/blob/master/learn/solutions.md#the-box-model">aquí</a>.</p> +</div> + +<h3 id="Utilizar_las_DevTools_del_navegador_para_ver_el_modelo_de_cajas">Utilizar las DevTools del navegador para ver el modelo de cajas</h3> + +<p>Las <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">herramientas del desarrollador de tu navegador</a> pueden facilitar la comprensión del modelo de cajas. Si inspeccionas un elemento con las DevTools de Firefox, puedes ver el tamaño del elemento más su margen, área de relleno y borde. Inspeccionar un elemento de esta manera es un modo excelente de descubrir si tu caja es en realidad del tamaño que crees que es.</p> + +<p><img alt="Inspeccionar el modelo de cajas de un elemento utilizando Firefox DevTools" src="https://mdn.mozillademos.org/files/16560/box-model-devtools.png" style="height: 683px; width: 1150px;"></p> + +<h2 id="Márgenes_relleno_y_bordes">Márgenes, relleno y bordes</h2> + +<p>Ya has visto las propiedades {{cssxref ("margin")}}, {{cssxref ("padding")}} y {{cssxref ("border")}} que usamos en el ejemplo anterior. Las propiedades que hemos usado en ese ejemplo son <strong>propiedades abreviadas</strong> y nos permiten establecer los cuatro lados de la caja a la vez. Estas propiedades abreviadas también tienen propiedades sin abreviar equivalentes, que permiten tener control sobre los diferentes lados de la caja de forma individual.</p> + +<p>Vamos a explorar estas propiedades más detalladamente.</p> + +<h3 id="Margen">Margen</h3> + +<p>El margen es un espacio invisible que hay alrededor de la caja. Aleja el resto de elementos de la caja. Los márgenes pueden tener valores positivos o negativos. Establecer un margen negativo para un lado de tu caja puede hacer que se superponga con otros elementos de la página. Tanto si utilizas el modelo de cajas estándar como el alternativo, el margen siempre se añade después de haber calculado el tamaño de la caja que se ve.</p> + +<p>Podemos controlar todos los márgenes de un elemento a la vez usando la propiedad {{cssxref ("margin")}}, o cada lado individualmente usando las propiedades equivalentes sin abreviar:</p> + +<ul> + <li>{{cssxref("margin-top")}}</li> + <li>{{cssxref("margin-right")}}</li> + <li>{{cssxref("margin-bottom")}}</li> + <li>{{cssxref("margin-left")}}</li> +</ul> + +<p><strong>En el ejemplo siguiente, cambia los valores de margen para ver cómo se empuja la caja debido al espacio que el margen crea o se elimina (si es un margen negativo) entre este elemento y el elemento que lo contiene.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/margin.html", '100%', 1000)}} </p> + +<h4 id="Colapso_del_margen">Colapso del margen</h4> + +<p>Un punto clave a la hora de entender los márgenes es el concepto de colapso del margen. Si tienes dos elementos cuyos márgenes se tocan, esos márgenes se combinan para convertirse en un solo margen, cuyo tamaño es el del margen más grande.</p> + +<p>En el ejemplo siguiente hay dos párrafos. El párrafo superior tiene un atributo <code>margin-bottom</code> de 50 píxeles. El segundo párrafo tiene un atributo <code>margin-top</code> de 30 píxeles. Los márgenes colapsan, por lo que el margen real entre las cajas es de 50 píxeles, y no el total de ambos márgenes.</p> + +<p><strong>Pruébalo ajustando el atributo <code>margin-top</code> del segundo párrafo a 0. El margen visible entre los dos párrafos no cambiará, sino que conservará los 50 píxeles fijados en el atributo <code>bottom-margin</code> del primer párrafo.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/margin-collapse.html", '100%', 1000)}} </p> + +<p>Hay una serie de reglas que establecen cuándo los márgenes colapsan y cuándo no. Para obtener más información, consulta la página web sobre <a href="/es/docs/Web/CSS/CSS_Modelo_Caja/Mastering_margin_collapsing">entender el colapso de márgenes</a>. Por ahora solo debes recordar que el colapso de los márgenes es algo que puede suceder. Si creas un espacio con márgenes y no obtienes el espacio que esperas, probablemente es que se haya producido algún colapso de márgenes.</p> + +<h3 id="Bordes">Bordes</h3> + +<p>El borde se dibuja entre el margen y el área de relleno de una caja. Si utilizas el modelo de cajas estándar, el tamaño del borde se añade a los elementos <code>width</code> y <code>height</code> que establecen el alto y el ancho de la caja. Si utilizas el modelo de cajas alternativo, el tamaño del borde reduce el tamaño de la caja de contenido, porque ocupa una parte del alto y el ancho disponibles.</p> + +<p>Hay una gran cantidad de propiedades que sirven para aplicar estilo a los bordes: hay cuatro bordes y cada borde tiene un estilo, un ancho y un color que podemos modificar.</p> + +<p>Puedes establecer el ancho, el estilo o el color de los cuatro bordes a la vez utilizando la propiedad {{cssxref ("border")}}.</p> + +<p>Para establecer las propiedades de cada lado de forma individual, puedes utilizar:</p> + +<ul> + <li>{{cssxref("border-top")}}</li> + <li>{{cssxref("border-right")}}</li> + <li>{{cssxref("border-bottom")}}</li> + <li>{{cssxref("border-left")}}</li> +</ul> + +<p>Para establecer el ancho, el estilo o el color de todos los lados, usa lo siguiente:</p> + +<ul> + <li>{{cssxref("border-width")}}</li> + <li>{{cssxref("border-style")}}</li> + <li>{{cssxref("border-color")}}</li> +</ul> + +<p>Para establecer el ancho, el estilo o el color de un solo lado, puedes usar una de las propiedades no abreviadas:</p> + +<ul> + <li>{{cssxref("border-top-width")}}</li> + <li>{{cssxref("border-top-style")}}</li> + <li>{{cssxref("border-top-color")}}</li> + <li>{{cssxref("border-right-width")}}</li> + <li>{{cssxref("border-right-style")}}</li> + <li>{{cssxref("border-right-color")}}</li> + <li>{{cssxref("border-bottom-width")}}</li> + <li>{{cssxref("border-bottom-style")}}</li> + <li>{{cssxref("border-bottom-color")}}</li> + <li>{{cssxref("border-left-width")}}</li> + <li>{{cssxref("border-left-style")}}</li> + <li>{{cssxref("border-left-color")}}</li> +</ul> + +<p><strong>En el ejemplo siguiente, hemos utilizado varios ejemplos de la lista anterior para crear bordes. Juega con las diferentes propiedades para comprobar que entiendes cómo funcionan. Las páginas de MDN sobre las propiedades de los bordes te proporcionan información sobre los diferentes estilos entre los que puedes elegir para los bordes.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/border.html", '100%', 1000)}} </p> + +<h3 id="Relleno">Relleno</h3> + +<p>El relleno se encuentra entre el borde y el área de contenido. A diferencia de los márgenes, el relleno no puede tomar valores negativos, por lo que el valor debe ser 0 o positivo. Cualquier fondo aplicado a tu elemento se mostrará detrás del área de relleno y, generalmente, se usa para mantener el contenido alejado del borde.</p> + +<p>Podemos controlar el área de relleno para todos los lados de un mismo elemento usando la propiedad {{cssxref ("padding")}}, o para cada lado uno de los lados usando las propiedades equivalentes:</p> + +<ul> + <li>{{cssxref("padding-top")}}</li> + <li>{{cssxref("padding-right")}}</li> + <li>{{cssxref("padding-bottom")}}</li> + <li>{{cssxref("padding-left")}}</li> +</ul> + +<p><strong>Si cambias los valores para el elleno en la clase <code>.box</code> del ejemplo siguiente, puedes ver que cambia dónde comienza el texto en relación con la caja.</strong></p> + +<p><strong>También puedes cambiar el relleno en la clase <code>.container</code>, que abrirá el espacio entre el contenedor y la caja. El área de relleno se puede cambiar para cualquier elemento y abrirá espacio entre su borde y lo que esté dentro del elemento.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/padding.html", '100%', 800)}} </p> + +<h2 id="El_modelo_de_cajas_y_las_cajas_en_línea">El modelo de cajas y las cajas en línea</h2> + +<p>Todo lo anterior se aplica por completo a las cajas en bloque. Algunas de las propiedades también pueden aplicarse a las cajas en línea, como las que crea un elemento <code><span></code>.</p> + +<p>En el ejemplo siguiente hay un elemento <code><span></code> dentro de un párrafo al que hemos aplicado las propiedades <code>width</code>, <code>height</code>, <code>margin</code>, <code>border</code>, y <code>padding</code> Puedes ver que la anchura y la altura se ignoran. Se respetan el margen, el relleno y el borde, pero no cambian la relación de otro contenido con respecto a nuestra caja en línea, por lo que el relleno y el borde se superponen a otras palabras en el párrafo.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/inline-box-model.html", '100%', 800)}} </p> + +<h2 id="El_uso_de_display_inline-block">El uso de display: inline-block</h2> + +<p>Hay un valor especial de <code>display</code> que proporciona un punto medio entre <code>inline</code> y <code>block</code>. Esto es útil para situaciones en las que no deseas que un elemento fuerce un salto de línea, pero sí deseas que se respeten las propiedades <code>width</code> y <code>height</code> para evitar superposiciones como la que se ve arriba.</p> + +<p>Un elemento con <code>display: inline-block</code> conforma un subconjunto de los elementos en bloque que ya conocemos:</p> + +<ul> + <li>Se respetan las propiedades de ancho y alto.</li> + <li>El relleno, el margen y el borde mantienen los otros elementos alejados de la caja.</li> +</ul> + +<p>Sin embargo, no se fuerza un salto de línea, y solo se hace más grande que su contenido si añades las propiedades <code>width</code> y <code>height</code> explícitamente.</p> + +<p><strong>En el ejemplo siguiente hemos añadido <code>display: inline-block</code> a nuestro elemento <code><span></code>. Cámbialo por <code>display: block</code> o elimina la línea para ver la diferencia entre ambos modelos de visualización.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/inline-block.html", '100%', 800)}} </p> + +<p>Esto puede ser útil cuando deseas dar a un enlace un área de impacto más grande añadiendo <code>padding</code>. <code><a></code> es un elemento en línea como <code><span></code>; puedes usar <code>display: inline-block</code> para configurar el área de relleno para facilitar al usuario hacer clic en el enlace.</p> + +<p>Esto se ve con bastante frecuencia en las barras de navegación. La navegación siguiente se muestra en una fila usando <code>flexbox</code> y hemos añadido una área de relleno al elemento <code><a></code> porque queremos poder cambiar su color de fondo (<code>background-color</code>) cuando se pasa el ratón por encima de <code><a></code>. El área de relleno parece superponerse al borde del elemento <code><ul></code>. Esto se debe a que <code><a></code> es un elemento en línea.</p> + +<p><strong>Añade <code>display: inline-block</code> a la regla con el selector <code>.links-list a</code> y verás cómo se soluciona este problema, al hacer que otros elementos respeten el área de relleno.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/box-model/inline-block-nav.html", '100%', 600)}} </p> + +<h2 id="Pon_a_prueba_tus_habilidades">Pon a prueba tus habilidades</h2> + +<p>Hemos cubierto mucho terreno en este artículo. ¿Recuerdas la información más relevante? Encontrarás más pruebas para verificar que has retenido esa información en <a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Box_Model_Tasks">Test your skills: The Box Model</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Eso es lo que hay que entender sobre el modelo de cajas. Es posible que en el futuro desees volver a este artículo si alguna vez te lías con los tamaños de las cajas en la disposición de tu página web.</p> + +<p>En el artículo siguiente veremos cómo se pueden usar los <a href="/es/docs/Learn/CSS/Building_blocks/Fondos_y_bordes">fondos y bordes</a> para hacer que tus simples cajas presenten un aspecto más interesante.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks/Backgrounds_and_borders", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascada y herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Selectores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de cajas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS </a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/fondos_y_bordes/index.html b/files/es/learn/css/building_blocks/fondos_y_bordes/index.html new file mode 100644 index 0000000000..0de93e1eb1 --- /dev/null +++ b/files/es/learn/css/building_blocks/fondos_y_bordes/index.html @@ -0,0 +1,306 @@ +--- +title: Fondos y bordes +slug: Learn/CSS/Building_blocks/Fondos_y_bordes +translation_of: Learn/CSS/Building_blocks/Backgrounds_and_borders +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/The_box_model", "Learn/CSS/Building_blocks/Handling_different_text_directions", "Learn/CSS/Building_blocks")}}</div> + +<p>En este artículo, veremos algunas de las cosas creativas que puedes hacer con los fondos y los bordes de CSS. Añadir degradados, imágenes de fondo o redondear esquinas; los fondos y los bordes son la solución para una gran cantidad de cuestiones de estilo en CSS.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, conocimientos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con el CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a diseñar el fondo y los bordes de las cajas.</td> + </tr> + </tbody> +</table> + +<h2 id="Aplicar_estilo_a_los_fondos_en_CSS">Aplicar estilo a los fondos en CSS</h2> + +<p>La propiedad {{cssxref ("background")}} de CSS es una propiedad abreviada de una serie de propiedades de fondo que vamos a ver en este artículo. Si descubres una propiedad de fondo compleja en una hoja de estilo, puede parecer un poco difícil de entender porque pueden estarse pasando muchos valores a la vez.</p> + +<pre class="brush: css notranslate"><code>.box { + background: linear-gradient(105deg, rgba(255,255,255,.2) 39%, rgba(51,56,57,1) 96%) center center / 400px 200px no-repeat, + url(big-star.png) center no-repeat, rebeccapurple; +} </code> +</pre> + +<p>Más adelante en este tutorial regresaremos a cómo funcionan las propiedades abreviadas, pero primero echemos un vistazo a las diferentes cosas que puedes hacer con los fondos en CSS, a partir de observar las propiedades de fondo individuales.</p> + +<h3 id="Los_colores_de_fondo">Los colores de fondo</h3> + +<p>La propiedad {{cssxref ("background-color")}} define el color de fondo de cualquier elemento en CSS. La propiedad admite cualquier <code><a href="/es/docs/Web/CSS/color_value"><color></a></code> válido. Un color de fondo (<code>background-color</code>) se extiende por debajo del contenido y el relleno del elemento.</p> + +<p>En el ejemplo siguiente hemos utilizado varios valores de color para añadir un color de fondo a la caja, a un encabezado y a un elemento {{htmlelement ("span")}}.</p> + +<p><strong>Juega un poco con ellos; usa cualquier valor <a href="/es/docs/Web/CSS/color_value"><color></a> disponible.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/color.html", '100%', 800)}}</p> + +<h3 id="Las_imágenes_de_fondo">Las imágenes de fondo</h3> + +<p>La propiedad {{cssxref ("background-image")}} permite visualizar una imagen de fondo en un elemento. En el ejemplo siguiente hay dos cajas: una tiene una imagen de fondo que es más grande que la caja misma, la otra tiene una imagen pequeña en forma de estrella.</p> + +<p>Este ejemplo demuestra dos cosas sobre las imágenes de fondo. De forma predeterminada, la imagen grande no se reduce para ajustarse a la caja, por lo que solo vemos una pequeña esquina de esta, mientras que la imagen pequeña aparece en forma de mosaico hasta llenar la caja. En este caso, la imagen es en realidad una sola estrella.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/background-image.html", '100%', 800)}}</p> + +<p><strong>Si especificas un color de fondo además de una imagen de fondo, la imagen se muestra encima del color de fondo. Añade una propiedad <code>background-color</code> al ejemplo anterior y obsérvalo en acción.</strong></p> + +<h4 id="Controlar_background-repeat">Controlar background-repeat</h4> + +<p>La propiedad {{cssxref ("background-repeat")}} se usa para controlar el comportamiento de tipo mosaico de las imágenes. Los valores disponibles son:</p> + +<ul> + <li><code>no-repeat</code>: evita que el fondo se repita.</li> + <li><code>repeat-x</code>: repite horizontalmente.</li> + <li><code>repeat-y</code>: repite verticalmente.</li> + <li><code>repeat</code>: es el valor por defecto; repite en ambas direcciones.</li> +</ul> + +<p><strong>Prueba estos valores en el ejemplo siguiente. Hemos establecido el valor <code>no-repeat</code>, así que solo verás una estrella. Prueba los diferentes valores (<code>repeat-x</code> y <code>repeat-y</code>) y observa cuáles son los efectos.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/repeat.html", '100%', 800)}}</p> + +<h4 id="Dimensionar_la_imagen_de_fondo">Dimensionar la imagen de fondo</h4> + +<p>En el ejemplo anterior hay una imagen grande que aparece recortada porque es más grande que el fondo. En este caso, podríamos usar la propiedad {{cssxref ("background-size")}}, que puede tomar valores de <a href="/es/docs/Web/CSS/length">longitud</a> o <a href="/es/docs/Web/CSS/porcentaje">porcentaje</a>, para ajustar el tamaño de la imagen para que quepa dentro del fondo.</p> + +<p>También puedes utilizar palabras clave:</p> + +<ul> + <li><code>cover</code>: el navegador agrandará la imagen lo suficientemente grande como para que esta cubra por completo el área de la caja sin que pierda su relación de aspecto. En este caso, es probable que parte de la imagen quede fuera de la caja.</li> + <li><code>contain</code>: el navegador adecuará el tamaño de la imagen para que quepa dentro de la caja. En este caso, pueden quedar huecos a ambos lados o en la parte superior e inferior de la imagen si la relación de aspecto de la imagen es diferente de la de la caja.</li> +</ul> + +<p>En el ejemplo siguiente hemos usado la imagen más grande del ejemplo anterior y unidades de longitud para establecer sus dimensiones dentro de la caja. Puedes ver que esto ha distorsionado la imagen.</p> + +<p>Prueba lo siguiente:</p> + +<ul> + <li>Cambia las unidades de longitud que has utilizado para modificar el tamaño del fondo.</li> + <li>Elimina las unidades de longitud y observa qué sucede cuando usas <code>background-size: cover</code> o <code>background-size: contain</code>.</li> + <li>Si tu imagen es más pequeña que la caja, puedes cambiar el valor <code>background-repeat</code> para que la imagen se repita.</li> +</ul> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/size.html", '100%', 800)}}</p> + +<h4 id="Posicionar_la_imagen_de_fondo">Posicionar la imagen de fondo</h4> + +<p>La propiedad {{cssxref ("background-position")}} te permite elegir la posición en la que aparece la imagen de fondo dentro de la caja a la que está asociada. Para ello se utiliza un sistema de coordenadas en el que la esquina superior izquierda de la caja es <code>(0,0)</code>, y la caja se coloca sobre los ejes horizontal (<code>x</code>) y vertical (<code>y</code>).</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: El valor predeterminado de <code>background-position</code> es <code>(0,0)</code>.</p> +</div> + +<p>Los valores de <code>background-position</code> más comunes toman dos valores independientes: un valor horizontal seguido de un valor vertical.</p> + +<p>Puedes usar palabras clave como <code>top</code> y <code>right</code> (busca todas las demás en la página sobre la propiedad {{cssxref ("background-position")}}):</p> + +<pre class="brush: css notranslate"><code>.box { + background-image: url(star.png); + background-repeat: no-repeat; + background-position: top center; +} </code> +</pre> + +<p>Y también <a href="/es/docs/Web/CSS/length">longitudes</a> y <a href="/es/docs/Web/CSS/porcentaje">porcentajes</a>:</p> + +<pre class="brush: css notranslate"><code>.box { + background-image: url(star.png); + background-repeat: no-repeat; + background-position: 20px 10%; +} </code> +</pre> + +<p>También puedes mezclar valores de palabras clave con longitudes o porcentajes, por ejemplo:</p> + +<pre class="brush: css notranslate">.box { + background-image: url(star.png); + background-repeat: no-repeat; + background-position: top 20px; +}</pre> + +<p>Por último, también puedes usar una sintaxis de 4 valores para indicar una distancia desde ciertos bordes del cuadro: la unidad de longitud en este caso es un desplazamiento del valor que la precede. Entonces, en el CSS siguiente, colocamos el fondo a 20 px desde la parte superior y a 10 px desde la derecha:</p> + +<pre class="brush: css notranslate"><code>.box { + background-image: url(star.png); + background-repeat: no-repeat; + background-position: top 20px right 10px; +} </code></pre> + +<p><strong>Utiliza el ejemplo siguiente para jugar con estos valores y mover la estrella por la caja.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/position.html", '100%', 800)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: <code>background-position</code> es una propiedad abreviada de {{cssxref("background-position-x")}} y {{cssxref("background-position-y")}}, que te permiten configurar los diferentes valores de posición del eje por separado.</p> +</div> + +<h3 id="Degradados_de_fondo">Degradados de fondo</h3> + +<p>Un degradado, cuando se usa para un fondo, actúa como una imagen y también se establece usando la propiedad {{cssxref("background-image")}}.</p> + +<p>Puedes leer más sobre los diferentes tipos de degradados y sobre qué puedes hacer con ellos en la página sobre el tipo de datos <code><a href="/en-US/docs/Web/CSS/gradient"><gradient></a></code> de MDN. Una forma divertida de jugar con degradados es usar uno de los muchos generadores de degradados CSS que hay disponibles en la web, <a href="https://cssgradient.io/">como este</a>. Puedes crear un degradado y luego copiar y pegar el código fuente que lo genera.</p> + +<p>Prueba algunos degradados diferentes en el ejemplo siguiente. En las dos cajas hay, respectivamente, un degradado lineal que se extiende por toda la caja, y un degradado radial con un tamaño establecido, que por lo tanto se repite.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/gradients.html", '100%', 800)}}</p> + +<h3 id="Múltiples_imágenes_de_fondo">Múltiples imágenes de fondo</h3> + +<p>También es posible poner múltiples imágenes de fondo: puedes especificar múltiples valores <code>background-image</code> para un solo atributo, separados cada uno por una coma.</p> + +<p>Si haces esto, las imágenes de fondo pueden quedar superpuestas entre sí. Los fondos se superponen con la última imagen de fondo que hay en la parte inferior de la lista, y cada imagen anterior se apila encima de la que sigue en el código.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Los degradados se pueden mezclar con imágenes de fondo normales.</p> +</div> + +<p>Las otras propiedades <code>background-*</code> también pueden tener valores múltiples separados por comas, de la misma manera que <code>background-image</code>:</p> + +<pre class="brush: css notranslate">background-image: url(image1.png), url(image2.png), url(image3.png), url(image1.png); +background-repeat: no-repeat, repeat-x, repeat; +background-position: 10px 20px, top right;</pre> + +<p>Cada valor de las diversas propiedades coincide con los valores que están en la misma posición en las otras propiedades. Arriba, por ejemplo, el valor para la propiedad <code>background-repeat</code> de <code>image1</code> será <code>no-repeat</code>. Sin embargo, ¿qué sucede cuando diferentes propiedades tienen una cantidad diferente de valores? La respuesta es que los valores que ocupan las posiciones más pequeñas se alternan cíclicamente: en el ejemplo anterior hay cuatro imágenes de fondo pero solo dos valores <code>background-position</code>. Los primeros dos valores de posición se aplicarán a las dos primeras imágenes, luego los valores volverán a asignarse cíclicamente: a <code>image3</code> se le dará el primer valor de posición, y a <code>image4</code> se le dará el segundo valor de posición.</p> + +<p><strong>Vamos a jugar. En el ejemplo siguiente hemos incluido dos imágenes. Para demostrar el orden de superposición, cambia la imagen de fondo que aparece primero en la lista. O juega con las otras propiedades para cambiar la posición, el tamaño o repite los valores.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/multiple-background-image.html", '100%', 800)}}</p> + +<h3 id="Anclaje_del_fondo">Anclaje del fondo</h3> + +<p>Otra opción que hay disponible para fondos es especificar cómo se desplazan cuando se desplaza el contenido. Esto se controla con la propiedad {{cssxref ("background-attachment")}}, que puede tomar los valores siguientes:</p> + +<ul> + <li><code>scroll</code>: Hace que el fondo del elemento se desplace cuando te desplazas por el contenido de la página. Si te desplazas por el contenido del elemento, el fondo no se mueve. El efecto resultante es que el fondo está anclado a la página en una posición fija, por lo que se desplaza a medida que la página se desplaza.</li> + <li><code>fixed</code>: Hace que el fondo de un elemento quede fijo con respecto a la ventana gráfica, de modo que no se desplace cuando te desplazas por la página o el contenido del elemento. Siempre permanece en la misma posición de la pantalla.</li> + <li><code>local</code>: Este valor se añadió posteriormente (solo es compatible con Internet Explorer 9+, mientras que los otros son compatibles con IE4+) porque el valor <code>scroll</code> es bastante confuso y en muchos casos no hace lo que deseas. El valor <code>local</code> ancla el fondo al elemento en el que está configurado, de modo que cuando te desplazas por el contenido del elemento, el fondo se desplaza con este.</li> +</ul> + +<p>La propiedad {{cssxref ("background-attachment")}} solo tiene efecto cuando hay contenido por el que puedas desplazarte, por lo que hemos preparado un ejemplo para demostrar las diferencias entre los tres valores: echa un vistazo a <a href="http://mdn.github.io/learning-area/css/styling-boxes/backgrounds/background-attachment.html">background-attachment.html</a> (También puedes consultar el <a href="https://github.com/mdn/learning-area/tree/master/css/styling-boxes/backgrounds">código fuente</a> aquí).</p> + +<h3 id="Usar_la_propiedad_abreviada_para_el_fondo">Usar la propiedad abreviada para el fondo</h3> + +<p>Como mencionamos al comienzo de este artículo, a menudo verás fondos que están especificados usando la propiedad {{cssxref ("background")}}. Esta forma abreviada te permite configurar todas las diferentes propiedades a la vez.</p> + +<p>Si utilizas varios fondos, debes especificar todas las propiedades para el primer fondo y luego añadir el fondo siguiente separado por una coma. En el ejemplo siguiente hay un degradado con un tamaño y una posición, luego un fondo de imagen con <code>no-repeat</code> y una posición y, por último, un color.</p> + +<p>Al escribir los valores abreviados de las imágenes de fondo es necesario seguir algunas reglas, por ejemplo:</p> + +<ul> + <li>Solo es posible especificar un color de fondo (<code>background-color</code>) después de la coma final.</li> + <li>El valor para <code>background-size</code> solo puede incluirse inmediatamente después de <code>background-position</code>, separado con el carácter '/', así: <code>center/80%</code>.</li> +</ul> + +<p>Consulta la página para el atributo {{cssxref ("background")}} de MDN para ver todas las posibilidades.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/background.html", '100%', 800)}}</p> + +<h3 id="Consideraciones_de_accesibilidad_con_los_fondos">Consideraciones de accesibilidad con los fondos</h3> + +<p>Al colocar texto sobre una imagen o un color de fondo, debes asegurarte de que tiene suficiente contraste para que tus visitantes puedan leer el texto. Si estableces una imagen de fondo y el texto se coloca encima de la imagen, también debes especificar un color de fondo (<code>background-color</code>) que permita leer el texto si la imagen no se carga.</p> + +<p>Los lectores de pantalla no pueden analizar las imágenes de fondo, por lo tanto, deben ser puramente decorativas; cualquier contenido importante debe ser parte de la página HTML y no debe estar contenido en un fondo.</p> + +<h2 id="Bordes">Bordes</h2> + +<p>Al aprender sobre el modelo de cajas descubrimos cómo los bordes afectan al tamaño de nuestra caja. En este artículo veremos cómo usar los bordes de una manera creativa. Por lo general, cuando a un elemento le añadimos bordes con CSS, usamos una propiedad abreviada que establece el color, el ancho y el estilo del borde en una línea de CSS.</p> + +<p>Podemos establecer un borde para los cuatro lados de una caja con {{cssxref ("border")}}:</p> + +<pre class="brush: css notranslate"><code>.box { + border: 1px solid black; +} </code></pre> + +<p>O podemos establecer solo un borde de la caja, por ejemplo:</p> + +<pre class="brush: css notranslate"><code>.box { + border-top: 1px solid black; +} </code></pre> + +<p>Cada una de las propiedades de estas propiedades abreviadas sería:</p> + +<pre class="brush: css notranslate"><code>.box { + border-width: 1px; + border-style: solid; + border-color: black; +} </code></pre> + +<p>Y las no abreviadas:</p> + +<pre class="brush: css notranslate"><code>.box { + border-top-width: 1px; + border-top-style: solid; + border-top-color: black; +} </code></pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Estas propiedades para el borde superior, derecho, inferior e izquierdo también tienen propiedades <em>lógicas</em> asignadas que se relacionan con el modo de escritura del documento (por ejemplo, texto de izquierda a derecha o de derecha a izquierda, o de arriba a abajo). Exploraremos esto en la próxima lección, que expone el <a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">uso de diferentes direcciones de texto</a>.</p> +</div> + +<p><strong>Hay una variedad de estilos que puedes usar para los bordes. En el ejemplo siguiente, hemos utilizado un estilo de borde diferente para los cuatro lados de la caja. Juega con el estilo, el ancho y el color del borde para ver cómo funcionan los bordes.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/borders.html", '100%', 800)}}</p> + +<h3 id="Esquinas_redondeadas">Esquinas redondeadas</h3> + +<p>El redondeo de esquinas en una caja se logra mediante el uso de la propiedad {{cssxref ("border-radius")}} y otras propiedades asociadas que se relacionan con cada esquina de la caja. Como valor pueden usarse dos longitudes o porcentajes: el primer valor define el radio horizontal y el segundo el radio vertical. En muchos casos, solo se pondrá un valor, que se utilizará para ambos.</p> + +<p>Por ejemplo, para hacer que las cuatro esquinas de una caja tengan un radio de 10 píxeles:</p> + +<pre class="brush: css notranslate"><code>.box { + border-radius: 10px; +} </code></pre> + +<p>O para hacer que la esquina superior derecha tenga un radio horizontal de 1 em y un radio vertical del 10%:</p> + +<pre class="brush: css notranslate"><code>.box { + border-top-right-radius: 1em 10%; +} </code></pre> + +<p>En el ejemplo siguiente hemos establecido las cuatro esquinas, y luego cambiamos los valores de la esquina superior derecha para que sea diferente. Juega con los valores para cambiar las esquinas. Echa un vistazo a la página de la propiedad {{cssxref ("border-radius")}} para ver las opciones de sintaxis disponibles.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/backgrounds-borders/corners.html", '100%', 800)}}</p> + +<h2 id="Pon_a_prueba_tus_habilidades">Pon a prueba tus habilidades</h2> + +<p>Hemos cubierto mucho terreno en este artículo. ¿Recuerdas la información más relevante? Encontrarás más pruebas para verificar que retienes la información antes de seguir adelante en<a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Test_your_skills_backgrounds_and_borders"> Test your skills: Backgrounds and Borders</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En este artículo hemos expuesto bastantes conceptos y puedes ver que hay mucho para añadir a un fondo o a un borde de una caja. Explora las diferentes páginas de propiedades si deseas obtener más información sobre cualquiera de las características que hemos discutido. Todas las páginas de MDN contienen más ejemplos de uso, para que juegues y mejores tus conocimientos.</p> + +<p>En el próximo artículo descubriremos cómo interacciona el modo de escritura de tu documento con tu CSS. ¿Qué sucede cuando el texto no fluye de izquierda a derecha?</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/The_box_model", "Learn/CSS/Building_blocks/Handling_different_text_directions", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascada y herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Selectores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de cajas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/imágenes_medios_y_elementos_de_formulario/index.html b/files/es/learn/css/building_blocks/imágenes_medios_y_elementos_de_formulario/index.html new file mode 100644 index 0000000000..db0f522728 --- /dev/null +++ b/files/es/learn/css/building_blocks/imágenes_medios_y_elementos_de_formulario/index.html @@ -0,0 +1,193 @@ +--- +title: 'Imágenes, medios y elementos de formulario' +slug: Learn/CSS/Building_blocks/Imágenes_medios_y_elementos_de_formulario +translation_of: Learn/CSS/Building_blocks/Images_media_form_elements +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Sizing_items_in_CSS", "Learn/CSS/Building_blocks/Styling_tables", "Learn/CSS/Building_blocks")}}</div> + +<p>En este artículo vamos a ver cómo se tratan ciertos elementos especiales en CSS. Las imágenes y otros medios y los elementos de formulario presentan un comportamiento algo distinto que otros elementos CSS, como las cajas, en cuanto a aplicación de estilo. Comprender qué es y qué no es posible te ahorrará frustraciones, y en este artículo vamos a destacar algunas de las cuestiones principales que necesitas saber.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, conocimientos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender el modo en que algunos elementos se comportan de manera inusual cuando se diseñan con CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="Elementos_de_reemplazo">Elementos de reemplazo</h2> + +<p>Las imágenes y los vídeos se describen como <strong><a href="/es/docs/Web/CSS/Elemento_reemplazo">elementos de reemplazo</a></strong>. Esto significa que el CSS no puede intervenir en aspectos del diseño interno de estos elementos, sino solo a su posición en la página y algunos otros aspectos. Sin embargo, como veremos, hay varias cosas que el CSS puede hacer con una imagen.</p> + +<p>También se describen ciertos elementos de reemplazo que, como las imágenes y vídeos, presentan una <strong>relación de aspecto</strong>. Esto significa que tienen un tamaño definido tanto en la dimensión horizontal (x) como en la vertical (y), y por defecto se mostrarán con las dimensiones intrínsecas del archivo.</p> + +<h2 id="El_tamaño_de_las_imágenes">El tamaño de las imágenes</h2> + +<p>Como ya conoces de estos artículos, todo en CSS genera una caja. Si colocas una imagen dentro de una caja que es más pequeña o más grande que las dimensiones intrínsecas del archivo de imagen en cualquier dirección, aparecerá más pequeño que la caja o se desbordará. Debes decidir qué hacer con el desbordamiento.</p> + +<p>En el ejemplo siguiente hay dos cajas, ambas de 200 píxeles de tamaño:</p> + +<ul> + <li>Una contiene una imagen que es más pequeña de 200 píxeles: es más pequeña que la caja y no se expande para rellenarla.</li> + <li>La otra es más grande de 200 píxeles y desborda la caja.</li> +</ul> + +<p>{{EmbedGHLiveSample("css-examples/learn/images/size.html", '100%', 1000)}}</p> + +<p>¿Qué podemos hacer con el problema del desbordado?</p> + +<p>Como aprendimos en <a href="/es/docs/Learn/CSS/Building_blocks/Dimensionar_elementos_en_CSS">nuestro artículo anterior</a>, una técnica común es hacer que el la propiedad {{cssxref ("max-width")}} de una imagen sea 100%. Esto permite que la imagen tenga un tamaño menor que la caja, pero no que tenga un tamaño mayor. Esta técnica funciona con otros elementos de reemplazo, como <code><a href="/es/docs/Web/HTML/Elemento/video"><video></a></code> o <code><a href="/es/docs/Web/HTML/Elemento/iframe"><iframe></a></code>.</p> + +<p><strong>Añade <code>max-width: 100%</code> al elemento <code><img></code> del ejemplo anterior. Verás que la imagen más pequeña permanece sin cambios, pero la más grande se reduce hasta caber en la caja.</strong></p> + +<p>Puedes tomar otras decisiones sobre las imágenes dentro de los contenedores. Por ejemplo, es posible que desees cambiar el tamaño de una imagen para que cubra una caja por completo.</p> + +<p>La propiedad {{cssxref ("object-fit")}} puede ser de gran ayuda. Cuando se usa <code>object-fit</code>, el elemento de reemplazo puede dimensionarse para adaptarse a una caja de varias maneras.</p> + +<p>A continuación, hemos utilizado el valor <code>cover</code>, que reduce el tamaño de la imagen a la vez que mantiene la relación de aspecto hasta que rellena toda la caja. Al mantenerse la relación de aspecto, la caja corta algunas partes de la imagen.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/images/object-fit.html", '100%', 1000)}}</p> + +<p>Si usamos el valor <code>contain</code>, la imagen se reduce hasta que es lo bastante pequeña para caber dentro de la caja. Esto puede dar lugar a un formato panorámico si la imagen no presenta la misma relación de aspecto que la caja.</p> + +<p>También puedes probar el valor <code>fill</code>, que rellena la caja, pero no mantiene la relación de aspecto.</p> + +<h2 id="Elementos_de_reemplazo_en_una_compaginación">Elementos de reemplazo en una compaginación</h2> + +<p>A medida que vayas usando diversas técnicas de diseño CSS en elementos de reemplazo, irás descubriendo que se comportan de manera ligeramente diferente a otros elementos. Por ejemplo, en un diseño flexible o en un diseño de página de cuadrícula, los elementos se expanden por defecto hasta que llenan toda el área. En cambio, las imágenes no se expanden, sino que se alinean con el inicio del área de la cuadrícula o del contenedor flexible.</p> + +<p>Puedes ver esto en el ejemplo siguiente, en que hay un contenedor de con dos columnas y dos filas, que tiene cuatro elementos. Todos los elementos <code><div></code> tienen un color de fondo y se estiran para llenar la fila y la columna. La imagen, sin embargo, no se expande.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/images/layout.html", '100%', 1000)}}</p> + +<p>Si sigues estos artículos en orden, no habrás llegado todavía a la compaginación. Ten en cuenta solo que cuando los elementos de reemplazo forman parte de una cuadrícula o un diseño flexible, presentan comportamientos predeterminados diferentes, en esencia para evitar que el diseño los expanda de manera extraña.</p> + +<p>Para forzar que la imagen se expanda para llenar la celda de la cuadrícula en la que se encuentra, tendrías que hacer algo como lo siguiente:</p> + +<pre class="brush: css">img { + width: 100%; + height: 100%; +}</pre> + +<p>Sin embargo, esto deformaría la imagen, por lo que probablemente no es lo que querrías hacer.</p> + +<h2 id="Los_elementos_de_formulario">Los elementos de formulario</h2> + +<p>Los elementos de formulario pueden ser un problema si queremos diseñar con CSS, y el <a href="/es/docs/Learn/HTML/Forms">artículo sobre formularios web</a> contiene guías detalladas sobre los aspectos más complicados relativos a este tema, que no vamos a repetir en este artículo. Hay algunos conceptos básicos clave que vale la pena destacar en esta sección.</p> + +<p>Muchos controles de formulario se añaden con el elemento <code><a href="/en-US/docs/Web/HTML/Element/input"><input></a></code>: este elemento define desde campos de formulario simples, como entradas de texto, hasta campos más complejos añadidos en HTML5, como selectores de color y fecha. Hay algunos elementos adicionales, como <code><a href="/en-US/docs/Web/HTML/Element/textarea"><textarea></a></code> para la entrada de texto multilínea, y también elementos que se utilizan para contener y etiquetar partes de formularios como <code><a href="/en-US/docs/Web/HTML/Element/fieldset"><fieldset></a></code> y <code><a href="/en-US/docs/Web/HTML/Element/legend"><legend></a></code>.</p> + +<p>El HTML5 también incluye atributos que permiten a los desarrolladores web indicar qué campos son obligatorios e incluso el tipo de contenido que debe introducirse. Si el usuario añade algo inesperado o deja un campo obligatorio en blanco, el navegador puede mostrar un mensaje de error. Los diversos navegadores no presentan ningún estilo coherente ni ninguna homogeneización en cuanto a la personalización que permiten para tales elementos.</p> + +<h3 id="Aplicar_estilo_a_los_elementos_de_entrada_de_texto">Aplicar estilo a los elementos de entrada de texto</h3> + +<p>Los elementos que permiten la entrada de texto, como <code><input type="text"></code>, algunos tipos específicos como <code><input type="email"></code> y el elemento <code><textarea></code> son bastante fáciles de diseñar y tienden a comportarse como otras cajas de tu página. Sin embargo, el estilo predeterminado de estos elementos es diferente según el sistema operativo y el navegador con el que el usuario visite el sitio.</p> + +<p>En el ejemplo siguiente hemos diseñado algunas entradas de texto con CSS: puedes ver que algunos elementos como los bordes, los márgenes y el área de relleno se aplican como es de esperar. Utilizamos selectores de atributos para apuntar a los diferentes tipos de entrada. Intenta cambiar el aspecto de este formulario ajustando los bordes, añadiendo colores de fondo a los campos y cambiando las fuentes y área de relleno.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/images/form.html", '100%', 1000)}}</p> + +<div class="blockIndicator warning"> +<p><strong>¡Importante!</strong>: Al cambiar el estilo de los elementos de formulario debes asegurarte de que para el usuario sigue siendo obvio que se trata de elementos de formulario. Podrías crear una entrada de formulario sin bordes y un fondo que sea casi indistinguible del contenido que lo rodea, pero esto haría que sea muy difícil de reconocer y completar.</p> +</div> + +<p>Como se explica en los artículos sobre <a href="/es/docs/Learn/HTML/Forms/Styling_HTML_forms">el diseño de formularios</a> en la parte HTML de esta web, el sistema operativo presenta muchos de los tipos de entrada más complejos y son inaccesibles para el diseño. Por lo tanto, siempre debes suponer que los formularios se verán de manera bastante diferentes para los distintos visitantes, y deberás probar los formularios complejos en diversos navegadores.</p> + +<h3 id="Herencia_y_elementos_de_formulario">Herencia y elementos de formulario</h3> + +<p>En algunos navegadores, los elementos de formulario no heredan el estilo de letra por defecto. Por lo tanto, si deseas asegurarte de que tus campos de formulario usan la letra que se define para el cuerpo o para un elemento principal, debes añadir esta regla a tu CSS.</p> + +<pre class="brush: css"><code>button, +input, +select, +textarea { + font-family : inherit; + font-size : 100%; +} </code></pre> + +<h3 id="Elementos_de_formulario_y_tamaño_de_la_caja">Elementos de formulario y tamaño de la caja</h3> + +<p>Los elementos de formulario utilizan reglas diferentes en los diversos navegadores para el dimensionado de las cajas de los diferentes controles de formulario. Ya cubrimos la propiedad <code>box-sizing</code> en <a href="/es/docs/Learn/CSS/Building_blocks/El_modelo_de_caja">el artículo sobre el modelo de cajas</a>. Puedes usar este conocimiento cuando diseñes formularios que garanticen una experiencia homogénea en cuanto a los anchos y las alturas de los elementos de formulario.</p> + +<p>Por coherencia, es una buena idea establecer los márgenes y el área de relleno en <code>0</code> para todos los elementos, y luego establecerlos de nuevo al diseñar cada uno de los controles de formulario.</p> + +<pre class="brush: css"><code>button, +input, +select, +textarea { + box-sizing: border-box; + padding: 0; + margin: 0; +}</code></pre> + +<h3 id="Otros_ajustes_útiles">Otros ajustes útiles</h3> + +<p>Además de las reglas ya mencionadas, también debes configurar <code>overflow: auto</code> en <code><textarea></code> para que Internet Explorer no muestre una barra de desplazamiento cuando no hay necesidad:</p> + +<pre class="brush: css">textarea { + overflow: auto; +}</pre> + +<h3 id="Ponerlo_todo_junto_en_un_«Reinicio»">Ponerlo todo junto en un «Reinicio»</h3> + +<p>Como último paso podemos resumir las diversas propiedades expuestas en el «reinicio de formulario» siguiente para proporcionar una base coherente sobre la que trabajar. Esto incluye todos los elementos mencionados en las tres últimas secciones:</p> + +<pre class="brush: css"><code>button, +input, +select, +textarea { + font-family: inherit; + font-size: 100%; + box-sizing: border-box; + padding: 0; margin: 0; +} + +textarea { + overflow: auto; +} </code></pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Muchos desarrolladores utilizan las hojas de estilo de normalización para crear un conjunto de estilos de línea base para usar en todos los proyectos. Por lo general, estas hojas hacen cosas similares a las que acabamos de describir y garantizan que cualquier cosa que pueda ser diferente en distintos navegadores tenga establecido un valor por defecto coherente antes de que tú hagas tu propio trabajo con el CSS. Aunque ya no son tan importantes como lo eran antes, porque los navegadores suelen ser más homogéneos que en el pasado. Sin embargo, si deseas ver un ejemplo, consulta <a href="http://necolas.github.io/normalize.css/">Normalize.css</a>, que es una hoja de estilo muy popular que muchos proyectos utilizan como base.</p> +</div> + +<p>Para obtener más información sobre los formularios de estilo, echa un vistazo a los dos artículos en la sección HTML de estas guías.</p> + +<ul> + <li><a href="/es/docs/Learn/HTML/Forms/Styling_HTML_forms">Diseño de formularios web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Aspectos avanzados de aplicación de estilo a formularios</a></li> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>En este artículo hemos destacado algunas de las diferencias que se presentan cuando trabajas con imágenes o media, y otros elementos inusuales, en CSS. En el artículo siguiente veremos algunos consejos que te resultarán útiles cuando tengas que diseñar tablas HTML.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Sizing_items_in_CSS", "Learn/CSS/Building_blocks/Styling_tables", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascada y herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Selectores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de cajas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/index.html b/files/es/learn/css/building_blocks/index.html new file mode 100644 index 0000000000..ce15097a6c --- /dev/null +++ b/files/es/learn/css/building_blocks/index.html @@ -0,0 +1,94 @@ +--- +title: Bloques de construcción CSS +slug: Learn/CSS/Building_blocks +tags: + - Aprender + - CSS + - Principiante + - bloques de construcción +translation_of: Learn/CSS/Building_blocks +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Este módulo retoma donde <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos en CSS</a> finalizó — ahora que estás familiarizado con el lenguaje y su sintaxis, y que tienes algo de experiencia en su uso, es hora de bucear un poco más profundo. Este módulo se centra en el estilo en cascada de css y en el concepto de herencia, también veremos todos los tipos de selectores, unidades, tamaños, estilos de fondo, bordes, debugging y mucho más.</p> + +<p class="summary">El objetivo aqui es proveerte de herramientas para que puedas escribir código CSS competentemente y ayudarte a entender lo escencial de la teoría antes de centrarnos en disciplinas más específicas como <a href="/en-US/docs/Learn/CSS/Styling_text">text styling</a> y <a href="/en-US/docs/Learn/CSS/CSS_layout">CSS layout</a>.</p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Antes de comenzar este módulo deberías poseer:</p> + +<ol> + <li>Un entendimiento básico de la utilización de una computadora y de la<br> + navegación web a nivel de usuario.</li> + <li>Un entorno básico constituido en base a lo dispuesto en la guía <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">Instalación de software básico</a>, tanto como conocimiento acerca de la creación y la administración de archivos, como es detallado en <a href="https://developer.mozilla.org/en-US/docs/Learn/Getting_started_with_the_web/Dealing_with_files">Dealing with files</a>.</li> + <li>Una familiaridad básica con html, como es establecido en el módulo <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introdución a HTML</a>.</li> + <li>Un entendimiento elemental de CSS, como es discutido en el módulo <a href="/en-US/docs/Learn/CSS/First_steps">CSS first steps</a>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si estás trabajando en una computadora, tablet, u otro dispositivo en el que no eres capaz de crear tus propios archivos puedes intentar la mayor parte de los ejemplos en código en un programa para trabajar código en linea como <a href="http://jsbin.com/">JSBin</a> o <a href="https://glitch.com/">Glitch</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<p>En este módulo encontrarás artículos que cubren los fundamentos más esenciales del lenguaje CSS. A lo largo del módulo encontrarás múltiples ejercicios que te permitirán poner a prueba tu entendimiento.</p> + +<dl> + <dt><a href="/es/docs/Learn/CSS/Building_blocks/Cascada_y_herencia">Cascada y herencia</a></dt> + <dd>El objetivo de ésta lección es desarrollar tu entendimiento sobre algunos de los conceptos fundamentales de CSS - cascada, especificidad y herencia - los cuales controlan como CSS es aplicado a HTML y como sus conflitos son resueltos.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a></dt> + <dd>Hay una gran variedad de selectores disponibles en CSS, permitiendo una fina precision para seleccionar elementos de estilo. En este artículo y sub-artículos, repasaremos los diferentes tipos en detalle y veremos como funcionan. Los sub-artículos son los que siguinetes : + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, clase e ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de Atributos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Pseudo-clases y pseudo-elementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Combinadores</a></li> + </ul> + </dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de caja</a></dt> + <dd>Todo en CSS tiene una caja a su alrededor, y comprender estas cajas es clave para poder crear diseños con CSS, o para alinear elementos con otros elementos. En esta lección, analizaremos adecuadamente el modelo CSS Box, para que pueda pasar a tareas de diseño más complejas con una comprensión de cómo funciona y la terminología que se relaciona con él.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></dt> + <dd>En esta lección, veremos algunas de las cosas creativas que puede hacer con fondos y bordes CSS. Al agregar degradados, imágenes de fondo y esquinas redondeadas, los fondos y los bordes son la respuesta a muchas preguntas de estilo en CSS.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">Manejo de diferentes direcciones de texto</a></dt> + <dd>En los últimos años, CSS ha evolucionado para admitir mejor la diferente direccionalidad del contenido, incluyendo Right-to-left (Derecha a Izquierda) pero también de Top-to-bottom (Arriba a abajo ,como el japonés); estas diferentes direccionalidades se llaman <strong>modos de escritura</strong>. A medida que avance en su estudio y comience a trabajar con el diseño, comprenderá los modos de escritura será muy útil para usted, por lo tanto, los presentaremos en este artículo.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">Contenido desbordante</a></dt> + <dd>En esta lección veremos otro concepto importante en CSS: desbordamiento. El Overflow (o desbordamiento) es lo que sucede cuando hay demasiado contenido para contenerlo cómodamente dentro de una caja. En esta guía aprenderá qué es y cómo administrarlo.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Valores y unidades de CSS</a></dt> + <dd> + <p>Cada propiedad utilizada en CSS tiene un valor o conjunto de valores permitidos para esa propiedad. En esta lección veremos algunos de los valores y unidades más comunes en uso.</p> + </dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Dimensionar elementos en CSS</a></dt> + <dd>En las diversas lecciones hasta ahora, ha encontrado varias formas de dimensionar elementos en una página web utilizando CSS. Es importante comprender cuán grandes serán las diferentes características en su diseño, y en esta lección resumiremos las diversas formas en que los elementos obtienen un tamaño a través de CSS y definiremos algunos términos sobre el tamaño que lo ayudarán en el futuro.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, medios y elementos de forma</a></dt> + <dd> + <p>En esta lección veremos cómo se tratan ciertos elementos especiales en CSS. Las imágenes, otros medios y elementos de formulario se comportan de manera un poco diferente en términos de su capacidad para diseñarlos con CSS que los cuadros normales. Comprender qué es y qué no es posible puede ahorrar un poco de frustración, y esta lección resaltará algunas de las cosas principales que necesita saber.</p> + </dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Dando estilo a una tabla</a></dt> + <dd>Diseñar una tabla HTML no es el trabajo más glamoroso del mundo, pero a veces todos tenemos que hacerlo. Este artículo proporciona una guía para hacer que las tablas HTML se vean bien, con algunas técnicas específicas de diseño de tablas resaltadas.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depuración de CSS</a></dt> + <dd>A veces, al escribir CSS, encontrará un problema en el que su CSS no parece estar haciendo lo que espera. Este artículo le dará orientación sobre cómo solucionar un problema de CSS y le mostrará cómo las DevTools incluidas en todos los navegadores modernos pueden ayudarlo a descubrir qué está sucediendo.</dd> + <dt></dt> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizando tu CSS</a></dt> + <dd>A medida que comience a trabajar en hojas de estilo más grandes y grandes proyectos, descubrirá que mantener un gran archivo CSS puede ser un desafío. En este artículo, analizaremos brevemente algunas de las mejores prácticas para escribir su CSS para que sea fácil de mantener, y algunas de las soluciones que encontrará en uso para ayudar a mejorar la capacidad de mantenimiento.</dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<p>¿Quieres probar tus habilidades de CSS? Las siguientes evaluaciones pondrán a prueba su comprensión del CSS cubierto en las guías anteriores.</p> + +<dl> + <dt><a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Fundamental_CSS_comprehension">Comprensión de CSS básica</a></dt> + <dd>Esta evaluación evalúa su comprensión de la sintaxis básica, selectores, especificidad, modelo de caja y más.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Styling_boxes/Creating_fancy_letterheaded_paper">Crear papel con membrete elegante</a></dt> + <dd>Si desea causar la impresión correcta, escribir una carta en papel con membrete puede ser un buen comienzo. En esta evaluación, lo retaremos a crear una plantilla en línea para lograr ese aspecto.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Styling_boxes/A_cool_looking_box">Una caja de aspecto genial</a></dt> + <dd>Aquí aprenderás a usar el estilo de fondo y borde para crear un cuadro llamativo.</dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/CSS/Building_blocks/Advanced_styling_effects">Efectos de estilo avanzados</a></dt> + <dd>Este artículo actúa como una caja de trucos, brindando una introducción a algunas características de estilo avanzadas e interesantes como sombras de caja, modos de fusión y filtros.</dd> +</dl> diff --git a/files/es/learn/css/building_blocks/manejando_diferentes_direcciones_de_texto/index.html b/files/es/learn/css/building_blocks/manejando_diferentes_direcciones_de_texto/index.html new file mode 100644 index 0000000000..fa21de66e5 --- /dev/null +++ b/files/es/learn/css/building_blocks/manejando_diferentes_direcciones_de_texto/index.html @@ -0,0 +1,165 @@ +--- +title: Manejando diferentes direcciones de texto +slug: Learn/CSS/Building_blocks/Manejando_diferentes_direcciones_de_texto +tags: + - Aprendizaje + - CSS + - Diseño en bloque + - Diseño lineal + - Modos de escritura + - Principiante + - Propiedades lógicas +translation_of: Learn/CSS/Building_blocks/Handling_different_text_directions +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Backgrounds_and_borders", "Learn/CSS/Building_blocks/Overflowing_content", "Learn/CSS/Building_blocks")}}</div> + +<p>Muchas de las propiedades y valores que hemos encontrado hasta ahora en nuestro aprendizaje de CSS han estado ligadas a las dimensiones físicas de nuestra pantalla. Creamos bordes arriba, a la derecha, abajo y a la izquierda de una caja, por ejemplo. Estas dimensiones físicas se ajustan adecuadamente al contenido que se visualiza de forma horizontal, y por defecto, la web tiende a apoyar lenguajes de izquierda a derecha, como el castellano o el francés, mejor que aquellos que se escriben de derecha a izquierda, como el árabe.</p> + +<p>Sin embargo, en los últimos años, CSS ha evolucionado para soportar de mejor forma contenidos en diferente direccionalidad, incluyendo contenido de derecha a izquierda, pero también de arriba-abajo, como el japonés - Estas direccionalidades se llaman <strong>modos de escritura</strong>.<strong> </strong>En la medida que progresa tu estudio y comiences a trabajar con diseños, comprender los modos de escritura será de mucha utilidad para ti, por ello los explicaremos a continuación.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Literatura computacional básica, <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Installing_basic_software">software básico instalado</a>, conocimiento básico de <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">manejo de archivos</a>, HTML básico (<a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>), y una idea de cómo funciona CSS (<a href="/es/docs/Learn/CSS/First_steps">Primeros pasos en CSS</a>.)</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender la importancia de los modos de escritura en el CSS moderno.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_son_los_modos_de_escritura">¿Qué son los modos de escritura?</h2> + +<p>Un modo de escritura en CSS se refiere a si el texto está escrito horizontal o verticalmente. La propiedad {{cssxref("writing-mode")}} permite cambiar de un modo a otro. No necesitas estar trabajando en un lenguaje que use un modo de escritura vertical para querer hacer esto - Podrías cambiar el modo de escritura de partes de tu diseño por razones creativas.</p> + +<p>En el ejemplo siguiente existe un encabezado desplegado usando <code>writing-mode: vertical-rl</code>. El texto ahora aparece vertical. El texto vertical es común en diseño gráfico, y puede ser una forma de agregar un aspecto más interesante a tu diseño web.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/writing-modes/simple-vertical.html", '100%', 800)}}</p> + +<p>Los tres valores posibles para la propiedad <code><a href="/en-US/docs/Web/CSS/writing-mode">writing-mode</a></code> son:</p> + +<ul> + <li><code>horizontal-tb</code>: Dirección de flujo de bloque de arriba abajo. Las frases aparecen horizontales.</li> + <li><code>vertical-rl</code>: Dirección de flujo de bloque de derecha a izquierda. Las frases aparecen verticales.</li> + <li><code>vertical-lr</code>: Dirección de flujo de bloque de izquierda a derecha. Las frases aparecen verticales.</li> +</ul> + +<p>Así, la propiedad <code>writing-mode</code> está configurando en realidad la direccion en que los elementos de nivel bloque son desplegados en la página - ya sea de arriba abajo, derecha a izquierda, o de izquierda a derecha. Luego señala la dirección del flujo de texto en las frases.</p> + +<h2 id="Modos_de_escritura_y_diseño_en_bloque_y_lineal.">Modos de escritura y diseño en bloque y lineal.</h2> + +<p>Ya hemos visto el diseño en bloque y lineal, y el hecho de que algunas cosas se muestran como elementos de bloque y otras como elementos lineales. Ésto se encuentra ligado al modo de escritura del documento, y no de la pantalla física. Los bloques sólo se presentan desde la parte superior a la inferior de la página si estas usando un modo de escritura que presente el texto horizontalmente, como el español.</p> + +<p>Con el siguiente ejemplo quedará más claro. Si tienes dos cajas que contengan un <code>heading</code> y un <code>paragraph</code>. La primera usa <code>writing-mode: horizontal-tb</code>, un modo de escritura horizontal y desde la parte superior de la página a la base. La segunda usa <code>writing-mode: vertical-rl</code>; este es un modo de escritura vertical y de derecha a izquierda.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/writing-modes/block-inline.html", '100%', 1200)}}</p> + +<p>Cuando cambiamos el modo de escritura, estamos cambiando que dirección es en bloque y cuál es lineal. En un modo de escritura <code>horizontal-tb</code> El la direccion del bloque va de arriba abajo; en un modo de escritura <code>vertical-rl</code> el bloque corre de derecha a izquierda horizontalmente. De esta forma la <strong>dimensión del bloque</strong> es siempre la direccion en la que se muestran los bloques en el modo de escritura en uso. La <strong>dimensión lineal</strong>, es siempre la dirección en que fluye una frase.</p> + +<p>Este dibujo muestra las dos dimensiones en un modo de escritura horizontal.<img alt="Showing the block and inline axis for a horizontal writing mode." src="https://mdn.mozillademos.org/files/16574/horizontal-tb.png" style="height: 353px; width: 634px;"></p> + +<p>Este dibujo muestra las dos dimensiones en un modo de escritura vertical.</p> + +<p><img alt="Showing the block and inline axis for a vertical writing mode." src="https://mdn.mozillademos.org/files/16575/vertical.png" style="height: 472px; width: 406px;"></p> + +<p>Una vez que empieces a observar el diseño CSS, y en particular los nuevos métodos de diseño, esta idea de bloque y lineal cobra mayor importancia. Será revisado más adelante.</p> + +<h3 id="Dirección">Dirección</h3> + +<p>Además del modo de escritura también tenemos la dirección del texto. Como se mencionó antes, algunos idiomas como el Árabe se escriben horizontalmente, de derecha a izquierda. Esto no es algo que usarías en un sentido creativo. Si tu simplemente quieres alinear algún elemento a la derecha, existen otras formas de hacerlo. Sin embargo es importante entender esto como parte de la naturaleza del CSS. La web no es solo para lenguajes que son escritos de izquierda a derecha!</p> + +<p>Debido al hecho de que el modo de escritura y la dirección del texto pueden cambiar, los nuevos métodos de diseño CSS no toman como referencia la izquierda y derecha, ni la parte superior e inferior. En su lugar, hablarán de inicio y fin junto con esta idea de en línea y bloque. No te preocupes mucho por eso en este momento, pero ten en cuenta estas ideas a medida que empiezas a mirar el diseño de una página web; va a ser de gran ayuda en tu entendimiento de CSS.</p> + +<h2 id="Valores_y_propiedades_lógicas">Valores y propiedades lógicas</h2> + +<p>La razón de hablar acerca de modos de escritura y dirección en este punto en tu aprendizaje, es por el hecho de que ya vimos muchas de estas propiedades que están atadas a las dimensiones físicas de la pantalla, y tienen más sentido cuando está en un modo de escritura horizontal.</p> + +<p>Vamos a echarle un vistzo a nuestras dos cajas de nuevo, una con el modo escritura <code>horizontal-tb</code> y otro con <code>vertical-rl</code>. Le hemos dado a estas dos cajas un {{cssxref("width")}}. Puedes ver que cuando la caja está en el modo de escritura vertical, aún tiene una anchura, y esto está causando que el texto se desborde.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/writing-modes/width.html", '100%', 1200)}}</p> + +<p>Lo que nosotros realmente queremos en este escenario, es esencialmente intercambiar altura y anchura junto con el modo de escritura. Cuando estamos en el modo de escritura vertical, queremos que la caja se expanda en la dimensión del bloque así como lo hace en el modo horizontal.</p> + +<p>Para hacerlo más fácil, CSS ha desarrollado recientemente un conjunto de propiedades asignadas. Estas esencialmente reemplazan las propiedades físicas como <code>width </code>and <code>height</code>, con versiones <strong>lógicas</strong> o <strong>relativas al flujo</strong>.</p> + +<p>La propiedad asignada a <code>width</code> cuando está en el modo de escritura horizontal se llama {{cssxref("inline-size")}}, se refiere al tamaño en la dimensión inline. La propiedad para <code>height </code>se llama {{cssxref("block-size")}} y es el tamaño en la dimensión de bloque. Puedes ver como funciona en el ejemplo de abajo, donde reemplazamos <code>width</code> con <code>inline-size</code>.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/writing-modes/inline-size.html", '100%', 1200)}}</p> + +<h3 id="Propiedades_lógicas_margin_border_y_padding">Propiedades lógicas <code>margin</code>, <code>border</code> y <code>padding</code></h3> + +<p>En las últimas dos lecciones aprendimos acerca del modelo de cajas con CSS, y los bordes CSS. En las propiedades margin, border y padding vas a encontrar varias instancias de propiedades físicas, por ejemplo {{cssxref("margin-top")}}, {{cssxref("padding-left")}}, y {{cssxref("border-bottom")}}. Del mismo modo que tenemos asignaciones para ancho y alto, hay asignaciones para estas propiedades.</p> + +<p>La propiedad <code>margin-top</code> está asignada a {{cssxref("margin-block-start")}}, esto siempre se va a referir al margen al inicio de la dimensión del bloque. </p> + +<p>La propiedad {{cssxref("padding-left")}} se asigna a {{cssxref("padding-inline-start")}}, el padding que se aplica al inicio de la dirección inline. Aquí será donde las oraciones comienzan en ese modo de escritura. La propiedad {{cssxref("border-bottom")}} se asigna a {{cssxref("border-block-end")}}, que es el borde del final de la dimensión del bloque.</p> + +<p>Puedes ver una comparación entre las propiedades físicas y lógicas a continuación.</p> + + + +<p><strong>Si cambias el modo de escritura de las cajas asignando a la propiedad <code>writing-mode</code> en <code>.box</code> a <code>vertical-rl</code>, vas a ver como las propiedades físicas se quedan ligadas a sus direcciones físicas, mientras que las propiedades lógicas cambian con el modo de escritura.</strong></p> + +<p><strong>También puedes ver que el </strong><strong>{{htmlelement("h2")}} tiene un <code>border-bottom</code> negro. ¿Puedes averiguar como hacer que el borde inferior siempre esté debajo del texto en ambos modos de escritura?</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/writing-modes/logical-mbp.html", '100%', 1200)}}</p> + +<p>Existe un gran número de propiedades cuando consideras cada uno de los bordes que puedes hacer a mano, y puedes ver todas las propiedades asignadas en la página de MDN para <a href="https://wiki.developer.mozilla.org/es/docs/Web/CSS/CSS_Logical_Properties">propiedades Lógicas y Valores</a></p> + +<h3 id="Valores_lógicos">Valores lógicos</h3> + +<p>Hasta ahora hemos examinado los nombres de las propiedades lógicas. Existen también algunas propiedades que toman valores físicos de <code>top</code>, <code>right</code>, <code>bottom</code>, y <code>left</code>. Estos valores también tienen asignaciones a valores lógicos: <code>block-start</code>, <code>inline-end</code>, <code>block-end</code>, y <code>inline-start</code>.</p> + +<p>Por ejemplo, puedes hacer que una imagen flote a la izquierda para hacer que el texto se ajuste alrededor de la imagen. Puedes reemplazar <code>left</code> con <code>inline-start</code> como se muestra en el ejemplo a continuación.</p> + +<p><strong>Cambia el modo de escritura en este ejemplo a <code>vertical-rl</code> para ver que sucede con la imagen. Cambia <code>inline-start</code> por <code>inline-end</code> para cambiar el modo en que flota.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/writing-modes/float.html", '100%', 1200)}}</p> + +<p>Aquí también estamos usando valores lógicos de el margen para asegurar que el margen está en el sitio correcto sin importar que modo de escritura es.</p> + +<div class="blockIndicator note"> +<p>Actualmente, solo Firefox soporta valores relativos de flujo para <code>float</code>. Si estás usando <strong>Google Chrome </strong>o <strong>Microsoft Edge</strong>, deberías ver que la imagen no flota.</p> +</div> + +<h3 id="¿Debería_usar_propiedades_físicas_o_lógicas">¿Debería usar propiedades físicas o lógicas?</h3> + +<p>Las propiedades lógicas y los valores son más recientes que su equivalente físico, y por lo tanto se han implementado recientemente en los navegadores. Puedes revisar cualquier página de propiedades en MDN para ver hasta donde llega el soporte del navegador. Si no estás usando multiples modos de escritura, entonces, por ahora, deberías preferir usar las versiones físicas. Sin embargo, en última instancia, esperamos que la gente va a pasar a las versiones lógicas para la mayoría de las cosas, ya que tienen mucho sentido una vez que comienzas a tratar también con métodos de diseño como Flexbox y Grid.</p> + +<h2 id="¡Prueba_tus_habilidades!">¡Prueba tus habilidades!</h2> + +<p>Tenemos mucho terreno cubierto en este artículo, pero puedes recordad la información más importante? Puedes encontrar algunas pruebas adicionales para verificar que has retenido esta información antes de seguir adelante: <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Writing_Modes_Tasks">Prueba tus habilidades: modos de escritura.</a></p> + +<h2 id="Resumen">Resumen</h2> + +<p>Los conceptos explicados en esta lección son cada vez más importantes en CSS. Un entendimiento pleno de las direcciones en bloque y en línea, y como el flujo de texto cambia con la variación de los modos de escritura, van a ser de gran ayuda en el futuro. Te ayudará a entender CSS incluso si nunca usas un modo de escritura diferente al horizontal.</p> + +<p>En el módulo siguiente, vamos a echar un buen vistazo al desbordamiento en CSS</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Backgrounds_and_borders", "Learn/CSS/Building_blocks/Overflowing_content", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/es/docs/Learn/CSS/Building_blocks/Cascada_y_herencia">Cascada y herencia</a></li> + <li><a href="/es/docs/Web/CSS/Selectores_CSS">Selectores CSS</a> + <ul> + <li><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_tipo_clase_e_ID">Selectores de tipo, clase e ID</a></li> + <li><a href="/es/docs/Web/CSS/Selectores_atributo">Selectores de atributo</a></li> + <li><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Pseudo-clases_y_pseudo-elementos">Pseudoclases y pseudoelementos</a></li> + <li><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Combinadores">Combinadores</a></li> + </ul> + </li> + <li><a href="/es/docs/Learn/CSS/Building_blocks/El_modelo_de_caja">The box model</a></li> + <li><a href="/es/docs/Learn/CSS/Building_blocks/Fondos_y_bordes">Backgrounds and borders</a></li> + <li><a href="/es/docs/Learn/CSS/Building_blocks/Manejando_diferentes_direcciones_de_texto">Handling different text directions</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">Overflowing content</a></li> + <li><a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS">Values and units</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Sizing items in CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Images, media, and form elements</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Styling tables</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Debugging CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizing your CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/selectores_css/combinadores/index.html b/files/es/learn/css/building_blocks/selectores_css/combinadores/index.html new file mode 100644 index 0000000000..54f416456d --- /dev/null +++ b/files/es/learn/css/building_blocks/selectores_css/combinadores/index.html @@ -0,0 +1,111 @@ +--- +title: Combinadores +slug: Learn/CSS/Building_blocks/Selectores_CSS/Combinadores +translation_of: Learn/CSS/Building_blocks/Selectors/Combinators +--- +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks/The_box_model", "Learn/CSS/Building_blocks")}}</p> + +<p>Los últimos selectores que veremos son los llamados selectores de combinación. Se llaman así porqué combinan otros selectores de manera que proporciona una relación útil entre ellos y la ubicación del contenido en el documento.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, HTML básico (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con el CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Conocer los diferentes selectores de combinación que se pueden utilizar en el CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="Selector_de_descendientes">Selector de descendientes</h2> + +<p>Ya hemos visto los selectores de descendientes en artículos anteriores (selectores con espacios entre ellos):</p> + +<pre class="brush: css notranslate">body article p</pre> + +<p>Estos selectores seleccionan elementos que son descendientes de otros selectores. No es necesario que sean hijos directos.</p> + +<p>En el ejemplo siguiente seleccionamos solo el elemento <code><p></code> que hay dentro de un elemento con una clase <code>.box</code>.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/descendant.html", '100%', 500)}}</p> + +<h2 id="Selector_de_combinación_de_elementos_hijo">Selector de combinación de elementos hijo</h2> + +<p>El selector de combinación de elementos hijo es un símbolo de «mayor que» (<code>></code>), que selecciona solo cuando los selectores identifican elementos que son hijos directos. Los elementos descendientes que se encuentran más abajo en la jerarquía no se seleccionan. Por ejemplo, para seleccionar solo los elementos <code><p></code> que son hijos directos de elementos <code><article></code>:</p> + +<pre class="brush: css notranslate">article > p</pre> + +<p>En el ejemplo siguiente hay una lista ordenada anidada dentro de otra lista no ordenada. Utilizamos los selectores de elementos hijo para seleccionar solo los elementos <code><li></code> que son hijos directos de <code><ul></code> y les aplicamos un borde superior.</p> + +<p>Si eliminamos el símbolo <code>></code> que lo identifica como un selector de elementos hijo, lo convertimos en un selector de elementos descendientes y se aplicará el borde rojo a todos los elementos <code><li></code>.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/child.html", '100%', 600)}}</p> + +<h2 id="Hermanos_adyacentes">Hermanos adyacentes</h2> + +<p>El selector de elementos hermanos adyacentes (<code>+</code>) se utiliza para seleccionar un elemento que se encuentra justo al lado de otro elemento en el mismo nivel de la jerarquía. Por ejemplo, para seleccionar todos los elementos <code><img></code> que aparecen justo después de elementos <code><p></code>:</p> + +<pre class="brush: css notranslate">p + img</pre> + +<p>El caso de uso más común es modificar el párrafo que va justo después del título, como en el ejemplo siguiente. Vamos a buscar un párrafo que sea directamente adyacente a <code><h1></code> y le vamos a aplicar un estilo.</p> + +<p>Si insertas algún otro elemento, como <code><h2></code> entre las etiquetas <code><h1></code> y <code><p></code>, verás que el selector ya no selecciona el párrafo y no se muestra con los mismos colores de fondo y de primer plano que cuando es adyacente.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/adjacent.html", '100%', 800)}}</p> + +<h2 id="Hermanos_generales">Hermanos generales</h2> + +<p>Si deseas seleccionar los hermanos de un elemento, incluso si no son directamente adyacentes, puedes utilizar el combinador de hermanos general (<code>~</code>). Por ejemplo, para seleccionar todos los elementos <code><img></code> que aparecen <em>después</em> de los elementos <code><p></code>, hacemos esto:</p> + +<pre class="brush: css notranslate">p ~ img</pre> + +<p>En el ejemplo siguiente seleccionamos todos los elementos <code><p></code> que vienen después de <code><h1></code>, y aunque en el documento también hay un <code><div></code>, se selecciona incluso la etiqueta <code><p></code> que viene después.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/general.html", '100%', 600)}}</p> + +<h2 id="El_uso_de_selectores_de_combinación">El uso de selectores de combinación</h2> + +<p>Puedes combinar cualquiera de los selectores de los artículos anteriores con selectores de combinación para seleccionar una parte del documento. Por ejemplo, podrías utilizar el código siguiente para seleccionar elementos de una lista con una clase «a» que son hijos directos de <code><ul></code>:</p> + +<pre class="brush: css notranslate">ul > li[class="a"] { }</pre> + +<p>Ten cuidado cuando creas largas listas de selectores que seleccionan partes del documento muy específicas. Te será difícil volver a utilizar las reglas CSS porque has definido un selector muy específico para la ubicación del elemento en el marcado.</p> + +<p>A menudo es mejor crear una clase sencilla y aplicarla al elemento en cuestión. Dicho esto, tu conocimiento de los selectores de combinación te será muy útil si necesitas modificar algo del documento y no puedes acceder al código HTML (tal vez porque se haya generado a partir de CMS).</p> + +<h2 id="Comprueba_tus_habilidades">Comprueba tus habilidades</h2> + +<p>Hemos cubierto mucho terreno en este artículo. ¿Recuerdas la información más importante? Encontrarás más pruebas para verificar que retienes esa información en <a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Selectors_Tasks">Test your skills: Selectors</a>.</p> + +<h2 id="Continuamos">Continuamos</h2> + +<p>Esta es la última sección de nuestros artículos sobre selectores. A continuación vamos a pasar a otra parte importante del CSS: <a href="/es/docs/Learn/CSS/Building_blocks/El_modelo_de_caja">el modelo de caja CSS</a>.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks/The_box_model", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">La cascada y la herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Selectores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de caja</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Elementos de imagen, de media y de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Estilo de las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/selectores_css/index.html b/files/es/learn/css/building_blocks/selectores_css/index.html new file mode 100644 index 0000000000..d0ea61da20 --- /dev/null +++ b/files/es/learn/css/building_blocks/selectores_css/index.html @@ -0,0 +1,223 @@ +--- +title: Selectores CSS +slug: Learn/CSS/Building_blocks/Selectores_CSS +translation_of: Learn/CSS/Building_blocks/Selectors +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Cascade_and_inheritance", "Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks")}}</div> + +<p class="summary">En {{Glossary( "CSS")}} los selectores se utilizan para delimitar los elementos {{glossary("HTML")}} de nuestra página web a los que queremos aplicar estilo. Hay una amplia variedad de selectores CSS, lo que permite una gran precisión a la hora de seleccionar elementos a los que aplicar estilo. En este artículo y sus subartículos veremos con detalle todos los tipos y el modo como funcionan.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Nociones básicas de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, conocimientos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y una idea de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender con detalle cómo funcionan los selectores CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_un_selector">¿Qué es un selector?</h2> + +<p>En un artículo anterior explicamos qué son los selectores. Un selector CSS es la primera parte de una regla CSS. Es un patrón de elementos y otros términos que indican al navegador qué elementos HTML se seleccionan para aplicarles una regla que incluye los valores de las propiedades CSS. El elemento o los elementos seleccionados por el selector se denominan <em>sujeto del selector</em>.</p> + +<p><img alt="Fragmento de código con el elemento h1 resaltado." src="https://mdn.mozillademos.org/files/16550/selector.png" style="border: 1px solid #cccccc; height: 218px; width: 471px;"></p> + +<p>En artículos anteriores ya has visto algunos selectores y has aprendido que hay diversas maneras de organizar el documento. Por ejemplo, seleccionando un elemento, como <code>h1</code>, o seleccionando una clase, como <code>.special</code>.</p> + +<p>En CSS, los selectores se definen en la especificación de selectores de CSS correspondiente; al igual que cualquier otro elemento de CSS, es necesario que los navegadores los admitan para que funcionen. La mayoría de los selectores que encontrarás se definen en <a href="https://www.w3.org/TR/selectors-3/">especificación de nivel 3 de selectores</a>, que es una especificación consolidada y, por lo tanto, la mayoría de navegadores admitirán esos selectores.</p> + +<h2 id="Listas_de_selectores">Listas de selectores</h2> + +<p>Si más de un elemento utiliza el mismo CSS, puedes combinar los selectores en una <em>lista de selectores</em> para que la regla se aplique a cada uno de los selectores individuales. Por ejemplo, si tengo el mismo CSS para un <code>h1</code> y para una clase <code>.special</code>, los puedo escribir como dos reglas separadas.</p> + +<pre class="brush: css notranslate"><code>h1 { + color: blue; +} + +.special { + color: blue; +} </code></pre> + +<p>También los podrías combinar en una lista de selectores, separándolos con una coma.</p> + +<pre class="brush: css notranslate"><code>h1, .special { + color: blue; +} </code></pre> + +<p>Es posible dejar un espacio en blanco tanto antes como después de la coma. Incluso puede resultar más legible si cada selector se encuentra en una línea distinta.</p> + +<pre class="brush: css notranslate"><code>h1, +.special { + color: blue; +} </code></pre> + +<p>En el ejemplo siguiente, intenta combinar los dos selectores de modo que tengan la misma declaración. El aspecto visual debe permanecer igual tras la combinación.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/selector-list.html", '100%', 1000)}} </p> + +<p>Cuando agrupas los selectores de esta manera, si alguno de los selectores no es válido, el navegador sencillamente ignora toda la regla.</p> + +<p>En el ejemplo siguiente, la regla que corresponde al selector de clase que no es válido se ignora, mientras que el estilo se aplica al elemento <code>h1</code>.</p> + +<pre class="brush: css notranslate"><code>h1 { + color: blue; +} + +..special { + color: blue; +} </code></pre> + +<p>Sin embargo, si se combinan, toda la regla se considera no válida y no se aplicará estilo ni a <code>h1</code> ni a la clase.</p> + +<pre class="brush: css notranslate"><code>h1, ..special { + color: blue; +} </code></pre> + +<h2 id="Tipos_de_selectores">Tipos de selectores</h2> + +<p>Hay diferentes agrupaciones de selectores, y conocer qué tipo de selector necesitas te ayudará a encontrar la herramienta adecuada para tu trabajo. En estos subartículos vamos a ver los diferentes grupos de selectores con más detalle.</p> + +<h3 id="Selectores_de_tipo_de_clase_y_de_ID">Selectores de tipo, de clase y de ID</h3> + +<p>Este grupo incluye selectores que delimitan un elemento HTML, como por ejemplo un <code><h1></code>.</p> + +<pre class="brush: css notranslate">h1 { }</pre> + +<p>También incluye selectores que delimitan una clase:</p> + +<pre class="brush: css notranslate">.box { }</pre> + +<p>o un ID:</p> + +<pre class="brush: css notranslate">#unique { }</pre> + +<h3 id="Selectores_de_atributo">Selectores de atributo</h3> + +<p>Este grupo de selectores te proporciona diferentes formas de seleccionar elementos según la presencia de un atributo determinado en un elemento:</p> + +<pre class="brush: css notranslate">a[title] { }</pre> + +<p>O incluso hacer una selección basada en la presencia de un atributo que tiene un valor particular asignado:</p> + +<pre class="brush: css notranslate">a[href="https://example.com"] { }</pre> + +<h3 id="Las_pseudoclases_y_los_pseudoelementos">Las pseudoclases y los pseudoelementos</h3> + +<p>Este grupo de selectores incluye pseudoclases, que aplican estilo a ciertos estados de un elemento. La pseudoclase <code>:hover</code>, por ejemplo, selecciona un elemento solo cuando se le pasa el ratón por encima.</p> + +<pre class="brush: css notranslate">a: hover {}</pre> + +<p>También incluye pseudoelementos, que seleccionan una parte determinada de un elemento en vez del elemento en sí. Por ejemplo, <code>::first-line</code> siempre selecciona la primera línea del texto que se encuentra dentro de un elemento (<code><p></code>, en el ejemplo siguiente), y actúa como si un elemento <code><span></code> hubiera delimitado la primera línea, seleccionado y aplicado estilo.</p> + +<pre class="brush: css notranslate">p::first-line { }</pre> + +<h3 id="Combinadores">Combinadores</h3> + +<p>El último grupo de selectores combina otros selectores con el fin de delimitar elementos de nuestros documentos. El ejemplo siguiente selecciona los párrafos que son hijos directos del elemento <code><article></code> utilizando el operador de combinación hijo (<code>></code>):</p> + +<pre class="brush: css notranslate">article > p { }</pre> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<p>Echa un vistazo a esta tabla de referencia de selectores que contiene enlaces directos a los distintos tipos de selectores que se explican en nuestra sección de aprendizaje o en MDN, o bien sigue adelante e inicia tu viaje para averiguar cómo funcionan en <a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_tipo_clase_e_ID">Selectores de tipo, de clase y de ID</a>.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Cascade_and_inheritance", "Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="Tabla_de_referencia_de_selectores">Tabla de referencia de selectores</h2> + +<p>La tabla que te mostramos a continuación proporciona una descripción general de los selectores que puedes utilizar junto con enlaces a diversas páginas de esta guía que te mostrarán cómo utilizar cada tipo de selector. También hemos incluido un enlace a la página MDN de cada selector para poder comprobar la información sobre los navegadores que lo admiten. Puedes utilizarlo como referencia para volver cuando necesites buscar los selectores a medida que avanzas con la materia o mientras experimentas con CSS por tu cuenta.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Ejemplo</th> + <th scope="col">Tutorial de aprendizaje de CSS</th> + </tr> + </thead> + <tbody> + <tr> + <td><a href="/es/docs/Web/CSS/Type_selectors">Selector de tipo</a></td> + <td><code>h1 { }</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_tipo_clase_e_ID#Tipos_de_selectores">Los tipos de selectores</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Universal_selectors">Selector universal</a></td> + <td><code>* { }</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_tipo_clase_e_ID#El_selector_universal">El selector universal</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Class_selectors">Selector de clase</a></td> + <td><code>.box { }</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_tipo_clase_e_ID#Selectores_de_clase">Los selectores de clase</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/ID_selectors">Selector de ID</a></td> + <td><code>#unique { }</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_tipo_clase_e_ID#Selectores_de_ID">Los selectores de ID</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Selectores_atributo">Selector de atributo</a></td> + <td><code>a[title] { }</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_atributos">Los selectores de atributo</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Pseudo-classes">Pseudoclase</a></td> + <td><code>p:first-child { }</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Pseudo-clases_y_pseudo-elementos#%C2%BFQu%C3%A9_es_una_pseudoclase">Las pseudoclases</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Pseudoelementos">Pseudoelemento</a></td> + <td><code>p::first-line { }</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Pseudo-clases_y_pseudo-elementos#%C2%BFQu%C3%A9_es_un_pseudoelemento">Los pseudoelementos</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Descendant_combinator">Operadores de combinación descendentes</a></td> + <td><code>article p</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Combinadores#Selector_de_descendientes">Operadores de combinación descendentes</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Child_combinator">Operador de combinación de elementos hijo</a></td> + <td><code>article > p</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Combinadores#Selector_de_combinaci%C3%B3n_de_elementos_hijo">Operadores de combinación de elementos hijo</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Selectores_hermanos_adyacentes">Operador de combinación de elementos hermanos adyacentes</a></td> + <td><code>h1 + p</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Combinadores#Hermanos_adyacentes">Hermanos adyacentes</a></td> + </tr> + <tr> + <td><a href="/es/docs/Web/CSS/Selectores_hermanos_generales">Operador de combinación general de elementos hermanos</a></td> + <td><code>h1 ~ p</code></td> + <td><a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Combinadores#Hermanos_generales">Hermanos generales</a></td> + </tr> + </tbody> +</table> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">La cascada y la herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Operadores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de caja</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/selectores_css/pseudo-clases_y_pseudo-elementos/index.html b/files/es/learn/css/building_blocks/selectores_css/pseudo-clases_y_pseudo-elementos/index.html new file mode 100644 index 0000000000..f48dfdcbd5 --- /dev/null +++ b/files/es/learn/css/building_blocks/selectores_css/pseudo-clases_y_pseudo-elementos/index.html @@ -0,0 +1,397 @@ +--- +title: Pseudoclases y pseudoelementos +slug: Learn/CSS/Building_blocks/Selectores_CSS/Pseudo-clases_y_pseudo-elementos +translation_of: Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements +--- +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks")}}</p> + +<p>El conjunto de selectores que estudiaremos en este artículo se conocen como <strong>pseudoclases</strong> y <strong>pseudoelementos</strong>. Hay muchos y a menudo sirven para fines muy específicos. Una vez que sepas cómo usarlos, puedes echar un vistazo a la lista para ver si alguno sirve para la página que quieres crear. Una vez más, la página correspondiente de MDN resulta muy útil para conocer qué navegadores los admiten o no.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, HTML básico (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con el CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Obtener información sobre los selectores de pseudoclases y pseudoelementos.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_una_pseudoclase">¿Qué es una pseudoclase?</h2> + +<p>Una pseudoclase es un selector que marca los elementos que están en un estado específico, por ejemplo, los que son el primer elemento de su tipo, o aquellos por los que el cursor les pasa por encima. Tienden a actuar como si hubieras aplicado una clase en una parte determinada del documento y, a menudo, ayudan a reducir el exceso de clases y proporcionan un marcado más flexible y fácil de mantener.</p> + +<p>Las pseudoclases son palabras clave que comienzan con dos puntos:</p> + +<pre class="notranslate">:<em>pseudo-class-name</em></pre> + +<h3 id="Ejemplos_simples_de_pseudoclases">Ejemplos simples de pseudoclases</h3> + +<p>Echemos un vistazo a algunos ejemplos. Si queremos el primer párrafo de un artículo en letra más grande y en negrita, podemos añadir una clase a ese párrafo y luego añadirle CSS a esa clase, como se muestra en este ejemplo:</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/first-child.html", '100%', 800)}}</p> + +<p>Sin embargo, podría ser complicado de mantener. ¿Y si añadiésemos un párrafo nuevo en la parte superior del documento? Habría que mover la clase para que quede antes del nuevo párrafo. En lugar de añadir la clase, podríamos utilizar el selector de pseudoclase {{cssxref(":first-child")}}, que <em>siempre</em> seleccionará el primer elemento hijo del artículo, y de esta forma no tendremos que editar el código HTML (esto no siempre es posible, tal vez debido a que lo genera un CMS).</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/first-child2.html", '100%', 700)}}</p> + +<p>Todas las pseudoclases se comportan del mismo modo. Seleccionan un fragmento del documento que está en un estado determinado y se comportan como si se hubiera añadido una clase a su HTML. Echa un vistazo a otros ejemplos en MDN:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/CSS/:last-child">:last-child</a></code></li> + <li><code><a href="/en-US/docs/Web/CSS/:only-child">:only-child</a></code></li> + <li><code><a href="/en-US/docs/Web/CSS/:invalid">:invalid</a></code></li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota:</strong> Es válido escribir pseudoclases y pseudoelementos sin que les preceda un selector de elemento. En el ejemplo anterior, podría escribirse <code>:first-child</code> y la regla se aplicaríaa cualquier elemento que sea el primer hijo de un elemento <code><article></code>, no solo un párrafo primer hijo. <code>:first-child</code> equivale a <code>*:first-child</code>. Pero normalmente se quiere más control y hay que ser más específico.</p> +</div> + +<h3 id="Pseudoclases_de_acción_de_usuario">Pseudoclases de acción de usuario</h3> + +<p>Algunas pseudoclases solo intervienen cuando el usuario interactúa con el documento de alguna manera. Estas pseudoclases de <strong>acción de usuario</strong>, que también reciben el nombre de <strong>pseudoclases dinámicas</strong>, actúan como si se añadiese una clase al elemento cuando el usuario interactúa con él. Algunos ejemplos son:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/CSS/:hover">:hover</a></code>: solo interviene si el usuario pasa el cursor sobre un elemento, normalmente un enlace.</li> + <li><code><a href="/en-US/docs/Web/CSS/:focus">:focus</a></code>: solo interviene si el usuario selecciona el elemento con los controles del teclado.</li> +</ul> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/hover.html", '100%', 500)}}</p> + +<h2 id="¿Qué_es_un_pseudoelemento">¿Qué es un pseudoelemento?</h2> + +<p>Los pseudoelementos se comportan de manera similar. Sin embargo, actúan como si hubieras añadido un elemento HTML totalmente nuevo en el marcado, en lugar de haber aplicado una clase nueva a los elementos presentes. Los pseudoelementos empiezan con un doble signo de dos puntos <code>::</code>.</p> + +<pre class="notranslate"><em>::pseudo-element-name</em></pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Algunos de los primeros pseudoelementos utilizaban la sintaxis de un solo signo de dos puntos, así que puede ser que en ocasiones los veas escritos de esta forma en algún código o ejemplo. Los navegadores modernos leen tanto los pseudoelementos con la sintaxis de los dos puntos simple como la de los dos puntos doble para garantizar la compatibilidad retrospectiva.</p> +</div> + +<p>Por ejemplo, si deseas seleccionar la primera línea de un párrafo simplemente puedes delimitarlo con el elemento <code><span></code> y utilizar un selector de elementos. Sin embargo, fallará si el número de palabras que has delimitado resulta ser más largo o más corto que el ancho del elemento padre. Ya que normalmente no sabemos cuántas palabras caben en una línea porque esto cambia con el ancho de la pantalla o con los cambios de tamaño de la letra, no es posible hacer esto introduciendo solo HTML.</p> + +<p>El pseudoelemento <code>::first-line</code> soluciona este problema: no importa si el número de palabras aumenta o disminuye, siempre se selecciona la primera línea.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/first-line.html", '100%', 800)}}</p> + +<p>Actúa como si hubiera un elemento <code><span></code> mágicamente delimitando esa primera línea, que se actualiza cada vez que la longitud de la línea cambia.</p> + +<p>Puedes observar que en ambos párrafos se selecciona la primera línea.</p> + +<h2 id="Combinar_pseudoclases_y_pseudoelementos">Combinar pseudoclases y pseudoelementos</h2> + +<p>Si quieres poner en negrita la primera línea del primer párrafo, puedes encadenar los selectores <code>:first-child</code> y <code>::first-line</code>. Añade al ejemplo anterior el CSS siguiente. Queremos que se seleccione la primera línea del primer elemento <code><p></code> que esté dentro de un elemento <code><article></code>.</p> + +<pre class="brush: css notranslate"><code>article p:first-child::first-line { + font-size: 120%; + font-weight: bold; +}</code></pre> + +<h2 id="Generar_contenido_con_before_y_after">Generar contenido con ::before y ::after</h2> + +<p>Hay un par de pseudoelementos especiales que se utilizan junto con la propiedad de <code><a href="/en-US/docs/Web/CSS/content">content</a></code> para introducir contenido en el documento usando el CSS.</p> + +<p>Puedes utilizarlos para insertar una cadena de texto, como en el ejemplo siguiente. Intenta cambiar el valor del texto de la propiedad {{cssxref("content")}} y observa el cambio en la salida. También puedes cambiar el pseudoelemento <code>::before</code> por <code>::after</code> y verás que el texto se inserta al final del elemento, en lugar de al principio.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/before.html", '100%', 400)}}</p> + +<p>Sin embargo, en realidad no es habitual insertar cadenas de texto desde el CSS, porque ese texto resulta inaccesible para algunos lectores de pantalla y puede ser difícil de buscar y modificar en el futuro.</p> + +<p>Un uso más adecuado de estos pseudoelementos es insertar un icono. Por ejemplo, la pequeña flecha que añadimos en el ejemplo siguiente es un indicador visual que no queremos que el lector de pantalla muestre:</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/after-icon.html", '100%', 400)}}</p> + +<p>Estos pseudoelementos también se utilizan con frecuencia para insertar una cadena vacía a la que luego se le puede aplicar estilo, como a cualquier otro elemento de la página.</p> + +<p>En el ejemplo siguiente hemos añadido una cadena vacía mediante el pseudoelemento <code>::before</code>. Le hemos asociado <code>display: block</code> para poder aplicarle estilo para que tenga una anchura y una altura determinadas. A continuación, utilizamos el CSS para aplicar estilo de la misma forma que lo haríamos con cualquier otro elemento. Juega con el CSS y cambia la forma en que se ve y se comporta.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/before-styled.html", '100%', 500)}}</p> + +<p>El uso de los pseudoelementos <code>::before</code> y <code>::after</code>, junto con la propiedad <code>content</code> se conoce como «contenido generado» en CSS, y verás que esta técnica se utiliza a menudo para diversas tareas. Un buen ejemplo es la página web <a href="http://www.cssarrowplease.com/">CSS Arrow Please</a>, que te ayuda a generar una flecha con CSS. Echa un vistazo al CSS a medida que creas tu flecha y verás cómo funcionan los pseudoelementos {{cssxref("::before")}} y {{cssxref("::after")}}. Cada vez que veas estos selectores, echa un vistazo a la propiedad {{cssxref("content")}} para ver qué se añade al documento.</p> + +<h2 id="Sección_de_referencia">Sección de referencia</h2> + +<p>Hay un gran número de pseudoclases y pseudoelementos, así que resulta útil tener una lista para ir consultándolos. A continuación encontrarás un par de tablas con enlaces a sus páginas de referencia en MDN. Tómalas como referencia para ver de qué dispones para seleccionar qué tipos de elementos.</p> + +<h3 id="Las_pseudoclases">Las pseudoclases</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ Cssxref(":active") }}</td> + <td>Selecciona un elemento cuando el usuario lo activa (por ejemplo, con un clic).</td> + </tr> + <tr> + <td>{{ Cssxref(":any-link") }}</td> + <td>Selecciona los estados <code>:link</code> y <code>:visited</code> de un enlace.</td> + </tr> + <tr> + <td>{{ Cssxref(":blank") }}</td> + <td>Selecciona un <a href="/es/docs/Web/HTML/Elemento/input">elemento <code><input></code></a> cuyo valor de entrada está vacío.</td> + </tr> + <tr> + <td>{{ Cssxref(":checked") }}</td> + <td>Selecciona un botón de opción o casilla de verificación en el estado que determines.</td> + </tr> + <tr> + <td>{{ Cssxref(":current") }}</td> + <td>Selecciona el elemento que se muestra en ese momento, o un ancestro de ese elemento.</td> + </tr> + <tr> + <td>{{ Cssxref(":default") }}</td> + <td>Selecciona uno o más elementos de interfaz de usuario cuyo valor es el predeterminado de entre un conjunto de elementos similares.</td> + </tr> + <tr> + <td>{{ Cssxref(":dir") }}</td> + <td>Selecciona un elemento según su direccionalidad (valor del atributo <code><a href="/en-US/docs/Web/HTML/Global_attributes/dir">dir</a></code> de HTML o propiedad <code><a href="/en-US/docs/Web/CSS/direction">direction</a></code> de CSS).</td> + </tr> + <tr> + <td>{{ Cssxref(":disabled") }}</td> + <td>Selecciona elementos de la interfaz de usuario que están en estado inactivo.</td> + </tr> + <tr> + <td>{{ Cssxref(":empty") }}</td> + <td>Selecciona un elemento que no tiene elementos hijo, excepto por algún espacio en blanco opcional.</td> + </tr> + <tr> + <td>{{ Cssxref(":enabled") }}</td> + <td>Selecciona elementos de la interfaz de usuario que están en estado activo.</td> + </tr> + <tr> + <td>{{ Cssxref(":first") }}</td> + <td>En <a href="/en-US/docs/Web/CSS/Paged_Media">Paged Media</a>, selecciona la primera página.</td> + </tr> + <tr> + <td>{{ Cssxref(":first-child") }}</td> + <td>Selecciona el primero entre elementos hermanos.</td> + </tr> + <tr> + <td>{{ Cssxref(":first-of-type") }}</td> + <td>Selecciona el primero entre un tipo determinado de elementos hermanos.</td> + </tr> + <tr> + <td>{{ Cssxref(":focus") }}</td> + <td>Selecciona el elemento que tiene el foco.</td> + </tr> + <tr> + <td>{{ Cssxref(":focus-visible")}}</td> + <td>Selecciona el elemento que tiene el foco cuando el foco tiene que estar visible para el usuario.</td> + </tr> + <tr> + <td>{{ Cssxref(":focus-within") }}</td> + <td>Selecciona el elemento que tiene el foco y el elemento con un descendiente que tiene el foco.</td> + </tr> + <tr> + <td>{{ Cssxref(":future") }}</td> + <td>Selecciona los elementos que van después del elemento en curso.</td> + </tr> + <tr> + <td>{{ Cssxref(":hover") }}</td> + <td>Selecciona un elemento cuando el usuario interactúa con él.</td> + </tr> + <tr> + <td>{{ Cssxref(":indeterminate") }}</td> + <td>Selecciona elementos de interfaz de usuario cuyo valor está en un estado no determinado, por lo general se trata de <a href="/es/docs/Web/HTML/Elemento/input/checkbox">casillas de verificación</a>.</td> + </tr> + <tr> + <td>{{ Cssxref(":in-range") }}</td> + <td>Selecciona un elemento cuyo valor se encuentra dentro de un rango de valores determinado.</td> + </tr> + <tr> + <td>{{ Cssxref(":invalid") }}</td> + <td>Selecciona un elemento, como por ejemplo un <code><input></code>, cuyo estado es no válido.</td> + </tr> + <tr> + <td>{{ Cssxref(":lang") }}</td> + <td>Selecciona un elemento según el idioma (valor del atributo <a href="/es/docs/Web/HTML/Atributos_Globales/lang">lang</a> de HTML).</td> + </tr> + <tr> + <td>{{ Cssxref(":last-child") }}</td> + <td>Selecciona el último elemento de entre sus elementos hermanos.</td> + </tr> + <tr> + <td>{{ Cssxref(":last-of-type") }}</td> + <td>Selecciona el último de entre los elementos hermanos de un tipo determinado.</td> + </tr> + <tr> + <td>{{ Cssxref(":left") }}</td> + <td>En <a href="/en-US/docs/Web/CSS/CSS_Pages">Paged Media</a> selecciona las páginas de la izquierda.</td> + </tr> + <tr> + <td>{{ Cssxref(":link")}}</td> + <td>Selecciona los enlaces no visitados.</td> + </tr> + <tr> + <td>{{ Cssxref(":local-link")}}</td> + <td>Selecciona los enlaces que dirigen a páginas que se encuentran en la misma página web que el documento activo.</td> + </tr> + <tr> + <td>{{ Cssxref(":is", ":is()")}}</td> + <td>Selecciona cualquiera de los selectores de la lista de selección que se pase como valor de este selector.</td> + </tr> + <tr> + <td>{{ Cssxref(":not") }}</td> + <td>Selecciona elementos que otros selectores no han seleccionado antes y que se han pasado como valor de este selector.</td> + </tr> + <tr> + <td>{{ Cssxref(":nth-child") }}</td> + <td>Selecciona elementos de entre una lista de elementos hermanos. Los elementos hermanos están relacionados por una fórmula del tipo <var>an + b</var> (por ejemplo, 2<var>n</var> + 1 seleccionaría los elementos 1, 3, 5, 7, etc., es decir, todos los impares).</td> + </tr> + <tr> + <td>{{ Cssxref(":nth-of-type") }}</td> + <td>Selecciona elementos de entre una lista de elementos hermanos de un tipo determinado (por ejemplo, todos los elementos <code><p></code>). Los elementos hermanos están relacionados por una fórmula del tipo <var>an + b</var> (por ejemplo, 2<var>n</var> + 1 relacionaría en la secuencia ese tipo de elementos, los números 1, 3, 5, 7, etc., es decir, todos los impares).</td> + </tr> + <tr> + <td>{{ Cssxref(":nth-last-child") }}</td> + <td>Selecciona elementos de entre una lista de elementos hermanos, contando hacia atrás desde el final. Los elementos hermanos están relacionados por una fórmula del tipo <var>an+b</var> (por ejemplo, 2<var>n<var> <em>+ 1 r</em>elacionaría en la secuencia el último de los elementos de este tipo con el que se encuentra dos por delante, y así sucesivamente. Todos los impares, contando desde el final).</var></var></td> + </tr> + <tr> + <td>{{ Cssxref(":nth-last-of-type") }}</td> + <td>Selecciona los elementos de entre una lista de elementos hermanos que son de un tipo determinado (por ejemplo, elementos <code><p></code>), contando hacia atrás desde el final. Los elementos hermanos están relacionados por una fórmula del tipo <var>an+b</var> (por ejemplo, 2<var>n</var> + 1 relacionaría en la secuencia el último de los elementos de ese tipo con el que se encuentra dos por delante, y así sucesivamente. Todos los impares, contando desde el final).</td> + </tr> + <tr> + <td>{{ Cssxref(":only-child") }}</td> + <td>Selecciona un elemento que no tiene elementos hermanos.</td> + </tr> + <tr> + <td>{{ Cssxref(":only-of-type") }}</td> + <td>Selecciona un elemento que es el único de su tipo entre sus elementos hermanos.</td> + </tr> + <tr> + <td>{{ Cssxref(":optional") }}</td> + <td>Selecciona los elementos de formulario que son innecesarios.</td> + </tr> + <tr> + <td>{{ Cssxref(":out-of-range") }}</td> + <td>Selecciona un elemento cuyo valor está fuera de rango.</td> + </tr> + <tr> + <td>{{ Cssxref(":past") }}</td> + <td>Selecciona los elementos que se encuentran antes del elemento activo.</td> + </tr> + <tr> + <td>{{ Cssxref(":placeholder-shown") }}</td> + <td>Selecciona el elemento de entrada que muestra texto de marcador de posición.</td> + </tr> + <tr> + <td>{{ Cssxref(":playing") }}</td> + <td>Selecciona un elemento que representa un audio, un vídeo o un recurso similar que se puede «reproducir» o «pausar», cuando el elemento está «en reproducción».</td> + </tr> + <tr> + <td>{{ Cssxref(":paused") }}</td> + <td>Selecciona un elemento que representa un audio, un vídeo o un recurso similar que se puede “«reproducir» o «pausar» cuando el elemento está «pausado».</td> + </tr> + <tr> + <td>{{ Cssxref(":read-only") }}</td> + <td>Selecciona los elementos que el usuario no puede modificar.</td> + </tr> + <tr> + <td>{{ Cssxref(":read-write") }}</td> + <td>Selecciona los elementos que el usuario puede modificar.</td> + </tr> + <tr> + <td>{{ Cssxref(":required") }}</td> + <td>Selecciona los elementos de formulario que son necesarios.</td> + </tr> + <tr> + <td>{{ Cssxref(":right") }}</td> + <td>En <a href="/en-US/docs/Web/CSS/CSS_Pages">Paged Media</a> selecciona las páginas de la derecha.</td> + </tr> + <tr> + <td>{{ Cssxref(":root") }}</td> + <td>Selecciona un elemento que es la raíz del documento.</td> + </tr> + <tr> + <td>{{ Cssxref(":scope") }}</td> + <td>Selecciona cualquier elemento de ámbito.</td> + </tr> + <tr> + <td>{{ Cssxref(":valid") }}</td> + <td>Selecciona un elemento como <code><input></code>, en un estado válido.</td> + </tr> + <tr> + <td>{{ Cssxref(":target") }}</td> + <td>Selecciona el elemento al que apunta la URL activa (es decir, cuyo ID coincide con el <a href="https://en.wikipedia.org/wiki/Fragment_identifier">identificador de fragmento de la URL</a> activo).</td> + </tr> + <tr> + <td>{{ Cssxref(":visited") }}</td> + <td>Selecciona los enlaces visitados.</td> + </tr> + </tbody> +</table> + +<h3 id="Pseudoelementos">Pseudoelementos</h3> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{ Cssxref("::after") }}</td> + <td>Selecciona el elemento al que se puede aplicar estilo que aparece a continuación del contenido del elemento que lo origina.</td> + </tr> + <tr> + <td>{{ Cssxref("::before") }}</td> + <td>Selecciona el elemento al que se puede aplicar estilo que aparece antes del contenido del elemento que lo origina.</td> + </tr> + <tr> + <td>{{ Cssxref("::first-letter") }}</td> + <td>Selecciona la primera letra del elemento.</td> + </tr> + <tr> + <td>{{ Cssxref("::first-line") }}</td> + <td>Selecciona la primera línea del elemento de contenido.</td> + </tr> + <tr> + <td>{{ Cssxref("::grammar-error") }}</td> + <td>Selecciona una parte del documento que contiene un error de gramática indicado por el navegador.</td> + </tr> + <tr> + <td>{{ Cssxref("::selection") }}</td> + <td>Selecciona la parte del documento que ha sido seleccionada.</td> + </tr> + <tr> + <td>{{ Cssxref("::spelling-error") }}</td> + <td>Selecciona una parte del documento que contiene un error de ortografía indicado por el navegador.</td> + </tr> + </tbody> +</table> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks/Selectors/Combinators", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">La cascada y la herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Operadores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de caja</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Elementos de imagen, de media y de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/selectores_css/selectores_de_atributos/index.html b/files/es/learn/css/building_blocks/selectores_css/selectores_de_atributos/index.html new file mode 100644 index 0000000000..057c38c18d --- /dev/null +++ b/files/es/learn/css/building_blocks/selectores_css/selectores_de_atributos/index.html @@ -0,0 +1,154 @@ +--- +title: Selectores de atributo +slug: Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_atributos +translation_of: Learn/CSS/Building_blocks/Selectors/Attribute_selectors +--- +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks")}}</p> + +<p>Como ya explicamos en los artículos de HTML, los elementos pueden tener atributos que proporcionan un nivel de detalle mayor sobre el elemento que delimitan. En el CSS puedes utilizar selectores de atributo para seleccionar elementos definidos con unos atributos determinados. En este artículo veremos cómo utilizar estos selectores tan útiles.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, HTML básico (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a identificar y utilizar selectores de atributo.</td> + </tr> + </tbody> +</table> + +<h2 id="Selectores_de_presencia_y_valor">Selectores de presencia y valor</h2> + +<p>Estos selectores permiten seleccionar un elemento solo a partir de la presencia de un atributo (por ejemplo <code>href</code>) o a partir de varias coincidencias diferentes con respecto al valor del atributo.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Ejemplo</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>[<em>attr</em>]</code></td> + <td><code>a[title]</code></td> + <td>Relaciona elementos con un mismo nombre de atributo, <em>attr</em> (el valor que se indica entre corchetes).</td> + </tr> + <tr> + <td><code>[<em>attr</em>=<em>value</em>]</code></td> + <td><code>a[href="https://example.com"]</code></td> + <td>Relaciona elementos con un mismo nombre de atributo, <em>attr</em>, cuyo valor es exactamente el mismo, <em>value</em> (la cadena de caracteres que se indica entre corchetes).</td> + </tr> + <tr> + <td><code>[<em>attr</em>~=<em>value</em>]</code></td> + <td><code>p[class~="special"]</code></td> + <td> + <p>Relaciona los elementos con un mismo nombre de atributo, <em>attr</em>, cuyo valor es exactamente <em>value</em>, o los elementos con un mismo atributo <em>attr</em> que contiene uno o más valores de los cuales, al menos uno, coincide con <em>value</em>.</p> + + <p>Ten en cuenta que en una lista que incluya más de un valor, los distintos valores se separan con un espacio.</p> + </td> + </tr> + <tr> + <td><code>[<em>attr</em>|=<em>value</em>]</code></td> + <td><code>div[lang|="zh"]</code></td> + <td>Relaciona los elementos con un mismo nombre de atributo, <em>attr</em>, cuyo valor puede ser exactamente <em>value</em> o puede comenzar con <em>value</em> seguido inmediatamente por un guion.</td> + </tr> + </tbody> +</table> + +<p>En el ejemplo siguiente puedes observar cómo se utilizan estos selectores.</p> + +<ul> + <li>Mediante el uso de <code>li[class]</code> podemos relacionar cualquier selector con un atributo de clase. Los relaciona todos menos el primer elemento de la lista.</li> + <li><code>li[class="a"]</code> relaciona un selector con una clase de <code>a</code>, pero no un selector con una clase de <code>a</code> con otra clase separada por un espacio como parte del valor. Selecciona el segundo elemento de la lista.</li> + <li><code>li[class~="a"]</code> coincidirá con una clase <code>a</code> pero también con un valor que contenga la clase de <code>a</code> como parte de una lista de elementos separados por un espacio. Selecciona el segundo y el tercer elemento de la lista.</li> +</ul> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/attribute.html", '100%', 800)}}</p> + +<h2 id="Selectores_coincidentes_con_subcadenas">Selectores coincidentes con subcadenas</h2> + +<p>Estos selectores permiten un tipo más avanzado de relación entre las subcadenas de caracteres que constituyen el valor del atributo. Por ejemplo, si tienes las clases <code>box-warning</code> y <code>box-error</code> y quieres encontrar todos los elementos que empiezan con la cadena de caracteres “box-”, puedes seleccionarlas ambas con <code>[class^="box-"]</code>.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Selector</th> + <th scope="col">Ejemplo</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>[<em>attr</em>^=<em>value</em>]</code></td> + <td><code>li[class^="box-"]</code></td> + <td>Relaciona elementos con un mismo nombre de atributo, <em>attr</em>, cuyo valor empieza exactamente con la subcadena de caracteres <em>value</em>.</td> + </tr> + <tr> + <td><code>[<em>attr</em>$=<em>value</em>]</code></td> + <td><code>li[class$="-box"]</code></td> + <td>Relaciona elementos con un mismo nombre de atributo, <em>attr</em>, cuyo valor termina exactamente con la subcadena de caracteres <em>value</em>.</td> + </tr> + <tr> + <td><code>[<em>attr</em>*=<em> </em>]</code></td> + <td><code>li[class*="box"]</code></td> + <td>Relaciona elementos con un mismo nombre de atributo, <em>attr</em>, cuyo valor incluye al menos una ocurrencia de la subcadena <em>value</em> en algún punto de la cadena.</td> + </tr> + </tbody> +</table> + +<p>El ejemplo siguiente muestra cómo se usan estos selectores:</p> + +<ul> + <li><code>li[class^="a"]</code> relaciona cualquier valor de atributo que empieza con <code>a</code>; luego, relaciona los dos primeros elementos de la lista se verán iguales.</li> + <li><code>li[class$="a"]</code> relaciona cualquier valor de atributo que termina con <code>a</code>; luego, relaciona el primer y el tercer elemento de la lista.</li> + <li><code>li[class*="a"]</code> relaciona cualquier valor de atributo que contiene <code>a</code> en cualquier posición; luego, relaciona todos los elementos de la lista.</li> +</ul> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/attribute-substring.html", '100%', 800)}}</p> + +<h2 id="Mayúsculas_y_minúsculas">Mayúsculas y minúsculas</h2> + +<p>Si quieres relacionar los valores de atributo tanto si están escritos en mayúsculas como en minúsculas, puedes utilizar el valor <code>i</code> antes del paréntesis de cierre. Este indicador informa al navegador de que debe relacionar todos los caracteres ASCII independientemente de si las letras son mayúsculas o minúsculas. Sin este indicador, los valores se relacionarán según las directrices del lenguaje del documento con respecto a la distinción entre mayúsculas y minúsculas; en el caso del HTML, se distinguirá entre mayúsculas y minúsculas.</p> + +<p>En el ejemplo siguiente, el primer selector relaciona valores que empiezan con <code>a</code>; luego, solo coincide el primer elemento de la lista porque los otros dos comienzan con una A mayúscula. El segundo selector utiliza el indicador de no distinción entre mayúsculas y minúsculas, así que relaciona todos los elementos de la lista.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/attribute-case.html", '100%', 800)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Recientemente se ha creado un valor <code>s</code>, que obliga a establecer la distinción de mayúsculas y minúsculas en contextos en que no se suele establecer esta distinción. Sin embargo, pocos navegadores lo utilizan y no resulta demasiado útil en un contexto HTML.</p> +</div> + +<h2 id="Próximos_pasos">Próximos pasos</h2> + +<p>Ahora que hemos terminado con los selectores de atributo, puedes avanzar al artículo siguiente y leer acerca de los <a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">selectores de pseudoclases y pseudoelementos</a>.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors", "Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">La cascada y la herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Operadores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de caja</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/selectores_css/selectores_de_tipo_clase_e_id/index.html b/files/es/learn/css/building_blocks/selectores_css/selectores_de_tipo_clase_e_id/index.html new file mode 100644 index 0000000000..01b3963f8a --- /dev/null +++ b/files/es/learn/css/building_blocks/selectores_css/selectores_de_tipo_clase_e_id/index.html @@ -0,0 +1,117 @@ +--- +title: 'Selectores de tipo, clase e ID' +slug: Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_tipo_clase_e_ID +translation_of: Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors +--- +<p>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks")}}</p> + +<p>En este artículo vamos a echar un vistazo a los selectores más simples de que dispones y que seguramente serán los que utilices con mayor frecuencia.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, HTML básico (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Conocer los diferentes selectores CSS que podemos utilizar para aplicar CSS a un documento.</td> + </tr> + </tbody> +</table> + +<h2 id="Tipos_de_selectores">Tipos de selectores</h2> + +<p>Un <strong>selector de tipo</strong> también recibe el nombre de <em>selector de nombre de etiqueta</em> o <em>selector de elemento</em> porque selecciona un elemento/etiqueta HTML del documento. En el ejemplo siguiente hemos utilizado los selectores span, em y strong. Se aplica estilo a todas las instancias de los elementos <code><span></code>, <code><em></code> y <code><strong></code>.</p> + +<p><strong>Trata de añadir una regla CSS que seleccione el elemento <code><h1></code> y cambie su color para que se vea azul.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/type.html", '100%', 1100)}}</p> + +<h2 id="El_selector_universal">El selector universal</h2> + +<p>El selector universal se indica con un asterisco (<code>*</code>) y selecciona todos los elementos del documento (o del elemento padre si está encadenado con otro elemento y un operador de combinación descendente, por ejemplo). En el ejemplo siguiente hemos utilizado el selector universal para eliminar los márgenes en todos los elementos. Esto significa que en lugar de la opción predeterminada de aplicación de estilos del navegador, que muestra los títulos de encabezado y los párrafos separados por un margen de respeto, todo se mostrará pegado y no resultará tan fácil distinguir los diversos párrafos.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/universal.html", '100%', 750)}}</p> + +<p>Es posible observar este tipo de comportamiento en las «hojas de estilo de puesta a cero» (o «hojas de estilo <em>reset</em>»), que anulan el formato del navegador. Fueron muy populares en un momento dado; sin embargo, excluir todo el estilo significa que luego tienes que ponerlo todo de nuevo. Por este motivo tendemos a utilizar el selector universal con mucho cuidado, y para situaciones muy específicas como la que se describe a continuación.</p> + +<h3 id="Uso_del_selector_universal_para_facilitar_la_legibilidad_de_tus_selectores">Uso del selector universal para facilitar la legibilidad de tus selectores</h3> + +<p>Uno de los usos del selector universal es facilitar la legibilidad de los selectores y clarificar sus funciones. Por ejemplo, si quiero seleccionar el primer elemento hijo de cualquier elemento <code><article></code> y poner ese elemento, cualquiera que sea, en negrita, puedo utilizar el selector {{cssxref(":first-child")}}, que veremos con mayor detalle más adelante en el artículo de <a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Pseudo-clases_y_pseudo-elementos">pseudoclases y pseudoelementos</a>, como selector descendente junto con el selector de elemento <code><article></code>: </p> + +<pre class="brush: css notranslate">article :first-child { + +}</pre> + +<p>Sin embargo, esto podría confundirse con <code>article:first-child</code>, que selecciona cualquier elemento <code><article></code> que sea el primer elemento hijo de otro elemento.</p> + +<p>Para evitar esta confusión podemos añadir al selector <code>:first-child</code> el selector universal. De este modo la función del selector resulta obvia: seleccionará <em>cualquier</em> elemento que entre en la jerarquía de primer hijo de un elemento <code><article></code>:</p> + +<pre class="brush: css notranslate">article *:first-child { + +} </pre> + +<h2 id="Selectores_de_clase">Selectores de clase</h2> + +<p>El selector de clase comienza con un punto (<code>.</code>) y selecciona todo elemento del documento que esté afectado por esa clase. En el ejemplo siguiente hemos creado una clase llamada <code>.highlight</code> y la hemos aplicado en varios lugares del documento. Todos los elementos a los que se aplique esta clase se resaltarán en amarillo.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/class.html", '100%', 750)}}</p> + +<h3 id="Delimitación_de_clases_en_elementos_particulares">Delimitación de clases en elementos particulares</h3> + +<p>Puedes crear un selector que seleccionará los elementos concretos que estén afectados por esa clase. En el ejemplo siguiente vamos a introducir un resaltado en un elemento <code><span></code> con una clase <code>highlight</code> del de los títulos <code><h1></code> con clase <code>highlight</code>. Para ello hay que anexar esa clase al selector de tipo correspondiente al elemento que queremos delimitar, sin dejar entre ellos ningún espacio.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/class-type.html", '100%', 750)}}</p> + +<p>Este enfoque hace el elemento CSS menos reutilizable porque la clase solo se aplicará a ese elemento en particular y tendrás que agregar otro selector en caso que quieras que las normas también se apliquen a otros elementos.</p> + +<h3 id="Delimitar_un_elemento_afectado_por_más_de_una_clase">Delimitar un elemento afectado por más de una clase</h3> + +<p>Puedes aplicar más de una clase a un elemento y delimitarlos de forma individual o seleccionar el elemento cuando todas las clases están presentes en el selector. Puede ser útil cuando se trabaja con componentes que se pueden combinar de maneras diferentes en tu página web.</p> + +<p>En el ejemplo siguiente hay un elemento <code><div></code> que contiene una nota. El borde gris se aplica cuando la caja tiene una clase <code>notebox</code>. Si además tiene una clase <code>warning</code> o <code>danger</code>, la propiedad {{cssxref("border-color")}} cambia.</p> + +<p>Para decirle al navegador que solo queremos seleccionar el elemento si incluye todas estas clases, las encadenamos juntas sin ningún espacio entre ellas.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/class-many.html", '100%', 900)}}</p> + +<h2 id="Selectores_de_ID">Selectores de ID</h2> + +<p>Un selector de ID comienza con un carácter <code>#</code> en lugar de un punto, pero se utiliza básicamente de la misma manera que un selector de clase. Sin embargo, un ID se puede utilizar una sola vez en cada documento, y a cada elemento solo se le puede aplicar un único <code>id</code>. Puede seleccionar un elemento que tenga propiedad <code>id</code> y ese ID puede ir precedido de un selector de tipo que seleccionará el elemento solo si el elemento y el ID coinciden. En el ejemplo siguiente puedes ver todos estos usos:</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/selectors/id.html", '100%', 750)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Como aprendimos en el artículo sobre la especificidad, un ID tiene una especificidad muy alta y anula la mayoría de los otros selectores. Esto puede dificultar su uso. En la mayoría de los casos es preferible añadir una clase al elemento en lugar de utilizar un ID. Sin embargo, si el ID es la única manera de seleccionar el elemento (tal vez porque no tengas acceso al marcado y, por lo tanto, no lo puedes editar) no hay ningún problema en utilizarlo.</p> +</div> + +<h2 id="En_el_próximo_artículo">En el próximo artículo</h2> + +<p>Seguiremos con la descripción de los selectores examinando los <a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Selectores_de_atributos">selectores de atributo</a>.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Selectors", "Learn/CSS/Building_blocks/Selectors/Attribute_selectors", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">La cascada y la herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Operadores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de caja</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/building_blocks/styling_tables/index.html b/files/es/learn/css/building_blocks/styling_tables/index.html new file mode 100644 index 0000000000..283df180e4 --- /dev/null +++ b/files/es/learn/css/building_blocks/styling_tables/index.html @@ -0,0 +1,282 @@ +--- +title: Estilizando tablas +slug: Learn/CSS/Building_blocks/Styling_tables +translation_of: Learn/CSS/Building_blocks/Styling_tables +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/Styling_boxes/Borders", "Learn/CSS/Styling_boxes/Advanced_box_effects", "Learn/CSS/Styling_boxes")}}</div> + +<p class="summary">Aplicar estilos a una tabla HTML no es el trabajo más interesante del mundo, pero a veces hay que hacerlo. Este artículo proporciona una guía para hacer que las tablas HTML presenten un aspecto agradable, para ello usaremos algunas de las características específicas para tablas que hemos destacado en artículos anteriores.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y <a href="/es/docs/Learn/HTML/Tablas">tablas HTML</a>, y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a>.)</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a aplicar estilo a tablas HTML de una forma efectiva.</td> + </tr> + </tbody> +</table> + +<h2 id="Una_tabla_HTML_típica">Una tabla HTML típica</h2> + +<p>Comencemos por echar un vistazo a una tabla HTML típica. Bueno, decimos típica porque la mayoría de los ejemplos de tablas HTML son sobre zapatos, el tiempo o empleados; y hemos decidido hacer las cosas más interesantes creando una tabla sobre grupos de música punk famosos del Reino Unido. El código es el siguiente:</p> + +<pre class="brush: html notranslate"><table summary="Los grupos de música punk más famosos del Reino Unido"> + <caption>Un resumen de los grupos de música punk más famosos del Reino Unido</caption> + <thead> + <tr> + <th scope="col">Grupo</th> + <th scope="col">Año de formación</th> + <th scope="col">Número de álbumes</th> + <th scope="col">Canción más conocida</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">Buzzcocks</th> + <td>1976</td> + <td>9</td> + <td>Ever fallen in love (with someone you shouldn't've)</td> + </tr> + <tr> + <th scope="row">The Clash</th> + <td>1976</td> + <td>6</td> + <td>London Calling</td> + </tr> + + ... se han eliminado algunas filas por abreviar + + <tr> + <th scope="row">The Stranglers</th> + <td>1974</td> + <td>17</td> + <td>No More Heroes</td> + </tr> + </tbody> + <tfoot> + <tr> + <th scope="row" colspan="2">Número total de álbumes</th> + <td colspan="2">77</td> + </tr> + </tfoot> +</table></pre> + +<p>La tabla está bien creada, puede aplicársele estilo fácilmente y presenta características de accesibilidad gracias a propiedades como {{htmlattrxref("scope","th")}}, {{htmlelement("caption")}}, {{htmlattrxref("summary","table")}}, {{htmlelement("thead")}}, {{htmlelement("tbody")}}, etc. Por desgracia, no presenta un aspecto agradable cuando se muestra en pantalla (puedes ver el ejemplo en <a href="http://mdn.github.io/learning-area/css/styling-boxes/styling-tables/punk-bands-unstyled.html">punk-bands-unstyled.html</a>):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13064/table-unstyled.png" style="display: block; margin: 0 auto;"></p> + +<p>Tal y como está, es aburrida y difícil de leer. Necesitamos usar algo de CSS para arreglar esto.</p> + +<h2 id="Aprendizaje_activo_Aplicar_estilo_a_nuestra_tabla">Aprendizaje activo: Aplicar estilo a nuestra tabla</h2> + +<p>En esta sección de aprendizaje activo vamos a aplica estilo a nuestra tabla juntos.</p> + +<ol> + <li>Para comenzar, crea una copia local del <a href="https://github.com/mdn/learning-area/blob/master/css/styling-boxes/styling-tables/punk-bands-unstyled.html" title="código de ejemplo">código de ejemplo</a>, descarga las dos imágenes (<a href="https://github.com/mdn/learning-area/blob/master/css/styling-boxes/styling-tables/noise.png">noise</a> y <a href="https://github.com/mdn/learning-area/blob/master/css/styling-boxes/styling-tables/leopardskin.jpg">leopardskin</a>), y pon los tres archivos en alguna carpeta de tu ordenador.</li> + <li>Ahora crea un archivo nuevo llamado <code>style.css</code> y guárdalo con el resto de archivos, en la misma carpeta.</li> + <li>Enlaza el CSS al HTML copiando la línea siguiente en {{htmlelement("head")}}: + <pre class="brush: html notranslate"><link href="style.css" rel="stylesheet" type="text/css"></pre> + </li> +</ol> + +<h3 id="Espaciado_y_distribución">Espaciado y distribución</h3> + +<p>Lo primero que hay que hacer es solucionar los aspectos de espaciado/distribución; ¡el estilo por defecto de la tabla es tan apretado! Para ello, añadimos el CSS siguiente al archivo <code>style.css</code>:</p> + +<pre class="brush: css notranslate">/* spacing */ + +table { + table-layout: fixed; + width: 100%; + border-collapse: collapse; + border: 3px solid purple; +} + +thead th:nth-child(1) { + width: 30%; +} + +thead th:nth-child(2) { + width: 20%; +} + +thead th:nth-child(3) { + width: 15%; +} + +thead th:nth-child(4) { + width: 35%; +} + +th, td { + padding: 20px; +}</pre> + +<p>Las partes más importantes que destacamos son:</p> + +<ul> + <li>En general es una buena idea establecer un valor {{cssxref("table-layout")}} en <code>fixed</code> para la tabla porque le proporciona un comportamiento predeterminado predecible. Normalmente se tiende a dar un tamaño de columna según la cantidad de contenido que haya en estas, lo que suele producir resultados extraños. Con <code>table-layout: fixed</code>, puedes dar a las columnas un tamaño de acuerdo con el ancho de sus celdas de encabezado y a continuación gestionar los contenidos de la forma que te parezca más adecuada. Por esto hemos seleccionado los cuatro encabezados con el selector <code>thead th:nth-child(<em>n</em>)</code> ({{cssxref(":nth-child")}}) (Seleccionar el descendiente enésimo que es un elemento {{htmlelement("th")}} en una secuencia dentro del elemento {{htmlelement("thead")}}) y, dados estos, asignar los porcentajes de anchura. Chris Coyier expone esta técnica con más detalle en <a href="https://css-tricks.com/fixing-tables-long-strings/">Fixed Table Layouts</a>.<br> + <br> + Hemos emparejado esto con un {{cssxref("width")}} del 100%, que significa que la tabla llenará cualquier contenedor en la que se ubique, y presentará unas buenas características adaptativas (aunque podría requerir algo más de trabajo para que se vea bien en pantallas de anchuras estrechas).</li> + <li>Un valor {{cssxref("border-collapse")}} de <code>collapse</code> es una buena práctica estándar para cualquier tarea de aplicación de estilo a tablas. Por defecto, cuando estableces los bordes de los elementos de la tabla, quedará un espacio entre ellos, como se muestra en la imagen siguiente. <img alt="" src="https://mdn.mozillademos.org/files/13068/no-border-collapse.png" style="display: block; margin: 0 auto;"> Esto no presenta un aspecto agradable (aunque puede ser el aspecto que buscas, ¡quién sabe!). Si estableces <code>border-collapse: collapse;</code>, los bordes se reducen a uno, y así presenta un aspecto mucho más agradable: <img alt="" src="https://mdn.mozillademos.org/files/13066/border-collapse.png" style="display: block; margin: 0 auto;"></li> + <li>Hemos puesto un borde ({{cssxref("border")}}) alrededor de la tabla, que es necesario, porque vamos a poner bordes en la cabecera de la tabla y después en el pie; queda raro e inconexo si no pones ningún borde a la tabla que la delimite del resto de los elementos del exterior y quedan huecos.</li> + <li>Hemos puesto área de relleno ({{cssxref("padding")}}) en los elementos {{htmlelement("th")}} y {{htmlelement("td")}}; esto da a los datos espacio para que respiren y mejora la legibilidad de la tabla.</li> +</ul> + +<p>En este punto, nuestra tabla ya presenta un aspecto mucho más agradable:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13070/table-with-spacing.png" style="display: block; margin: 0 auto;"></p> + +<h3 id="Un_poco_de_tipografía">Un poco de tipografía</h3> + +<p>Ahora arreglaremos un poco nuestro texto.</p> + +<p>En primer lugar, hemos ido a <a href="https://www.google.com/fonts">Google Fonts</a> y hemos encontrado un tipo de letra adecuado para una tabla sobre bandas punk. Puedes buscar uno diferente si lo deseas; solo tienes que reemplazar el elemento {{htmlelement ("link")}} que te hemos proporcionado y la declaración {{cssxref ("font-family")}} personalizada por las que te proporcione Google Fonts.</p> + +<p>Primero, añade el elemento {{htmlelement ("link")}} siguiente a tu encabezado HTML, justo encima del elemento <code><link></code>:</p> + +<pre class="brush: html notranslate"><link href='https://fonts.googleapis.com/css?family=Rock+Salt' rel='stylesheet' type='text/css'></pre> + +<p>Ahora añade el CSS siguiente a tu archivo <code>style.css</code>, debajo de la línea añadida anterior:</p> + +<pre class="brush: css notranslate">/* typography */ + +html { + font-family: 'helvetica neue', helvetica, arial, sans-serif; +} + +thead th, tfoot th { + font-family: 'Rock Salt', cursive; +} + +th { + letter-spacing: 2px; +} + +td { + letter-spacing: 1px; +} + +tbody td { + text-align: center; +} + +tfoot th { + text-align: right; +}</pre> + +<p>En realidad aquí no hay nada que sea específico para las tablas. En general, modificamos el estilo de la letra para facilitar la lectura:</p> + +<ul> + <li>Hemos establecido una lista global de fuentes Sans Serif. Esto es puramente una elección de estilo. También hemos configurado nuestro tipo de letra personalizada en los encabezados que hay dentro de los elementos {{htmlelement ("thead")}} y {{htmlelement ("tfoot")}} para dotarlos de una encantadora sucia estética punk.</li> + <li>Hemos establecido algunos {{cssxref("letter-spacing")}} en los encabezados y las celdas, porque creemos que ayuda a la legibilidad. De nuevo es, sobre todo, una elección estilística.</li> + <li>Hemos establecido en el elemento {{htmlelement("tbody")}} el centrado del texto en las celdas de la tabla para que se queden alineadas con los encabezados. Por defecto, en {{cssxref("text-align")}} se asigna un valor <code>left</code> para las celdas, y un valor <code>center</code> para los encabezados, pero a menudo queda mejor disponer las alineaciones de texto establecidas de la misma manera en ambos. El peso predeterminado para la negrita en los tipos de letra de los encabezados basta para diferenciar su aspecto.</li> + <li>Hemos establecido el texto del encabezado alineado a la derecha en el elemento {{htmlelement ("tfoot")}} para que visualmente quede mejor asociado con sus datos.</li> +</ul> + +<p>El resultado se ve un poco más limpio:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13072/table-with-typography.png" style="display: block; margin: 0 auto;"></p> + +<h3 id="Gráficos_y_colores">Gráficos y colores</h3> + +<p>Ahora, ¡a por los gráficos y los colores! Puesto que la tabla rezuma contenido y actitud punk, vamos a darle un brillante estilo imponente que le pegue. No te preocupes, no tienes que hacer tus tablas tan extremadas: puedes optar por algo más sutil y de buen gusto.</p> + +<p>Empieza añadiendo el CSS siguiente a tu archivo <code>style.css</code>, de nuevo al final:</p> + +<pre class="brush: css notranslate">thead, tfoot { + background: url(leopardskin.jpg); + color: white; + text-shadow: 1px 1px 1px black; +} + +thead th, tfoot th, tfoot td { + background: linear-gradient(to bottom, rgba(0,0,0,0.1), rgba(0,0,0,0.5)); + border: 3px solid purple; +} +</pre> + +<p>Una vez más, aquí no hay nada específico para las tablas, pero vale la pena señalar algunas cosas.</p> + +<p>Hemos añadido una imagen de fondo ({{cssxref("background-image")}}) a los elementos {{htmlelement("thead")}} y {{htmlelement("tfoot")}}, y hemos cambiado el ({{cssxref("color")}}) de todo el texto del encabezado y el pie de página por el blanco (y le hemos dado una sombra, {{cssxref("text-shadow")}}) para que sea legible. Siempre debes asegurarte de que tu texto contraste bien con el fondo, para que sea legible.</p> + +<p>También hemos añadido un degradado lineal a los elementos {{htmlelement("th")}} y {{htmlelement("td")}} del encabezado y el pie de página para obtener un poco de textura, y también hemos dado a esos elementos un borde púrpura brillante. Es útil tener múltiples elementos anidados disponibles para que puedas superponer estilos. Sí, podríamos haber colocado tanto la imagen de fondo como el gradiente lineal en los elementos {{htmlelement ("thead")}} y {{htmlelement ("tfoot")}} utilizando múltiples imágenes de fondo, pero decidimos hacerlo por separado por los navegadores más antiguos que no admiten múltiples imágenes de fondo o gradientes lineales.</p> + +<h4 id="Rayas_de_cebra">Rayas de cebra</h4> + +<p>Queremos dedicar una sección independiente a mostrarte cómo implementar <strong>rayas de cebra</strong>, alternando filas de color que facilitan el análisis y la legibilidad de las diversas filas de datos de la tabla. Añade el CSS siguiente al final de tu archivo <code>style.css</code>:</p> + +<pre class="brush: css notranslate">tbody tr:nth-child(odd) { + background-color: #ff33cc; +} + +tbody tr:nth-child(even) { + background-color: #e495e4; +} + +tbody tr { + background-image: url(noise.png); +} + +table { + background-color: #ff33cc; +}</pre> + +<ul> + <li>Ya has visto el selector {{cssxref(":nth-child")}}, que se usa para seleccionar elementos hijo específicos. También se le puede dar una fórmula como parámetro, de modo que seleccione una secuencia de elementos. La fórmula <code>2n-1</code> seleccionaría todos los elementos hijo impares (1, 3, 5, etc.), y la fórmula <code>2n</code>, todos los elementos hijo pares (2, 4, 6, etc.) Nosotros hemos utilizado las palabras clave <code>odd</code> y <code>even</code> en nuestro código, que hacen exactamente lo mismo que las fórmulas mencionadas. En este caso, damos a las filas pares y a las impares (espeluznantes) colores diferentes.</li> + <li>También hemos añadido un mosaico de fondo repetitivo a todas las filas del cuerpo de la tabla, que es solo un poco de ruido (un <code>.png</code> semitransparente con un poco de distorsión visual) para proporcionar algo de textura.</li> + <li>Por último, le hemos dado a toda la tabla un color de fondo sólido para que los navegadores que no admiten el selector <code>:nth-child</code> todavía dispongan de un fondo para las filas del cuerpo de la tabla.</li> +</ul> + +<p>Esta explosión de colores da como resultado el aspecto siguiente:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13074/table-with-color.png" style="display: block; margin: 0 auto;"></p> + +<p>Esto puede quedar un poco exagerado y no ser de tu agrado, pero el punto que tratamos de explicar es que las tablas no tienen por qué ser aburridas ni académicas.</p> + +<h3 id="Aplicar_estilo_al_título">Aplicar estilo al título</h3> + +<p>Hay una última cosa que hacer con nuestra tabla: aplicar estilo al título. Para ello, añade al final de tu archivo <code>style.css</code> lo siguiente:</p> + +<pre class="brush: css notranslate">caption { + font-family: 'Rock Salt', cursive; + padding: 20px; + font-style: italic; + caption-side: bottom; + color: #666; + text-align: right; + letter-spacing: 1px; +}</pre> + +<p>Aquí no hay nada notable, excepto la propiedad {{cssxref ("caption-side")}}, a la que se le ha dado un valor <code>bottom</code>. Esto coloca el título en la parte inferior de la tabla, lo que junto con el resto de declaraciones nos proporciona este aspecto final (puedes verlo vivo en <a href="http://mdn.github.io/learning-area/css/styling-boxes/styling-tables/punk-bands-complete.html">punk-bands-complete.html</a>):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13076/table-with-caption.png" style="display: block; height: 357px; margin: 0px auto; width: 723px;"></p> + +<h2 id="Aprendizaje_activo_Aplica_estilo_a_tu_tabla">Aprendizaje activo: Aplica estilo a tu tabla</h2> + +<p>En este punto, nos gustaría que tomes nuestro ejemplo de tabla HTML (¡o que uses uno propio!) y que le apliques estilo para obtener algo considerablemente mejor diseñado y menos llamativo que nuestra tabla.</p> + +<h2 id="Consejos_rápidos_para_el_diseño_de_tablas">Consejos rápidos para el diseño de tablas</h2> + +<p>Antes de seguir adelante, creemos que tendríamos que proporcionar una lista rápida de los puntos más útiles que acabamos de ilustrar:</p> + +<ul> + <li>Haz el marcado de la tabla lo más simple posible y mantén las cosas flexibles. Por ejemplo, con el uso de porcentajes, para que el diseño sea más adaptativo.</li> + <li>Usa {{cssxref("table-layout")}}<code>: fixed</code> para crear un diseño de tabla más predecible que te permita establecer con facilidad los anchos de columna configurando {{cssxref("width")}} en sus encabezados ({{htmlelement("th")}}).</li> + <li>Usa {{cssxref ("border-collapse")}}<code>: collapse</code> para que los bordes de los elementos de la tabla colapsen entre sí y proporcionen una apariencia más ordenada y más fácil de controlar.</li> + <li>Usa {{htmlelement ("thead")}}, {{htmlelement ("tbody")}} y {{htmlelement ("tfoot")}} para dividir la tabla en fragmentos lógicos y proporcionar lugares adicionales para aplicarle CSS, para superponer estilos entre sí con más facilidad, si es necesario.</li> + <li>Usa rayas de cebra en filas alternativas para facilitar la legibilidad.</li> + <li>Usa {{cssxref ("text-align")}} para alinear el texto en tus elementos {{htmlelement ("th")}} y {{htmlelement ("td")}}, para ordenar los elementos y facilitar su legibilidad.</li> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>Después de aplicar estilo a las tablas, necesitamos algo más en que ocupar nuestro tiempo. El artículo siguiente expone la depuración de documentos CSS, es decir, cómo resolver problemas como diseños de página que no presentan el aspecto que deberían, o propiedades que no se aplican cuando crees que deberían aplicarse. Esto incluye información sobre el uso de las herramientas DevTools del navegador para hallar soluciones a tus problemas.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Styling_boxes/Borders", "Learn/CSS/Styling_boxes/Advanced_box_effects", "Learn/CSS/Styling_boxes")}}</p> diff --git a/files/es/learn/css/building_blocks/valores_y_unidades_css/index.html b/files/es/learn/css/building_blocks/valores_y_unidades_css/index.html new file mode 100644 index 0000000000..4470746bc8 --- /dev/null +++ b/files/es/learn/css/building_blocks/valores_y_unidades_css/index.html @@ -0,0 +1,392 @@ +--- +title: Valores y unidades CSS +slug: Learn/CSS/Building_blocks/Valores_y_unidades_CSS +translation_of: Learn/CSS/Building_blocks/Values_and_units +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/CSS/Building_blocks/Overflowing_content", "Learn/CSS/Building_blocks/Sizing_items_in_CSS", "Learn/CSS/Building_blocks")}}</div> + +<p>Todas las propiedades que se utilizan en CSS tienen un valor o un conjunto de valores que esa propiedad admite, y echar un vistazo a cualquier página de propiedades en MDN te ayudará a comprender qué valores admite una propiedad en particular. En este artículo veremos algunos de los valores y unidades más comunes en uso.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, HTML básico (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos con el CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Conocer los diferentes tipos de valores y unidades que admiten las propiedades CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_un_valor_CSS">¿Qué es un valor CSS?</h2> + +<p>En las especificaciones CSS y en las páginas de propiedades de este proyecto MDN, podrás detectar los valores porque estarán escritos entre corchetes angulares, como <code><a href="/en-US/docs/Web/CSS/color_value"><color></a></code> o <code><a href="/en-US/docs/Web/CSS/length"><length></a></code>. Cuando veas que el valor <code><color></code> es válido para una propiedad en particular, significa que para esa propiedad puedes usar como valor cualquier color válido de entre los que se enumeran en la página de referencia de la propiedad <code><a href="/en-US/docs/Web/CSS/color_value"><color></a></code>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: También verás valores CSS denominados <em>tipos de datos</em>. Los términos son básicamente intercambiables: cuando veas algo en CSS denominado ‘tipo de datos’, en realidad es solo una forma elegante de decir ‘valor’.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Sí, hay una tendencia de denotar los valores CSS entre corchetes angulares, para diferenciarlos de las propiedades CSS (por ejemplo, la propiedad {{cssxref ("color")}} con respecto al tipo de dato <a href="/es/docs/Web/CSS/color_value"><color></a>). Aunque podría generarte confusión entre los tipos de datos CSS y los elementos HTML, porque ambos usan corchetes angulares, es poco probable porque se usan en contextos muy diferentes.</p> +</div> + +<p>En el ejemplo siguiente hemos establecido el color de nuestro encabezado con una palabra clave y el fondo con la función <code>rgb()</code>:</p> + +<pre class="brush: css notranslate"><code>h1 { + color: black; + background-color: rgb(197,93,161); +} </code> +</pre> + +<p>Un valor en CSS es una forma de definir una colección de subvalores admitidos. Esto significa que si ves <code><color></code> como válido, no necesitas preguntarte cuáles de los diferentes tipos de valor de color puedes usar: palabras clave, valores hexadecimales, funciones <code>rgb()</code>, etc. Puedes usar <em>cualquier</em> valor <code><color></code> disponible siempre que tu navegador lo admita. La página de MDN te dará información sobre lo que admite cada navegador para cada valor. Por ejemplo, puedes ver que en la sección de compatibilidad de navegadores de la página para <code><a href="/en-US/docs/Web/CSS/color_value"><color></a></code> se enumeran diferentes tipos de valores de color y los navegadores que los admiten.</p> + +<p>Echemos un vistazo a algunos de los tipos de valores y unidades con los que puedes encontrar con frecuencia, con ejemplos para que puedas probar diferentes valores posibles.</p> + +<h2 id="Números_longitudes_y_porcentajes">Números, longitudes y porcentajes</h2> + +<p>Al utilizar CSS te puedes encontrar con varios tipos de datos numéricos. Todos los siguientes están clasificados como tipos de datos numéricos:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Tipo de datos</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code><a href="/es/docs/Web/CSS/integer"><integer></a></code></td> + <td>Un <code><integer></code> es un número entero, como <code>1024</code> o <code>-55</code>.</td> + </tr> + <tr> + <td><code><a href="/es/docs/Web/CSS/number"><number></a></code></td> + <td>Un <code><number></code> representa un número decimal; puede tener o no un punto de separación decimal con un componente fraccionario, por ejemplo: <code>0,255</code>, <code>128</code> o <code>-1,2</code>.</td> + </tr> + <tr> + <td><code><dimension></code></td> + <td>Una <code><dimension></code> es un <code><number></code> con una unidad asociada, por ejemplo: <code>45deg</code> (grados), <code>5s</code> (segundos) o <code>10px</code> (píxeles). <code><dimension></code> es una categoría general que incluye los tipos <code><a href="/es/docs/Web/CSS/length"><length></a></code>, <code><a href="/es/docs/Web/CSS/angle"><angle></a></code>, <code><a href="/es/docs/Web/CSS/time"><time></a></code> y <code><a href="/es/docs/Web/CSS/resolución"><resolution></a></code><a href="/en-US/docs/Web/CSS/resolution">.</a></td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/CSS/percentage"><percentage></a></code></td> + <td>Un <code><percentage></code> representa una fracción de algún otro valor, por ejemplo, <code>50%</code>. Los valores de porcentaje siempre son relativos a otra cantidad, por ejemplo, la longitud de un elemento es relativa a la longitud de su elemento padre.</td> + </tr> + </tbody> +</table> + +<h3 id="Longitudes">Longitudes</h3> + +<p>El tipo numérico con el que te vas a encontrar con mayor frecuencia es <code><length></code>, por ejemplo, <code>10px</code> (píxeles) o <code>30em</code>. En CSS se utilizan dos longitudes diferentes: relativa y absoluta. Es importante conocer la diferencia para entender qué dimensiones van a tener las cosas.</p> + +<h4 id="Unidades_de_longitud_absoluta">Unidades de longitud absoluta</h4> + +<p>Todas las unidades siguientes son unidades de longitud <strong>absoluta</strong>: no son relativas a nada más y en general se considera que siempre tienen el mismo tamaño.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Unidad</th> + <th scope="col">Nombre</th> + <th scope="col">Equivale a</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>cm</code></td> + <td>Centímetros</td> + <td>1cm = 96px/2,54</td> + </tr> + <tr> + <td><code>mm</code></td> + <td>Milímetros</td> + <td>1mm = 1/10 de 1cm</td> + </tr> + <tr> + <td><code>Q</code></td> + <td>Cuartos de milímetros</td> + <td>1Q = 1/40 de 1cm</td> + </tr> + <tr> + <td><code>in</code></td> + <td>Pulgadas</td> + <td>1in = 2,54cm = 96px</td> + </tr> + <tr> + <td><code>pc</code></td> + <td>Picas</td> + <td>1pc = 1/16 de 1in</td> + </tr> + <tr> + <td><code>pt</code></td> + <td>Puntos</td> + <td>1pt = 1/72 de 1in</td> + </tr> + <tr> + <td><code>px</code></td> + <td>Píxeles</td> + <td>1px = 1/96 de 1in</td> + </tr> + </tbody> +</table> + +<p>La mayoría de estos valores son más útiles cuando se usan en una salida en formato impreso que en la salida de pantalla. Por ejemplo, normalmente no usamos <code>cm</code> (centímetros) en pantalla. El único valor que usarás de forma frecuente es <code>px</code> (píxeles).</p> + +<h4 id="Unidades_de_longitud_relativa">Unidades de longitud relativa</h4> + +<p>Las unidades de longitud relativa son relativas a algo más, por ejemplo, al tamaño de letra del elemento principal o al tamaño de la ventana gráfica. La ventaja de usar unidades relativas es que con una planificación cuidadosa puedes lograr que el tamaño del texto u otros elementos escalen en relación con todo lo demás en la página. En la tabla siguiente se enumeran algunas de las unidades más útiles para el desarrollo web.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Unidad</th> + <th scope="col">Relativa a</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>em</code></td> + <td>Tamaño de letra del elemento padre, en el caso de propiedades tipográficas como {{cssxref("font-size")}}, y tamaño de la fuente del propio elemento en el caso de otras propiedades, como {{cssxref("width")}}.</td> + </tr> + <tr> + <td><code>ex</code></td> + <td>Altura x de la fuente del elemento.</td> + </tr> + <tr> + <td><code>ch</code></td> + <td>La medida de avance (ancho) del glifo "0" de la letra del elemento.</td> + </tr> + <tr> + <td><code>rem</code></td> + <td>Tamaño de la letra del elemento raíz.</td> + </tr> + <tr> + <td><code>lh</code></td> + <td>Altura de la línea del elemento.</td> + </tr> + <tr> + <td><code>vw</code></td> + <td>1% del ancho de la ventana gráfica.</td> + </tr> + <tr> + <td><code>vh</code></td> + <td>1% de la altura de la ventana gráfica.</td> + </tr> + <tr> + <td><code>vmin</code></td> + <td>1% de la dimensión más pequeña de la ventana gráfica.</td> + </tr> + <tr> + <td><code>vmax</code></td> + <td>1% de la dimensión más grande de la ventana gráfica.</td> + </tr> + </tbody> +</table> + +<h4 id="Un_ejemplo_de_análisis">Un ejemplo de análisis</h4> + +<p>En el ejemplo siguiente puedes ver cómo se comportan algunas unidades de longitud relativa y absoluta. La primera caja tiene un ancho ({{cssxref ("width")}}) establecido en píxeles. Como unidad absoluta, este ancho será siempre el mismo aunque lo demás cambie.</p> + +<p>La segunda caja tiene un ancho establecido en unidades <code>vw</code> (ancho de ventana). Este valor es relativo al ancho de la ventana gráfica, por lo que 10vw es el 10 por ciento del ancho de la ventana gráfica. Si cambiases el ancho de la ventana de tu navegador, el tamaño de la caja cambiaría. Sin embargo, esto no te va a funcionar porque este ejemplo se ha incrustado en la página usando <code><a href="/en-US/docs/Web/HTML/Element/iframe"><iframe></a></code>. Para verlo en acción debes <a href="https://mdn.github.io/css-examples/learn/values-units/length.html">probar el ejemplo después de abrirlo en una pestaña independiente de tu navegador</a>.</p> + +<p>La tercera caja utiliza unidades <code>em</code>. Son unidades relativas al tamaño de la letra. Hemos establecido un tamaño de fuente de <code>1em</code> en el contenido {{htmlelement ("div")}}, que tiene una clase <code>.wrapper</code>. Si cambias este valor a <code>1.5em</code>, verás que el tamaño de letra de todos los elementos aumenta, pero solo se amplía el ancho en el último elemento, porque el ancho es relativo a ese tamaño de letra.</p> + +<p>Después de seguir las instrucciones anteriores, juega un poco más con los valores para ver qué obtienes.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/length.html", '100%', 820)}}</p> + +<h4 id="ems_y_rems">ems y rems</h4> + +<p><code>em</code> y <code>rem</code> son las dos longitudes relativas que es probable que encuentres con mayor frecuencia al cambiar el tamaño de cualquier cosa, de cajas a texto. Vale la pena entender cómo funcionan y las diferencias entre ellos, especialmente cuando comienzas a abordar temas más complejos como <a href="/es/docs/Learn/CSS/Styling_text">aplicar estilos a texto</a> o <a href="/es/docs/Learn/CSS/CSS_layout">compaginar con CSS</a>. El ejemplo siguiente te proporciona una muestra.</p> + +<p>El HTML es un conjunto de listas anidadas: hay tres listas en total y ambos ejemplos tienen el mismo HTML. La única diferencia es que el primero tiene una clase <em>ems</em> y el segundo una clase <em>rems</em>.</p> + +<p>Para empezar, configuramos un tamaño de letra de 16px en el elemento <code><html></code>.</p> + +<p><strong>En definitiva, la unidad <em>em</em> significa «el tamaño de letra de mi elemento padre»</strong>. Los elementos {{htmlelement ("li")}} dentro de un elemento {{htmlelement ("ul")}} con una clase de <code>ems</code> toman el tamaño con respecto a su elemento padre. Por lo tanto, en cada nivel de anidamiento sucesivo, el tamaño de letra aumenta progresivamente, porque en cada uno el tamaño de letra está establecido en <code>1.3em</code> (1,3 veces el tamaño de letra de su elemento padre).</p> + +<p><strong>En definitiva, la unidad <em>rem</em> significa «el tamaño de letra del elemento raíz»</strong>. (‘rem’ viene de «root em»). Los elementos {{htmlelement ("li")}} dentro de un elemento {{htmlelement ("ul")}} con una clase de <code>rems</code> toman su tamaño del elemento raíz (<code><html></code>). Esto significa que el tamaño de letra no aumenta en cada nivel sucesivo de anidamiento.</p> + +<p>Sin embargo, si cambias el atributo <code>font-size</code> de <code><html></code> en el CSS, verás que todo lo demás cambia en relación con él, tanto la letra cuyo tamaño está especificado en unidades <code>rem</code> como la que lo está en unidades <code>em</code>.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/em-rem.html", '100%', 1000)}} </p> + +<h3 id="Porcentajes">Porcentajes</h3> + +<p>En muchos casos, un porcentaje es tratado de la misma manera que una longitud. Lo que sucede con los porcentajes es que siempre se establecen en relación con otro valor. Por ejemplo, si estableces el atributo <code>font-size</code> de un elemento como un porcentaje, será un porcentaje del <code>font-size</code> del elemento padre. Si usas un porcentaje para un valor <code>width</code>, será un porcentaje del atributo <code>width</code> del elemento padre.</p> + +<p>En el ejemplo siguiente, las dos cajas con el tamaño especificado en unidades de porcentaje y las dos cajas con el tamaño especificado en unidades de píxel tienen los mismos nombres de clase. En ambos conjuntos de cajas, los anchos de las cajas son de 200 píxeles y de 40%, respectivamente.</p> + +<p>La diferencia es que el segundo conjunto de dos cajas está dentro de un contenedor que tiene 400 píxeles de ancho. La segunda caja de 200 px de ancho tiene el mismo ancho que la primera, pero la segunda caja de 40% ahora es el 40% de 400 px, ¡mucho más estrecha que la primera!</p> + +<p><strong>Cambia el ancho del contenedor o el valor de porcentaje para ver cómo funciona.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/percentage.html", '100%', 850)}} </p> + +<p>El ejemplo siguiente tiene tamaños de letra establecidos en porcentajes. Cada elemento <code><li></code> tiene un atributo <code>font-size</code> del 80%, por lo tanto, los elementos de la lista anidada se vuelven progresivamente más pequeños a medida que heredan su tamaño del elemento padre.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/percentage-fonts.html", '100%', 650)}} </p> + +<p>Observa que aunque muchos valores admiten unidades de longitud o porcentaje, algunos solo admiten unidades de longitud. Puedes ver qué valores admite cada propiedad en las páginas de referencia correspondientes del proyecto MDN. Si el valor admitido incluye <code><a href="/en-US/docs/Web/CSS/length-percentage"><length-percentage></a></code>, puedes usar una unidad de longitud o un porcentaje. Si el valor admitido solo incluye <code><length></code>, no es posible utilizar un porcentaje.</p> + +<h3 id="Números">Números</h3> + +<p>Algunos valores aceptan números sin ninguna unidad asociada. Un ejemplo de una propiedad que acepta un número sin unidades es la propiedad <code>opacity</code>, que controla la opacidad de un elemento (cuán transparente es). Esta propiedad admite un número entre <code>0</code> (totalmente transparente) y <code>1</code> (totalmente opaco).</p> + +<p><strong>En el ejemplo siguiente, asigna al valor de <code>opacity</code> diversos valores decimales entre <code>0</code> y <code>1</code> para ver cómo la caja y su contenido cambian su opacidad.</strong></p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/opacity.html", '100%', 500)}} </p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Cuando en CSS utilizas un número como valor, no debe estar entre comillas.</p> +</div> + +<h2 id="Color">Color</h2> + +<p>En CSS hay muchas formas de especificar el color, algunas de las cuales se implementaron más recientemente que otras. En todas partes en CSS se pueden usar los mismos valores de color, tanto para especificar el color del texto como el color de fondo, o de cualquier otra cosa.</p> + +<p>El sistema de colores estándar disponible en los ordenadores modernos es de 24 bits, lo que permite visualizar aproximadamente 16,7 millones de colores distintos a partir de una combinación de diferentes canales de rojo, verde y azul con 256 valores diferentes por canal (256 x 256 x 256 = 16.777.216). Echemos un vistazo a algunas de las formas en que podemos especificar colores en CSS.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: En este artículo vamos a ver los métodos comunes para especificar colores que admiten los navegadores; hay otros métodos no tan comunes que no admiten todos los navegadores.</p> +</div> + +<h3 id="Palabras_clave_para_los_colores">Palabras clave para los colores</h3> + +<p>Muy a menudo, en los ejemplos de este artículo o en cualquier otra página de MDN, verás que se utilizan las palabras clave para los colores, ya que son una forma simple y comprensible de especificar colores. Hay una multitud de estas palabras clave, ¡algunas de las cuales tienen nombres de lo más curiosos! Puedes ver una lista completa en la página para el valor <code><a href="/es/docs/Web/CSS/color_value"><color></a></code>.</p> + +<p><strong>Juega con diferentes valores de color en los ejemplos en vivo que encontrarás a continuación, para adquirir una idea más clara de cómo funcionan.</strong></p> + +<h3 id="Los_valores_hexadecimales_RGB">Los valores hexadecimales RGB</h3> + +<p>El siguiente tipo de valores de color que es probable que encuentres son los códigos hexadecimales. Cada valor hexadecimal consiste en un símbolo de hashtag/almohadilla (#) seguido de seis cifras hexadecimales, cada una de las cuales puede tomar uno de los 16 valores entre el 0 y la f (que representa el 15), por ejemplo: <code>0123456789abcdef</code>. Cada par de cifras representa uno de los canales (rojo, verde y azul) y nos permite especificar cualesquiera de los 256 valores disponibles para cada uno (16 x 16 = 256).</p> + +<p>Estos valores son un poco más complejos y menos fáciles de entender, pero son mucho más versátiles que las palabras clave: puedes usar valores hexadecimales para representar cualquier color que desees usar en tu combinación de colores.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/color-hex.html", '100%', 700)}} </p> + +<p><strong>Una vez más, cambia los valores para ver cómo varían los colores.</strong></p> + +<h3 id="Valores_RGB_y_RGBA">Valores RGB y RGBA</h3> + +<p>El tercer esquema del que hablaremos aquí es RGB. Un valor RGB es una función <code>rgb()</code> que recibe tres parámetros que representan los valores de los canales rojo, verde y azul del color, de modo muy similar a los valores hexadecimales. La diferencia con RGB es que cada canal está representado no por dos dígitos hexadecimales, sino por un número decimal entre el 0 y el 255, lo que de algún modo resulta algo más fácil de entender.</p> + +<p>Vamos a reescribir nuestro último ejemplo para utilizar colores RGB:</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/color-rgb.html", '100%', 700)}} </p> + +<p>También puedes usar colores RGBA: estos funcionan exactamente de la misma manera que los colores RGB, por lo que puedes usar cualquier valor RGB; sin embargo, hay un cuarto valor que representa el canal alfa del color, que controla la opacidad. Si estableces este valor en <code>0</code>, el color será completamente transparente, mientras que en <code>1</code> será completamente opaco. Los valores intermedios le confieren diferentes niveles de transparencia.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Establecer un canal alfa en un color representa una diferencia clave para usar la propiedad {{cssxref ("opacity")}} que vimos anteriormente. Cuando usas la opacidad, el elemento y todo lo que contiene es opaco, mientras que cuando usas colores RGBA, solo son opacos los que especificas.</p> +</div> + +<p>En el ejemplo siguiente hemos añadido una imagen de fondo al bloque que contiene nuestras cajas de color. También hemos configurado las cajas para que tengan diferentes valores de opacidad: observa que el fondo se muestra más cuanto menor es el valor del canal alfa.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/color-rgba.html", '100%', 770)}}</p> + +<p><strong>En este ejemplo, cambia los valores del canal alfa y observa cómo afecta a la salida de color. </strong></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: En algún momento, los navegadores modernos se actualizaron para que <code>rgba()</code> y <code>rgb()</code>, y <code>hsl()</code> y <code>hsla()</code> (ver más abajo) se convirtieran en alias puros el uno del otro y comenzaran a comportarse exactamente igual. Así, por ejemplo, tanto <code>rgba()</code> como <code>rgb()</code> admiten colores con y sin valores de canal alfa. Cambia el <code>rgba()</code> del ejemplo anterior por <code>rgb()</code> y observa si los colores aún funcionan. El estilo que uses depende de ti, pero separar las definiciones de los colores transparentes y las de los no transparentes con el uso de funciones diferentes mejora la ejecución de los navegadores y puede actuar como un indicador visual de dónde se definen colores transparentes en tu código.</p> +</div> + +<h3 id="Los_valores_HSL_y_HSLA">Los valores HSL y HSLA</h3> + +<p>Un poco menos compatible que RGB es el modelo de color HSL (no compatible con las antiguas versiones de Internet Explorer), que se implementó después de mucha insistencia por parte de los diseñadores. En lugar de los valores rojo, verde y azul, la función <code>hsl()</code> admite valores de matiz, saturación y luminosidad, que se utilizan para distinguir entre los 16,7 millones de colores, pero de una manera diferente:</p> + +<ul> + <li><strong>Matiz</strong>: El tono base del color. Toma un valor entre 0 y 360, que representa un ángulo en torno a una rueda de colores.</li> + <li><strong>Saturación</strong>: ¿Qué nivel de saturación presenta el color? Esta propiedad toma un valor entre 0 y 100%, en que 0 no es un color (aparece como un tono de gris) y 100% es el nivel de saturación total del color.</li> + <li><strong>Luminosidad</strong>: ¿Qué claridad o brillo presenta el color? Este atributo toma un valor entre 0 y 100%, en que 0 es no claro (aparece completamente negro) y 100% es completamente claro (aparece completamente blanco).</li> +</ul> + +<p>Podemos adaptar el ejemplo con colores RGB para usar colores HSL, así:</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/color-hsl.html", '100%', 700)}} </p> + +<p>Al igual que RGB tiene un equivalente RGBA, HSL tiene un equivalente HSLA, que le proporciona la misma capacidad para especificar el canal alfa. Demostramos esto a continuación cambiando nuestro ejemplo RGBA para usar colores HSLA.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/color-hsla.html", '100%', 770)}} </p> + +<p>Puedes usar cualquiera de estos valores de color en tus proyectos. Es probable que para la mayoría de los proyectos te decidas por una paleta de colores y luego uses esos colores (y tu método elegido para especificar el color) en todo el proyecto. También puedes mezclar y combinar diversos modelos de color, sin embargo, por coherencia, en general es mejor si todo el proyecto usa el mismo.</p> + +<h2 id="Imágenes">Imágenes</h2> + +<p>El tipo de datos <code><a href="/en-US/docs/Web/CSS/image"><image></a></code> se usa cuando una imagen es un valor válido. Puede ser un archivo de imagen real al que apunta una función <code>url()</code>, o un degradado.</p> + +<p>En el ejemplo siguiente mostramos una imagen y un gradiente en uso como un valor para la propiedad CSS <code>background-image</code>.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/image.html", '100%', 740)}} </p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: hay otros valores posibles para <code><image></code>, pero son más nuevos y aún hay pocos navegadores que los admiten. Consulta la página de MDN para el tipo de dato <code><a href="/en-US/docs/Web/CSS/image"><image></a></code> si deseas saber más sobre ellos.</p> +</div> + +<h2 id="Posición">Posición</h2> + +<p>El tipo de dato <code><a href="/en-US/docs/Web/CSS/position_value"><position></a></code> representa un conjunto de coordenadas 2D que se utiliza para colocar un elemento, por ejemplo una imagen de fondo (con el atributo <code><a href="/en-US/docs/Web/CSS/background-position">background-position</a></code>). Puede tomar palabras clave como <code>top</code>, <code>left</code>, <code>bottom</code>, <code>right</code> y <code>center</code> para alinear los elementos con los límites específicos de una caja de dos dimensiones, y también longitudes, que representan desplazamientos desde los bordes superior e izquierdo de la caja.</p> + +<p>Un valor de posición típico consta de dos valores: el primero establece la posición horizontal, y el segundo la vertical. Si solo especificas valores para un eje, el otro usará <code>center</code> por defecto.</p> + +<p>En el ejemplo siguiente hemos colocado una imagen de fondo a 40px de la parte superior, y a la derecha del contenedor con una palabra clave.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/position.html", '100%', 720)}} </p> + +<p><strong>Juega un poco con estos valores y observa cómo cambia la posición de la imagen.</strong></p> + +<h2 id="Cadenas_e_identificadores">Cadenas e identificadores</h2> + +<p>En los ejemplos anteriores hemos visto casos en que se usan palabras clave como valores (por ejemplo, palabras clave para <code><color></code>, como <code>red</code>, <code>black</code>, <code>rebeccapurple</code> y <code>goldenrod</code>). Estas palabras clave normalmente se describen como <em>identificadores</em>, un valor especial que el CSS entiende. Como tales, no se escriben entre comillas (es decir, no se tratan como cadenas).</p> + +<p>Hay casos en el CSS en que debes usar cadenas, por ejemplo, <a href="https://wiki.developer.mozilla.org/es/docs/Learn/CSS/Building_blocks/Selectores_CSS/Pseudo-clases_y_pseudo-elementos#Generar_contenido_con_before_y_after">al especificar el contenido que generas</a>. En este caso, el valor se escribe entre comillas para mostrar que se trata de una cadena de caracteres. En el ejemplo siguiente hemos usado palabras clave para el color, sin entrecomillar, y también una cadena caracteres, de contenido generado, entrecomillada.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/strings-idents.html", '100%', 550)}} </p> + +<h2 id="Funciones">Funciones</h2> + +<p>El último tipo de valor que vamos a analizar es el grupo de valores conocidos como funciones. En programación, una función es un bloque de código reutilizable que es posible ejecutar varias veces para completar una tarea repetitiva con el mínimo esfuerzo tanto por parte del desarrollador como del ordenador. Las funciones suelen asociarse a lenguajes como JavaScript, Python o C++, pero también hay funciones en CSS, como valores de código propietario. Ya hemos visto funciones en acción en la sección sobre los colores: <code>rgb()</code>, <code>hsl()</code>, etc. El valor que se utiliza para devolver una imagen de un archivo, en este caso <code>url()</code>, también es una función.</p> + +<p>Un valor que se comporta más como algo que puedes encontrar en un lenguaje de programación tradicional es la función <code>calc()</code>. Esta función te proporciona la capacidad de hacer cálculos simples en tu CSS. Es particularmente útil si deseas calcular valores que no puedes definir al escribir el CSS para tu proyecto y necesitas que el navegador lo haga durante la ejecución.</p> + +<p>Por ejemplo, a continuación usamos <code>calc()</code> para hacer que la caja tenga <code>20% + 100px</code> de ancho. El 20% se calcula a partir del ancho del contenedor principal <code>.wrapper</code> y, por lo tanto, cambiará si ese ancho cambia. No podemos hacer este cálculo de antemano porque no sabemos cuál será el 20% del elemento padre, por lo que usamos <code>calc()</code> para decirle al navegador que lo haga por nosotros.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/values-units/calc.html", '100%', 450)}}</p> + +<h2 id="Pon_a_prueba_tus_conocimientos">Pon a prueba tus conocimientos</h2> + +<p>Hemos cubierto mucho terreno en este artículo. ¿Recuerdas la información más importante? Encontrarás más pruebas para comprobar que retienes esa información antes de seguir en <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS/Building_blocks/Values_tasks">Test your skills: Values and units</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Esta ha sido una revisión rápida de los tipos de valores y unidades más comunes que te puedes encontrar. Puedes echar un vistazo a todos los diferentes tipos en la página de referencia de <a href="/en-US/docs/Web/CSS/CSS_Values_and_Units">valores y unidades CSS</a>; encontrarás muchos de estos mientras trabajas en estos artículos.</p> + +<p>Lo que debes recordar es que cada propiedad tiene una lista definida de valores admisibles, y cada valor incluye una definición que explica cuáles son sus subvalores. A continuación puedes buscar los detalles aquí, en MDN.</p> + +<p>Por ejemplo, comprender que <code><a href="/es/docs/Web/CSS/image"><image></a></code> también te permite crear un degradado de color es útil, ¡pero quizás no sea un conocimiento obvio!</p> + +<p>{{PreviousMenuNext("Learn/CSS/Building_blocks/Overflowing_content", "Learn/CSS/Building_blocks/Sizing_items_in_CSS", "Learn/CSS/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Cascade_and_inheritance">Cascada y herencia</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors">Selectores CSS</a> + <ul> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Type_Class_and_ID_Selectors">Selectores de tipo, de clase y de ID</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Attribute_selectors">Selectores de atributo</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Pseudo-classes_and_pseudo-elements">Las pseudoclases y los pseudoelementos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Selectors/Combinators">Selectores de combinación</a></li> + </ul> + </li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/The_box_model">El modelo de caja</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Backgrounds_and_borders">Fondos y bordes</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Handling_different_text_directions">El uso de diferentes direcciones de texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Overflowing_content">El desbordamiento de los contenidos</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Values_and_units">Los valores y las unidades</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Sizing_items_in_CSS">Elementos de dimensionado en CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Images_media_form_elements">Imágenes, media y elementos de formulario</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Debugging_CSS">Depurar el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/Building_blocks/Organizing">Organizar el CSS</a></li> +</ol> diff --git a/files/es/learn/css/css_layout/diseño_receptivo/index.html b/files/es/learn/css/css_layout/diseño_receptivo/index.html new file mode 100644 index 0000000000..4ddb7a94db --- /dev/null +++ b/files/es/learn/css/css_layout/diseño_receptivo/index.html @@ -0,0 +1,324 @@ +--- +title: Diseño receptivo +slug: Learn/CSS/CSS_layout/Diseño_receptivo +translation_of: Learn/CSS/CSS_layout/Responsive_Design +--- +<div>{{learnsidebar}}{{PreviousMenuNext("Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout/Media_queries", "Learn/CSS/CSS_layout")}}</div> + +<p>En los primeros días del diseño web, las páginas se diseñaban para llenar un tamaño de pantalla en particular. Si el usuario tenía una pantalla más grande o más pequeña que la del diseñador, los resultados esperados iban desde barras de desplazamiento no deseadas hasta longitudes de línea excesivamente largas y un mal uso del espacio. A medida que estuvieron disponibles tamaños de pantalla más diversos, apareció el concepto de <em>diseño web responsivo </em> (RWD, <em>responsive web design</em>), un conjunto de prácticas que permite a las páginas web alterar su diseño y apariencia para adaptarse a diferentes anchos de pantalla, resoluciones, etc. Es una idea que cambió la forma en que diseñamos para una web multidispositivo, y en este artículo te ayudaremos a comprender las principales técnicas que necesitas saber para dominarlo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Primeros pasos en CSS</a> y <a href="/es/docs/Learn/CSS/Building_blocks">Los elementos básicos del CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender los conceptos fundamentales y la historia del diseño responsivo.</td> + </tr> + </tbody> +</table> + +<h2 id="Diseños_de_sitios_web_históricos">Diseños de sitios web históricos</h2> + +<p>En un momento de la historia, solo tenías dos opciones al diseñar un sitio web:</p> + +<ul> + <li>Podías crear un sitio <em>líquido</em>, que se expandiría para llenar toda la ventana del navegador</li> + <li>o un sitio de <em>ancho fijo</em>, que sería un tamaño fijo en píxeles.</li> +</ul> + +<p>Estos dos enfoques tendían a dar como resultado un sitio web que se veía mejor ¡en la pantalla de la persona que diseñaba el sitio! El sitio líquido dio como resultado un diseño encogido en las pantallas que eran más pequeñas (como se ve a continuación) o longitudes de línea interminables en las pantallas que eran más grandes.</p> + +<figure><img alt="Un diseño de página con dos columnas encogidas en una ventana gráfica del tamaño de un teléfono móvil." src="https://mdn.mozillademos.org/files/16834/mdn-rwd-liquid.png" style="display: block; height: 406px; width: 300px;"> +<figcaption></figcaption> +</figure> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Observa este <a href="https://mdn.github.io/css-examples/learn/rwd/liquid-width.html">ejemplo</a> y su <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/liquid-width.html">código fuente</a> de un diseño líquido sencillo. Amplía o reduce la ventana del navegador y observa cómo cambia su aspecto en diferentes tamaños.</p> +</div> + +<p>El sitio de ancho fijo se arriesgaba a una barra de desplazamiento horizontal en pantallas que eran más pequeñas que el ancho del sitio (como se ve a continuación), y a un gran espacio en blanco en los bordes del diseño en las pantallas que eran más grandes.</p> + +<figure><img alt="Un diseño con una barra de desplazamiento horizontal en una ventana de teléfono móvil." src="https://mdn.mozillademos.org/files/16835/mdn-rwd-fixed.png" style="display: block; height: 411px; width: 300px;"> +<figcaption></figcaption> +</figure> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Observa este <a href="https://mdn.github.io/css-examples/learn/rwd/fixed-width.html">ejemplo</a> y su <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/fixed-width.html">código fuente</a> de un diseño sencillo con un ancho fijo. Nuevamente, cambia el tamaño de la ventana del navegador y observa el resultado.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Las capturas de pantalla anteriores se han tomado usando el <a href="/es/docs/Tools/Responsive_Design_View">modo de diseño responsivo</a> de las herramientas DevTools de Firefox.</p> +</div> + +<p>A medida que la web móvil comenzó a hacerse realidad con los primeros teléfonos con funciones, las empresas que deseaban adoptar los dispositivos móviles solían crear una versión especial de su sitio web para dispositivo móvil, con una URL diferente (a menudo algo así como <em>m.example.com</em> o <em>example.mobi</em>). Esto significaba que había que desarrollar y actualizar dos versiones independientes del sitio web.</p> + +<p>Además, estos sitios web para dispositivos móviles a menudo ofrecían una experiencia muy reducida. A medida que los dispositivos móviles se volvían más potentes y capaces de mostrar sitios web completos, esto resultaba frustrante para los usuarios de dispositivos móviles, que se veían atrapados en la versión móvil del sitio web y no podían acceder a la información que sabían que había en la versión de escritorio, que incluía todas las funciones del sitio web.</p> + +<h2 id="Diseño_flexible_antes_del_diseño_responsivo">Diseño flexible antes del diseño responsivo</h2> + +<p>Se desarrollaron varios enfoques para tratar de resolver los inconvenientes de los métodos líquidos o de ancho fijo para crear sitios web. En 2004, Cameron Adams escribió una publicación titulada <a href="http://www.themaninblue.com/writing/perspective/2004/09/21/">Resolution dependent layout</a>, que describe un método para crear un diseño que podría adaptarse a diferentes resoluciones de pantalla. Este enfoque requería JavaScript para detectar la resolución de la pantalla y cargar el CSS correcto.</p> + +<p>Zoe Mickley Gillenwater fue determinante en <a href="http://zomigi.com/blog/voices-that-matter-slides-available/">su trabajo</a> de descripción y formalización de los diversos modos en que se podían crear sitios web flexibles para intentar encontrar una situación intermedia entre llenar toda la pantalla o tener un tamaño completamente fijo.</p> + +<h2 id="Diseño_responsivo">Diseño responsivo</h2> + +<p>El término <em>diseño responsivo</em> fue acuñado por <a href="https://alistapart.com/article/responsive-web-design/">Ethan Marcotte en 2010</a>, y describía el uso combinado de tres técnicas.</p> + +<ol> + <li>La primera era la idea de las redes fluidas, algo que ya exploraba Gillenwater, y que puede leerse en el artículo de Marcotte, <a href="https://alistapart.com/article/fluidgrids/">Fluid Grids</a> (publicado en 2009 en <em>A list apart</em>).</li> + <li>La segunda técnica era la idea de las <a href="http://unstoppablerobotninja.com/entry/fluid-images">imágenes fluidas</a>. Usando una técnica muy simple de establecer la propiedad de <code>max-width</code> al <code>100%</code>, las imágenes se reducían si su columna de contención se volvía más estrecha que el tamaño intrínseco de la imagen, pero nunca se expandía. Esto permite reducir una imagen para que se ajuste a una columna de tamaño flexible, en lugar de que desborde, pero no se expande ni se pixela si la columna se ensancha más que la imagen.</li> + <li>El tercer componente clave era la <a href="/es/docs/Web/CSS/Media_Queries">consulta a los media</a>. Las consultas a los media habilitan el tipo de cambio de diseño que Cameron Adams había explorado previamente usando JavaScript, pero usando solo CSS. En lugar de tener un único diseño para todos los tamaños de pantalla, el diseño podría cambiarse. Las barras laterales pueden reposicionarse en una pantalla más pequeña, o puede mostrarse una navegación alternativa.</li> +</ol> + +<p>Es importante comprender que <strong>el diseño web responsivo no es una tecnología independiente</strong>: es un término utilizado para describir un enfoque para el diseño web, o un conjunto de buenas prácticas utilizado para crear un diseño que puede <em>responder</em> según el dispositivo que se utiliza para ver un contenido. En la exploración original de Marcotte, esto significaba cuadrículas flexibles (mediante elementos flotantes) y consultas de media; sin embargo, en los casi 10 años desde que se escribió ese artículo, trabajar de manera responsiva se ha convertido en la norma. Los métodos de diseño CSS modernos son inherentemente responsivos, y la plataforma web dispone de herramientas integradas nuevas que facilitan el diseño de sitios web responsivos.</p> + +<p>El resto de este artículo te indicará las diversas características de la plataforma web que puedas querer utilizar para crear un sitio responsivo.</p> + +<h2 id="La_consulta_a_los_media">La consulta a los media</h2> + +<p>El diseño responsivo solo pudo surgir gracias a la consulta a los media. La especificación de nivel 3 de consulta a los media se convirtió en una candidata a Recomendación en 2009, lo que significa que se consideró lista para su implementación en los navegadores. Las consultas a los media nos permiten ejecutar una serie de pruebas (por ejemplo, si la pantalla del usuario es mayor que un ancho o una resolución determinados) y aplicar CSS selectivamente para diseñar la página de manera que resulte adecuada a las necesidades del usuario.</p> + +<p>Por ejemplo, la consulta a los media siguiente explora si la página web que se muestra lo hace como un medio de pantalla (por lo tanto, no es un documento impreso) y si la ventana tiene al menos 800 píxeles de ancho. El CSS para el selector <code>.container</code> solo se aplicará si ambas condiciones son ciertas.</p> + +<pre class="brush: css"><code>@media screen and (min-width: 800px) { + .container { + margin: 1em 2em; + } +} </code> +</pre> + +<p>Puedes añadir múltiples consultas a los media dentro de una hoja de estilo, y ajustar todo tu diseño o solo partes de él para que se adapte mejor a los diferentes tamaños de pantalla. Los puntos en los que se introduce una consulta a los media y se cambia el diseño se conocen como <em>puntos de interrupción</em>.</p> + +<p>Un enfoque común cuando se usan las consultas a los media es crear un diseño sencillo de una sola columna para dispositivos de pantalla estrecha (por ejemplo, teléfonos móviles), luego implementar un diseño en columnas para pantallas más grandes cuando se sabe que hay suficiente ancho de pantalla para manejarlo. Esto se describe a menudo como diseño <strong>primero móvil</strong>.</p> + +<p>Obtén más información sobre las <a href="/es/docs/Web/CSS/Media_Queries">consultas a los media</a> en la documentación de MDN.</p> + +<h2 id="Cuadrículas_flexibles">Cuadrículas flexibles</h2> + +<p>Los sitios responsivos no solo cambian su diseño entre puntos de interrupción, sino que se construyen sobre cuadrículas flexibles. Una cuadrícula flexible significa que no tienes que centrarte en todos los tamaños de dispositivo posibles y construir para ellos un diseño en píxeles perfecto. Ese enfoque sería imposible dada la gran cantidad de dispositivos de tamaños diferentes que hay, y el hecho de que, al menos en la versión de escritorio, las personas no siempre tienen la ventana de su navegador maximizada.</p> + +<p>Al usar una cuadrícula flexible, solo necesitas añadir un punto de interrupción y cambiar el diseño en el punto en que el contenido comienza a verse mal. Por ejemplo, si las longitudes de las líneas se vuelven interminablemente largas a medida que el tamaño de la pantalla aumenta, o una caja se encoje hasta un ancho de dos palabras en cada línea a medida que el tamaño de la pantalla se reduce.</p> + +<p>En los primeros días del diseño responsivo, nuestra única opción para el diseño de páginas web era usar <a href="/es/docs/Learn/CSS/CSS_layout/Floats">elementos flotantes</a>. Los diseños de pantalla con elementos flotantes flexibles se lograban dando a cada elemento un ancho porcentual asegurándose de que para toda la página no alcanzara más del 100%. En su trabajo original sobre cuadrículas fluidas, Marcotte detalló una fórmula para tomar un diseño de página web diseñado usando píxeles y convertirlo en porcentajes.</p> + +<pre><code>target / context = result </code> +</pre> + +<p>Por ejemplo, si el tamaño de nuestra columna de destino es de 60 píxeles y el contexto (o contenedor) en el que se encuentra es de 960 píxeles, dividimos 60 por 960 para obtener un valor que podemos usar en nuestro CSS, después de mover el separador de cifras decimales dos posiciones a la derecha.</p> + +<pre class="brush: css"><code>.col { + width: 6.25%; /* 60 / 960 = 0.0625 */ +} </code> +</pre> + +<p>Este enfoque se encuentra hoy en muchos lugares de la web, y aquí está documentado en la sección de compaginación de nuestro artículo sobre <a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">métodos de compaginación heredados</a>. Es probable que encuentres sitios web que utilizan este enfoque en su trabajo, por lo que vale la pena entenderlo, aunque no vas a construir un sitio web moderno utilizando una cuadrícula flexible basada en elementos flotantes.</p> + +<p>El ejemplo siguiente muestra un diseño responsivo sencillo que utiliza consultas a los medios y una cuadrícula flexible. En pantallas estrechas, el diseño de página muestra las cajas en columna una encima de la otra:</p> + +<figure><img alt="Una vista de un dispositivo móvil con un diseño de página con cajas en columna vertical una encima de la otra." src="https://mdn.mozillademos.org/files/16836/mdn-rwd-mobile.png" style="display: block; height: 407px; width: 300px;"> +<figcaption></figcaption> +</figure> + +<p>En pantallas más anchas se pasa a dos columnas:</p> + +<figure><img alt="Una vista de un dispositivo de escritorio con un diseño a dos columnas." src="https://mdn.mozillademos.org/files/16837/mdn-rwd-desktop.png" style="display: block; height: 217px; width: 600px;"> +<figcaption></figcaption> +</figure> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar el <a href="https://mdn.github.io/css-examples/learn/rwd/float-based-rwd.html">ejemplo en vivo</a> y el <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/float-based-rwd.html">código fuente</a> de este ejemplo en GitHub.</p> +</div> + +<h2 id="Tecnologías_modernas_de_diseño_de_páginas_web">Tecnologías modernas de diseño de páginas web</h2> + +<p>Los métodos modernos de diseño de páginas web, como el <a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">diseño en columnas</a>, <a href="/es/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a> y <a href="/es/docs/Learn/CSS/CSS_layout/Grids">Grid</a> son responsivos por defecto. Todos estos métodos asumen que tratas de crear una cuadrícula flexible y te proporcionan los modos más fáciles de hacerlo.</p> + +<h3 id="Multicol">Multicol</h3> + +<p>El más antiguo de estos métodos de diseño de páginas web es multicol. Cuando especificas un atributo <code>column-count</code>, esto indica en cuántas columnas deseas dividir tu contenido. El navegador entonces calcula el tamaño de estas columnas, que cambiará de acuerdo con el tamaño de la pantalla.</p> + +<pre class="brush: css"><code>.container { + column-count: 3; +} </code> +</pre> + +<p>Si en lugar de ello estableces el atributo <code>column-width</code>, especificas un ancho <em>mínimo</em>. El navegador crea tantas columnas de ese ancho como quepan cómodamente en el contenedor, y reparte el espacio entre todas las columnas. Por lo tanto, el número de columnas cambia según la cantidad de espacio que hay.</p> + +<pre class="brush: css"><code>.container { + column-width: 10em; +} </code> +</pre> + +<h3 id="Flexbox">Flexbox</h3> + +<p>En el método Flexbox, los elementos flexibles se encogen y distribuyen el espacio entre los elementos según el espacio que hay en su contenedor, según su comportamiento inicial. Al cambiar los valores de <code>flex-grow</code> y <code>flex-shrink</code>, puedes indicar cómo deseas que se comporten los elementos cuando a su alrededor hay más o menos espacio.</p> + +<p>En el ejemplo siguiente, los elementos flexibles ocupan cada uno la misma cantidad de espacio en el contenedor flexible, al utilizar la abreviatura <code>flex: 1</code> como se describe en el artículo <a href="/es/docs/Learn/CSS/CSS_layout/Grids#Cuadr%C3%ADculas_flexibles_con_la_unidad_fr">Flexbox: Dimensionamiento flexible de los elementos flex</a>.</p> + +<pre class="brush: css"><code>.container { + display: flex; +} + +.item { + flex: 1; +} </code> +</pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Como ejemplo, hemos reconstruido el anterior diseño de página responsivo sencillo, esta vez usando Flexbox. Puedes ver que ya no necesitamos usar valores de porcentaje extraños para calcular el tamaño de las columnas: <a href="https://mdn.github.io/css-examples/learn/rwd/flex-based-rwd.html">ejemplo</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/flex-based-rwd.html">código fuente</a>.</p> +</div> + +<h3 id="Cuadrículas_CSS">Cuadrículas CSS</h3> + +<p>En el diseño de cuadrículas con CSS, la unidad <code>fr</code> permite la distribución del espacio disponible en las trazas de la cuadrícula. El ejemplo siguiente crea un contenedor de cuadrícula con tres trazas dimensionadas a <code>1fr</code>. Esto crea tres columnas, cada una de las cuales ocupa una parte del espacio que hay disponible en el contenedor. Puedes obtener más información sobre este enfoque para crear una cuadrícula en el módulo Aprender a diseñar cuadrículas en <a href="/en-US/docs/Learn/CSS/CSS_layout/Grids#Flexible_grids_with_the_fr_unit">Cuadrículas flexibles con la unidad fr</a>.</p> + +<pre class="brush: css"><code>.container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; +} </code> +</pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: La versión del diseño de página en cuadrícula es aún más simple, ya que podemos definir las columnas en .wrapper: <a href="https://mdn.github.io/css-examples/learn/rwd/grid-based-rwd.html">ejemplo</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/grid-based-rwd.html">código fuente</a>.</p> +</div> + +<h2 id="Imágenes_responsivas">Imágenes responsivas</h2> + +<p>El enfoque más simple para las imágenes responsivas es el que se describe en los primeros artículos de Marcotte sobre diseño responsivo. Básicamente, tomar una imagen que tenga el tamaño más grande que puedas necesitar, y reducirla. Este continúa siendo un enfoque utilizado hoy en día, y en la mayoría de las hojas de estilo encontrarás en alguna parte el CSS siguiente:</p> + +<pre class="brush: css"><code>img { + max-width: 100%: +} </code> +</pre> + +<p>Hay inconvenientes obvios en este enfoque. La imagen puede mostrarse mucho más pequeña que su tamaño intrínseco, lo que representa una pérdida de ancho de banda: un usuario de dispositivo móvil puede descargar una imagen que sea varias veces el tamaño de lo que ve en realidad en la ventana del navegador. Además, es posible que no desees la misma relación de aspecto de la imagen en dispositivos móviles y en ordenadores de escritorio. Por ejemplo, podría ser bueno tener una imagen cuadrada para dispositivos móviles, pero mostrar la misma escena que una imagen horizontal en el escritorio. O bien es posible que, reconociendo el tamaño más pequeño de una imagen en dispositivos móviles, desees mostrar una imagen diferente, que se entienda mejor en un tamaño de pantalla pequeño. Estas cosas no se pueden lograr simplemente reduciendo una imagen.</p> + +<p>Las imágenes responsivas, que utilizan el elemento {{htmlelement ("picture")}} y los atributos {{htmlelement ("img")}} <code>srcset</code> y <code>sizes</code> resuelven ambos problemas. Puedes proporcionar varios tamaños junto con «sugerencias» (metadatos que describen el tamaño de pantalla y la resolución para que la imagen sea la más adecuada), y el navegador elije la imagen que resulta más adecuada para cada dispositivo, y se asegura de que el usuario descarga un tamaño de imagen apropiado para el dispositivo que utiliza.</p> + +<p>También puedes usar imágenes <em>de director artístico</em>, que proporcionan un recorte o una imagen completamente diferente para diferentes tamaños de pantalla.</p> + +<p>Puedes encontrar una <a href="/es/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">guía detallada de imágenes responsivas en el artículo sobre Aprender HTML</a> en MDN.</p> + +<h2 id="Tipografía_responsiva">Tipografía responsiva</h2> + +<p>Un elemento de diseño responsivo que todavía no hemos tratado en trabajos anteriores es la idea de la tipografía responsiva. Este concepto describe esencialmente el hecho de cambiar el tamaño de letra según el espacio de pantalla que reflejan las consultas a media.</p> + +<p>En este ejemplo, queremos establecer que nuestro encabezado de nivel 1 sea <code>4rem</code>, lo que significa que será cuatro veces nuestro tamaño de letra base. ¡Es un título muy grande! Solo queremos este título de encabezado gigante en los tamaños de pantalla más grandes, por lo tanto, primero creamos un título de encabezado más pequeño y luego usamos las consultas a los media para sobrescribirlo con el tamaño más grande si sabemos que el usuario tiene un tamaño de pantalla de al menos <code>1200px</code>.</p> + +<pre class="brush: css"><code>html { + font-size: 1em; +} + +h1 { + font-size: 2rem; +} + +@media (min-width: 1200px) { + h1 { + font-size: 4rem; + } +} </code> +</pre> + +<p>Hemos editado nuestro ejemplo anterior de cuadrícula responsiva para incluir también el tipo de respuesta utilizando el método descrito. Puedes ver cómo el título de encabezado cambia de tamaño cuando el diseño para a la versión de dos columnas.</p> + +<p>En la versión para dispositivo móvil, el encabezado es más pequeño:</p> + +<figure><img alt="Un diseño de elementos apilados en columna con un tamaño de título de encabezado pequeño." src="https://mdn.mozillademos.org/files/16838/mdn-rwd-font-mobile.png" style="display: block; height: 407px; width: 300px;"> +<figcaption></figcaption> +</figure> + +<p>Sin embargo, en las versiones de escritorio vemos un tamaño de título de encabezado más grande:</p> + +<figure><img alt="Un diseño en dos columnas con un título grande." src="https://mdn.mozillademos.org/files/16839/mdn-rwd-font-desktop.png" style="display: block; height: 169px; width: 600px;"> +<figcaption></figcaption> +</figure> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Observa este ejemplo en: <a href="https://mdn.github.io/css-examples/learn/rwd/type-rwd.html">ejemplo</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/type-rwd.html">código fuente</a>.</p> +</div> + +<p>Como muestra este enfoque sobre la tipografía, no es necesario restringir las consultas a medios a cambiar solo el diseño de página. Se pueden usar para ajustar cualquier elemento y hacerlo más útil o atractivo según los diversos tamaños de pantalla.</p> + +<h3 id="El_uso_de_unidades_de_ventana_gráfica_para_tipografía_responsiva">El uso de unidades de ventana gráfica para tipografía responsiva</h3> + +<p>Un enfoque interesante es utilizar las unidades de ventana gráfica <code>vw</code> para habilitar la tipografía responsiva. <code>1vw</code> es igual al uno por ciento del ancho de la ventana gráfica, lo que significa que si configuras el tamaño del tipo de letra con <code>vw</code>, siempre estará en relación con el tamaño de la ventana gráfica.</p> + +<pre class="brush: css">h1 { + font-size: 6vw; +}</pre> + +<p>El problema de hacer esto es que el usuario pierde la posibilidad de ampliar cualquier conjunto de texto configurado en unidades <code>vw</code>, porque ese texto siempre está en relación con el tamaño de la ventana gráfica. <strong>Por lo tanto, nunca hay que establecer texto utilizando solo unidades de ventana</strong>.</p> + +<p>Hay una solución, que implica el uso de la función <code><a href="/en-US/docs/Web/CSS/calc">calc()</a></code>. Si añades la unidad <code>vw</code> a un valor establecido con un tamaño fijo, como <code>em</code> o <code>rem</code>, el texto continúa siendo ampliable. Esencialmente, la unidad <code>vw</code> se añade sobre ese valor ampliado:</p> + +<pre class="brush: css">h1 { + font-size: calc(1.5rem + 3vw); +}</pre> + +<p>Esto significa que necesitamos especificar el tamaño de letra para el título de encabezado una sola vez, en lugar de configurarlo para dispositivos móviles y redefinirlo en las consultas a medios. Luego, el tipo de letra aumenta gradualmente a medida que aumenta el tamaño de la ventana gráfica.</p> + +<div class="blockIndicator note"> +<p>Observa un ejemplo en: <a href="https://mdn.github.io/css-examples/learn/rwd/type-vw.html">ejemplo</a>, <a href="https://github.com/mdn/css-examples/blob/master/learn/rwd/type-vw.html">código fuente</a>.</p> +</div> + +<h2 id="La_metaetiqueta_viewport">La metaetiqueta viewport</h2> + +<p>Si observas el tipo de letra de una página HTML responsiva, en general vas a encontrar la siguiente etiqueta {{htmlelement ("meta")}} en la cabecera del documento.</p> + +<pre class="brush: html"><code><meta name="viewport" content="width=device-width,initial-scale=1"></code> +</pre> + +<p>Esta metaetiqueta informa a los navegadores de los dispositivos móviles que deben establecer el ancho de la ventana gráfica al ancho del dispositivo y escalar el documento al 100% de ese tamaño, de modo que el documento se mostrará al tamaño optimizado para esos dispositivos móviles.</p> + +<p>¿Por qué esto es necesario? Porque los navegadores de los dispositivos móviles tienden a mentir sobre el ancho de su ventana gráfica.</p> + +<p>Esta metaetiqueta existe porque cuando se lanzó el iPhone original y la gente comenzó a ver sitios web en una pequeña pantalla de teléfono móvil, la mayoría de los sitios web no estaban optimizados para dispositivos móviles. Por lo tanto, el navegador móvil establecía el ancho de la ventana gráfica en 960 píxeles, representaba la página con ese ancho y mostraba el resultado como una versión reducida del diseño del escritorio. Otros navegadores de dispositivos móviles (por ejemplo, en Google Android) hicieron lo mismo. Los usuarios podían acercarse y desplazarse por el sitio web para ver las partes que les interesaban, pero se veía mal. Todavía verás esto hoy en día si tienes la desgracia de encontrarte con un sitio web que no tiene un diseño de página responsivo.</p> + +<p>El problema es que tu diseño responsivo con puntos de interrupción y consultas a media no va a funcionar según lo previsto en los navegadores de dispositivos móviles, si tienes un diseño de pantalla estrecho que se inicia con un ancho de ventana de 480px o menos, pero la ventana gráfica está configurada en 960px. E cambio, al configurar <code>width=device-width</code> anulas el ancho predeterminado <code>width=960px</code> de Apple con el ancho real del dispositivo, y tus consultas a media funcionarán según lo previsto.</p> + +<p><strong>Por lo tanto, <em>siempre</em> debes incluir la línea de HTML anterior en la cabecera de tus documentos.</strong></p> + +<p>Con la metaetiqueta <code>viewport</code> puedes usar otras configuraciones, aunque, en general vas a querer usar la línea anterior.</p> + +<ul> + <li><code>initial-scale</code>: Establece el zoom inicial de la página, que establecemos en 1.</li> + <li><code>height</code>: Establece una altura específica para la ventana gráfica.</li> + <li><code>minimum-scale</code>: Establece el nivel mínimo de zoom.</li> + <li><code>maximum-scale</code>: Establece el nivel máximo de zoom.</li> + <li><code>user-scalable</code>: Impide el zoom si se establece en <code>no</code>.</li> +</ul> + +<p>Deberías evitar el uso de <code>minimum-scale</code> y <code>maximum-scale</code>, y en particular establecer <code>user-scalable</code> en <code>no</code>. Hay que permitir a los usuarios hacer zoom tanto o tan poco como lo necesiten; evitarlo provoca problemas de accesibilidad.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Hay una @regla CSS establecida para reemplazar la metaetiqueta <code>viewport</code>: <a href="/en-US/docs/Web/CSS/@viewport">@viewport</a>. Sin embargo, tiene poca compatibilidad con los navegadores. Se implementó en Internet Explorer y Edge, pero una vez que se lance el navegador Edge basado en Chromium, dejará de formar parte del navegador Edge.</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p>El diseño responsivo se refiere a un diseño página de un sitio web o una aplicación que responde al entorno en el que se visualiza. Abarca una serie de características y técnicas de CSS y HTML, y ahora es esencialmente el modo como construimos los sitios web de forma predeterminada. Piensa en los sitios web que visitas con tu dispositivo móvil; probablemente sea inusual encontrar un sitio web que tenga la versión de escritorio reducida o en que necesites desplazarse hacia los lados para encontrar las cosas. Esto se debe a que la web se ha movido a este enfoque de diseño responsivo.</p> + +<p>Además, lograr diseños responsivos se ha vuelto mucho más fácil con la ayuda de los métodos de diseño que has aprendido en estos artículos. Si eres nuevo en el desarrollo web, hoy tienes muchas más herramientas a tu disposición que en los primeros días del diseño de página responsivo. Por lo tanto, vale la pena verificar la antigüedad de los materiales que consultas. Si bien los artículos históricos continúan siendo útiles, el uso moderno de CSS y HTML facilita mucho la creación de diseños elegantes y útiles, sin importar con qué dispositivo el visitante visita el sitio.</p> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Multiple-column_Layout", "Learn/CSS/CSS_layout/Media_queries", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introducción al diseño CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Flujo normal</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Cuadrícula</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Elementos flotantes</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamiento</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Diseño en columnas</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Diseño responsivo</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Guía para principiantes sobre consultas a medios</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Métodos de compaginación heredados</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Compatibilidad de navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Evaluación del conjunto de elementos básicos de compaginación</a></li> +</ul> diff --git a/files/es/learn/css/css_layout/flexbox/index.html b/files/es/learn/css/css_layout/flexbox/index.html new file mode 100644 index 0000000000..5d2b8cdf36 --- /dev/null +++ b/files/es/learn/css/css_layout/flexbox/index.html @@ -0,0 +1,337 @@ +--- +title: Flexbox +slug: Learn/CSS/CSS_layout/Flexbox +translation_of: Learn/CSS/CSS_layout/Flexbox +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout")}}</div> + +<p class="summary"><a href="/es/docs/Web/CSS/CSS_Flexible_Box_Layout">Flexbox</a> es un método de diseño de página unidimensional para compaginar elementos en filas o columnas. Los elementos de contenido se ensanchan para rellenar el espacio adicional y se encogen para caber en espacios más pequeños. En este artículo expondremos todas sus características básicas.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Los conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a usar el sistema de compaginación con elementos flexbox para crear compaginaciones web.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Por_qué_flexbox">¿Por qué flexbox?</h2> + +<p>Durante mucho tiempo, las únicas herramientas fiables con compatibilidad cruzada entre navegadores disponibles para crear diseños CSS fueron cosas como la <a href="/es/docs/Learn/CSS/CSS_layout/Floats">flotación</a> y el <a href="/es/docs/Learn/CSS/CSS_layout/Positioning">posicionamiento</a>. Están bien y funcionan, pero de alguna manera también limitan bastante y frustran.</p> + +<p>Con tales herramientas resulta difícil, si no imposible, lograr obtener en cualquier forma conveniente y flexible un diseño de página sencillo con unos requisitos como los siguientes:</p> + +<ul> + <li>Centrar verticalmente un bloque de contenido dentro de su elemento padre.</li> + <li>Hacer que todos los elementos secundarios de un contenedor ocupen una cantidad igual del ancho/alto disponible, independientemente del ancho/alto que haya disponible.</li> + <li>Hacer que todas las columnas en una compaginación en columnas múltiples adopten la misma altura incluso si contienen cantidades diferentes de contenido.</li> +</ul> + +<p>Como verás en las secciones siguientes, los elementos flexbox facilitan mucho algunas tareas de compaginación. ¡Vamos a profundizar en ello!</p> + +<h2 id="Presentación_de_un_ejemplo_sencillo">Presentación de un ejemplo sencillo</h2> + +<p>En este artículo, te guiaremos por una serie de ejercicios para ayudarte a comprender cómo funcionan los elementos flexbox. Para comenzar, debes hacer una copia local del primer archivo de inicio <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flexbox0.html">flexbox0.html</a> de nuestro repositorio de GitHub. Cárgalo en un navegador moderno (como Firefox o Chrome) y echa un vistazo al código en tu editor de código. Puedes <a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/flexbox0.html">verlo en vivo aquí</a>.</p> + +<p>Verás que hay un elemento {{htmlelement ("header")}} con un encabezado de nivel superior en él, y un elemento {{htmlelement ("section")}} que contiene tres elementos {{htmlelement ("article")}}. Los usaremos para crear una compaginación bastante habitual de tres columnas.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13406/flexbox-example1.png" style="border-style: solid; border-width: 1px; display: block; height: 324px; margin: 0px auto; width: 800px;"></p> + +<h2 id="Especificar_qué_elementos_colocar_como_cajas_flexibles">Especificar qué elementos colocar como cajas flexibles</h2> + +<p>Para comenzar, vamos a seleccionar qué elementos se van a presentar como cajas flexibles. Para ello, establecemos un valor especial de {{cssxref ("display")}} en el elemento padre de los elementos que deseas editar. En este caso, queremos compaginar los elementos {{htmlelement ("article")}}, por lo que lo establecemos en {{htmlelement ("section")}} (que se convierte en un contenedor flexible):</p> + +<pre class="brush: css notranslate">section { + display: flex; +}</pre> + +<p>Esto hace que el elemento <code><section></code> se convierta en <strong>contenedor flex</strong>, y sus hijos en <strong>elementos flexibles</strong>. El resultado de esto debería ser algo así:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13408/flexbox-example2.png" style="border-style: solid; border-width: 1px; display: block; height: 348px; margin: 0px auto; width: 800px;"></p> + +<p>Así, esta declaración única nos da todo lo que necesitamos. Increíble, ¿verdad? Tenemos nuestra compaginación en columnas múltiples con columnas de igual tamaño, y todas las columnas tienen la misma altura. Esto se debe a que los valores por defecto que se han asignado a los elementos flexibles (los elementos secundarios del contenedor flexible) están pensados para resolver problemas comunes como este. Veremos más sobre el tema más adelante.</p> + +<p>Para que quede claro, reiteremos lo que está sucediendo aquí. El elemento al que le hemos dado un valor de {{cssxref("display")}} de <code>flex</code> actúa como un elemento a nivel de bloque en términos de cómo interactúa con el resto de la página, pero sus elementos secundarios se presentan como elementos flexibles. La siguiente sección explicará con más detalle qué significa esto. Ten en cuenta también que puede usar un valor de <code>display</code> de <code>inline-flex</code> si desea diseñar los elementos secundarios de un elemento como elementos flexibles, pero hacer que ese elemento se comporte como un elemento en línea.</p> + +<p> + </p><h2 id="El_modelo_flexible">El modelo flexible</h2> + + +<p>Cuando los elementos se presentan como cajas flexibles, se distribuyen con respecto a dos ejes:</p> + +<p><img alt="flex_terms.png" class="default internal" src="/files/3739/flex_terms.png" style="display: block; margin: 0px auto;"></p> + +<ul> + <li>El <strong>eje principal</strong> (<strong>main axis</strong>) es el eje que corre en la dirección en que se colocan los elementos flexibles (por ejemplo, según se disponen las filas en una página o hacia abajo según se disponen las columnas en una página). El inicio y el final de este eje se denominan <strong>inicio principal</strong> (<strong>main start</strong>) y <strong>final principal</strong> (<strong>main end</strong>).</li> + <li>El <strong>eje transversal</strong> (<strong>cross axis</strong>) es el eje que corre perpendicular a la dirección en la que se colocan los elementos flexibles. El inicio y el final de este eje se denominan <strong>inicio transversal</strong> (<strong>cross start</strong>) y <strong>extremo cruzado</strong> (<strong>cross end</strong>).</li> + <li>El elemento padre que tiene establecido <code>display: flex</code> (el elemento {{htmlelement ("section")}} en nuestro ejemplo) se llama <strong>contenedor flexible</strong>.</li> + <li>Los elementos que se presentan como cajas flexibles dentro del contenedor flexible se denominan <strong>elementos flexibles</strong> (son los elementos {{htmlelement ("article")}} de nuestro ejemplo).</li> +</ul> + +<p>Ten presente esta terminología al avanzar por las secciones posteriores. Si en algún momento te confundes con el uso de estos conceptos, siempre puedes volver atrás a consultarlos.</p> + +<h2 id="¿Columnas_o_filas">¿Columnas o filas?</h2> + +<p>Los elementos flexbox proporcionan una propiedad llamada {{cssxref ("flex-direction")}} que especifica en qué dirección corre el eje principal (en qué dirección están dispuestos los elementos hijo de un elemento flexbox); por defecto, está establecido en el valor <code>row</code>, por lo que se presenta en una fila en la dirección en que se escribe el idioma predeterminado de tu navegador (de izquierda a derecha, en el caso de un navegador en español).</p> + +<p>Añade la declaración siguiente a tu regla {{htmlelement ("section")}}:</p> + +<pre class="brush: css notranslate">flex-direction: column;</pre> + +<p>Observa que esto vuelve a colocar los elementos en una disposición en columna, al igual que antes de añadir cualquier CSS. Antes de continuar, elimina esta declaración de tu ejemplo.</p> + +<div class="note"> +<p><strong>Nota</strong>: También puedes compaginar elementos flexibles en una dirección inversa utilizando los valores <code>row-reverse</code> y <code>column-reverse</code>. ¡Experimenta también con estos valores!</p> +</div> + +<h2 id="Delimitar">Delimitar</h2> + +<p>Un problema que surge cuando tienes una cantidad fija de ancho o alto en tu diseño es que los hijos de un elemento flexbox eventualmente desbordan el contenedor y rompen el diseño. Echa un vistazo a nuestro ejemplo <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flexbox-wrap0.html">flexbox-wrap0.html</a> e intenta <a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/flexbox-wrap0.html">verlo en vivo</a> (toma una copia local de este archivo si deseas seguir este ejemplo):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13410/flexbox-example3.png" style="display: block; height: 646px; margin: 0px auto; width: 800px;"></p> + +<p>Aquí vemos que los elementos hijo se salen de su contenedor. Una forma de solucionar esto es añadir la declaración siguiente a tu regla {{htmlelement ("section")}}:</p> + +<pre class="brush: css notranslate">flex-wrap: wrap;</pre> + +<p>Añade también la declaración siguiente a tu regla {{htmlelement ("article")}}:</p> + +<pre class="brush: css notranslate">flex: 200px;</pre> + +<p>Pruébalo; observa que al haberlo incluido el aspecto de la compaginación resulta mucho más agradable:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13412/flexbox-example4.png" style="display: block; height: 646px; margin: 0px auto; width: 800px;"> Ahora hay varias filas y en cada fila caben tantos elementos hijo de un elemento flexbox como sean necesarios, y cualquier desbordamiento hace saltar el elemento hacia la línea siguiente. La declaración <code>flex: 200px</code> que hemos establecido en los artículos significa que cada uno tendrá al menos 200 px de ancho; discutiremos esta propiedad con más detalle más adelante. Observa también que los últimos elementos hijo de la última fila se agrandan hasta rellenar toda la fila.</p> + +<p>Pero aquí podemos hacer mucho más. En primer lugar, cambia el valor de tu propiedad {{cssxref ("flex-direction")}} a <code>row-reverse</code>; ahora verás que todavía tienes tu compaginación en diversas filas, pero comienza desde la esquina opuesta de la ventana del navegador y fluye al revés.</p> + +<h2 id="Propiedades_abreviadas_de_flex-flow">Propiedades abreviadas de flex-flow</h2> + +<p>En este punto vale la pena señalar que hay una propiedad abreviada para {{cssxref ("flex-direction")}} y {{cssxref ("flex-wrap")}}: {{cssxref ("flex-flow")}}. Así, por ejemplo, puedes reemplazar:</p> + +<pre class="brush: css notranslate">flex-direction: row; +flex-wrap: wrap;</pre> + +<p>con</p> + +<pre class="brush: css notranslate">flex-flow: row wrap;</pre> + +<h2 id="Dimensionamiento_flexible_de_elementos_flexibles">Dimensionamiento flexible de elementos flexibles</h2> + +<p>Volvamos ahora a nuestro primer ejemplo y veamos cómo podemos controlar qué proporción de espacio ocupan los elementos flexibles. Inicia tu copia local de <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flexbox0.html">flexbox0.html</a> o toma una copia de <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flexbox1.html">flexbox1.html</a> como nuevo punto de partida (<a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/flexbox1.html">consúltalo en vivo</a>).</p> + +<p>Primero, añade la regla siguiente al final de tu CSS:</p> + +<pre class="brush: css notranslate">article { + flex: 1; +}</pre> + +<p>Este es un valor de proporción sin unidades que especifica la cantidad de espacio disponible sobre el eje principal que ocupa cada elemento flexible. En este caso, damos a cada elemento {{htmlelement ("article")}} un valor de 1, lo que significa que todos ocuparán una cantidad igual del espacio libre restante después de que se hayan establecido elementos como el área de relleno y el margen. Es una proporción, lo que significa que dar a cada elemento flexible un valor de 400000 tendría exactamente el mismo efecto.</p> + +<p>Ahora añade la regla siguiente debajo de la anterior:</p> + +<pre class="brush: css notranslate">article:nth-of-type(3) { + flex: 2; +}</pre> + +<p>Al actualizar verás que el tercer {{htmlelement ("article")}} ocupa ahora el doble del ancho disponible que los otros dos; ahora hay cuatro unidades de proporción disponibles en total. Los primeros dos elementos flexibles tienen una cada uno, por lo que ocupan 1/4 del espacio disponible cada uno. El tercero tiene dos unidades, por lo que ocupa 2/4 del espacio disponible (o 1/2).</p> + +<p>También puedes especificar un valor de tamaño mínimo dentro del valor flexible. Actualiza las reglas para tu artículo de la manera siguiente:</p> + +<pre class="brush: css notranslate">article { + flex: 1 200px; +} + +article:nth-of-type(3) { + flex: 2 200px; +}</pre> + +<p>Esto establece básicamente que «a cada elemento flexible se le da primero 200px del espacio disponible. Después de eso, el resto del espacio disponible se reparte de acuerdo con las unidades de proporción». Actualiza y observa de qué modo se reparte ahora el espacio.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13406/flexbox-example1.png" style="border-style: solid; border-width: 1px; display: block; height: 324px; margin: 0px auto; width: 800px;"></p> + +<p>El valor real del elemento flexbox se puede ver en su flexibilidad/adaptabilidad: si cambias el tamaño de la ventana del navegador o añades otro elemento {{htmlelement ("article")}}, el diseño continúa funcionando bien.</p> + +<h2 id="flex_forma_completa_y_abreviada">flex: forma completa y abreviada</h2> + +<p>{{cssxref ("flex")}} es una propiedad abreviada que puede especificar hasta tres valores diferentes:</p> + +<ul> + <li>El valor de proporción sin unidades que ya hemos comentado. Se puede especificar individualmente usando la propiedad {{cssxref ("flex-grow")}}.</li> + <li>Un segundo valor de proporción sin unidades, {{cssxref ("flex-shrink")}}, que entra en juego cuando los elementos flexibles desbordan el contenedor. Especifica cuánto de la cantidad desbordada se quita al tamaño de cada elemento flexible para evitar que el contenedor se desborde. Esta es una característica bastante avanzada de flexbox, y no la vamos a exponer en detalle en este artículo.</li> + <li>El valor de tamaño mínimo que ya hemos visto. Se puede especificar individualmente usando el valor {{cssxref ("flex-basis")}}.</li> +</ul> + +<p>Recomendamos no usar las propiedades flex sin abreviar a menos que realmente tengas que hacerlo (por ejemplo, para anular algo establecido previamente). Comportan mucho código añadido y suelen aportar confusión.</p> + +<h2 id="Alineación_horizontal_y_vertical">Alineación horizontal y vertical</h2> + +<p>También puedes usar las funciones de los elementos flexbox para alinear elementos flexibles sobre el eje principal o transversal. Exploremos este aspecto a partir de un ejemplo nuevo: <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/flexbox/flex-align0.html">flex-align0.html</a> (<a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/flex-align0.html">consúltalo en vivo</a>), que vamos a convertir en una barra de herramientas/botones ordenada y flexible. En este momento puedes ver una barra de menú horizontal, con algunos botones pegados en línea a la esquina superior izquierda.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13414/flexbox-example5.png" style="display: block; height: 77px; margin: 0px auto; width: 600px;"></p> + +<p>Primero, toma una copia local de este ejemplo.</p> + +<p>Ahora, añade a la parte inferior del CSS del ejemplo lo siguiente:</p> + +<pre class="brush: css notranslate">div { + display: flex; + align-items: center; + justify-content: space-around; +}</pre> + +<p>Actualiza la página y observa que los botones ahora están convenientemente centrados, horizontal y verticalmente. Lo hemos hecho a partir de dos propiedades nuevas.</p> + +<p>{{cssxref ("align-items")}} controla dónde se ubican los elementos flexibles en el eje transversal.</p> + +<ul> + <li>Por defecto, el valor es <code>stretch</code>, que ensancha todos los elementos flexibles para rellenar el elemento primario en la dirección del eje transversal. Si el elemento padre no tiene un ancho fijo en la dirección del eje transversal, todos los elementos flexibles son tan largos como los elementos flexibles más largos. Así es como nuestro primer ejemplo obtuvo columnas de igual altura por defecto.</li> + <li>El valor <code>center</code> que utilizamos en nuestro código anterior mantiene las dimensiones intrínsecas de los elementos pero los centra sobre el eje transversal. Es por eso que los botones de nuestro ejemplo ahora están centrados verticalmente.</li> + <li>También puedes tener valores como <code>flex-start</code> y <code>flex-end</code>, que alinean todos los elementos al inicio y al final del eje transversal, respectivamente. Consulta {{cssxref ("align-items")}} para conocer todos los detalles al respecto.</li> +</ul> + +<p>Puedes anular el comportamiento {{cssxref ("align-items")}} para elementos flexibles individuales aplicándoles la propiedad {{cssxref ("align-self")}}. Por ejemplo, añade a tu CSS lo siguiente:</p> + +<pre class="brush: css notranslate">button:first-child { + align-self: flex-end; +}</pre> + +<p>Observa qué efecto tiene esto y retíralo de nuevo al terminar.</p> + +<p>{{cssxref ("justify-content")}} controla dónde se ubican los elementos flexibles sobre el eje principal.</p> + +<ul> + <li>El valor por defecto es <code>flex-start</code>, que asienta todos los elementos al comienzo del eje principal.</li> + <li>Puedes usar <code>flex-end</code> para que se asienten al final.</li> + <li><code>center</code> también es un valor de <code>justify-content</code> (para alinear contenido), que asienta los elementos flexibles sobre el centro del eje principal.</li> + <li>El valor <code>space-around</code> que hemos usado antes es útil porque distribuye todos los elementos de manera uniforme sobre el eje principal y deja un poco de espacio en cada extremo.</li> + <li>Hay otro valor, <code>space-between</code>, que es muy similar a <code>space-around</code>, pero no deja espacio en los extremos.</li> +</ul> + +<p>Te animamos a jugar con estos valores para ver cómo funcionan antes de continuar.</p> + +<h2 id="Ordenar_los_elementos_flexibles">Ordenar los elementos flexibles</h2> + +<p>Los elementos flexbox también tienen una función para cambiar el orden de disposición de los elementos flexibles, sin que ello afecte a su orden en el código fuente. Esto es algo que resulta imposible de hacer con los métodos de compaginación tradicionales.</p> + +<p>El código para esto es simple: añade el siguiente CSS al código de ejemplo de la barra de controles:</p> + +<pre class="brush: css notranslate">button:first-child { + order: 1; +}</pre> + +<p>Actualiza, y observa que el botón «Smile» se ha movido al final del eje principal. Observemos cómo funciona esto con un poco más de detalle:</p> + +<ul> + <li>Por defecto, todos los elementos flexibles tienen un valor {{cssxref ("order")}} de 0.</li> + <li>Los elementos flexibles que tengan establecidos los valores de orden más altos aparecerán más tarde en el orden de visualización que los elementos que tengan valores de orden más bajos.</li> + <li>Los artículos flexibles con el mismo valor de orden aparecerán en su orden de origen. Luego, si hay cuatro elementos cuyos valores de orden se han establecido en 2, 1, 1 y 0, respectivamente, su orden de visualización será 4°, 2°, 3° y, por último, 1°.</li> + <li>El tercer elemento aparece después del segundo porque tiene el mismo valor de orden y está después de él en el orden del código de origen.</li> +</ul> + +<p>Puedes establecer valores de orden negativos para que los elementos aparezcan antes que los elementos establecidos con el valor 0. Por ejemplo, puedes hacer que el botón «Blush» aparezca al comienzo del eje principal utilizando la regla siguiente:</p> + +<pre class="brush: css notranslate">button:last-child { + order: -1; +}</pre> + +<h2 id="Cajas_flexibles_anidadas">Cajas flexibles anidadas</h2> + +<p>Los elementos flexbox permiten crear algunos diseños de página bastante complejos. Es perfectamente aceptable configurar un elemento flexible para que también sea un contenedor flexible, de modo que los elementos secundarios también se dispongan como cajas flexibles. Echa un vistazo a complex-flexbox.html (<a href="http://mdn.github.io/learning-area/css/css-layout/flexbox/complex-flexbox.html">consúltalo en vivo</a>).</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13418/flexbox-example7.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>El HTML para ello es bastante simple. Hay un elemento {{htmlelement ("section")}} que contiene tres elementos {{htmlelement ("article")}}. El tercer elemento {{htmlelement ("article")}} contiene tres elementos {{htmlelement ("div")}}:</p> + +<pre class="notranslate">section - article + article + article - div - button + div button + div button + button + button</pre> + +<p>Veamos el código que hemos usado para esta compaginación.</p> + +<p>En primer lugar, configuramos los elementos secundarios de {{htmlelement ("section")}} para que se presenten como cajas flexibles.</p> + +<pre class="brush: css notranslate">section { + display: flex; +}</pre> + +<p>A continuación, establecemos algunos valores flexibles en los elementos {{htmlelement ("article")}}. Presta una atención especial a la segunda regla: configuramos el tercer elemento {{htmlelement ("article")}} para que sus hijos también se presenten como elementos flexibles, pero esta vez los disponemos en una columna.</p> + +<pre class="brush: css notranslate">article { + flex: 1 200px; +} + +article:nth-of-type(3) { + flex: 3 200px; + display: flex; + flex-flow: column; +} +</pre> + +<p>A continuación, seleccionamos el primer elemento {{htmlelement ("div")}}. Primero usamos <code>flex:1 100px;</code> para darle una altura mínima efectiva de 100 px, luego configuramos sus elementos secundarios (los elementos {{htmlelement ("button")}}) para que también se presenten como elementos flexibles. Aquí los colocamos en una fila que los delimita y los alineamos en el centro del espacio disponible, como hicimos en el ejemplo del botón individual que vimos antes.</p> + +<pre class="brush: css notranslate">article:nth-of-type(3) div:first-child { + flex:1 100px; + display: flex; + flex-flow: row wrap; + align-items: center; + justify-content: space-around; +}</pre> + +<p>Por último, establecemos un tamaño para el botón, pero lo más interesante es que le damos un valor flexible de 1 auto. Esto tiene un efecto muy interesante, que puedes observar si cambias el tamaño del ancho de la ventana de tu navegador. Los botones ocuparán tanto espacio como puedan y se asentarán tantos en la misma línea como quepan, pero cuando ya no quepan con comodidad en la misma línea, saltarán de línea y crearán líneas nuevas.</p> + +<pre class="brush: css notranslate">button { + flex: 1 auto; + margin: 5px; + font-size: 18px; + line-height: 1.5; +}</pre> + +<h2 id="Compatibilidad_entre_navegadores">Compatibilidad entre navegadores</h2> + +<p>La compatibilidad de los elementos flexbox está garantizada para la mayoría de los navegadores nuevos: Firefox, Chrome, Opera, Microsoft Edge e Internet Explorer 11, las versiones más recientes de Android/iOS, etc. Sin embargo, todavía hay navegadores antiguos en uso que no admiten las propiedades flexbox (o lo hacen, pero admiten una versión muy antigua y desactualizada).</p> + +<p>Esto no importa demasiado mientras estás aprendiendo y experimentando; pero cuando consideras usar propiedades flexbox en un sitio web real, debes hacer pruebas y asegurarte de que tu experiencia de usuario sea lo suficientemente aceptable en tantos navegadores como sea posible.</p> + +<p>Las propiedades flexbox son un poco más complicadas que otras características de CSS. Por ejemplo, si un navegador no soporta sombras en CSS, es probable que el sitio todavía sea utilizable. Sin embargo, si no es compatible con las funciones flexbox, probablemente el diseño completo se romperá, y el sitio web se inutilizará.</p> + +<p>Expusimos estrategias para superar problemas de compatibilidad entre navegadores en nuestro módulo <a href="/es/docs/Learn/Herramientas_y_pruebas/Cross_browser_testing">Pruebas de compatibilidad del navegador</a>.</p> + +<h2 id="Pon_a_prueba_tus_habilidades">Pon a prueba tus habilidades</h2> + +<p>Hemos cubierto mucho terreno en este artículo. ¿Recuerdas la información más importante? Encontrarás más pruebas para comprobar si retienes esta información antes de seguir en <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Flexbox_skills">Test your skills: Flexbox</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Con esto concluye nuestro recorrido por los conceptos básicos de las propiedades flexbox. Esperamos que te hayas divertido y que juegues con ello mientras avanzas en tu aprendizaje. A continuación, veremos otro aspecto importante de los diseños CSS: las rejillas CSS.</p> + +<div>{{PreviousMenuNext("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout")}}</div> + +<div> +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introducción al diseño CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Flujo normal</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Cuadrícula</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Flotadores</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamiento</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Diseño en varias columnas</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Diseño adaptativo</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Guía para principiantes sobre consultas a medios</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Métodos de compaginación heredados</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Compatibilidad en navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Evaluación del conjunto de elementos básicos de compaginación</a></li> +</ul> +</div> diff --git a/files/es/learn/css/css_layout/floats/index.html b/files/es/learn/css/css_layout/floats/index.html new file mode 100644 index 0000000000..47ae275f2e --- /dev/null +++ b/files/es/learn/css/css_layout/floats/index.html @@ -0,0 +1,505 @@ +--- +title: Floats +slug: Learn/CSS/CSS_layout/Floats +translation_of: Learn/CSS/CSS_layout/Floats +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout/Positioning", "Learn/CSS/CSS_layout")}}</div> + +<p>Originalmente pensada para flotar imágenes dentro de bloques de texto, la propiedad {{cssxref("float")}} se convirtió en una de las herramientas más usadas para crear diseños multicolumna en las páginas web. Con la llegada de Flexbox y Grid ha vuelto ahora a su propósito original, como se explica en este artículo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>HTML básico (ver <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>), y una idea de Cómo funciona CSS (ver <a href="/es/docs/Learn/CSS/First_steps">Introducción a CSS</a>.)</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a crear elementos flotantes en páginas web, y a usar la propiedad <em>clear</em> y otros métodos para limpiar los elementos flotantes.</td> + </tr> + </tbody> +</table> + +<h2 id="La_historia_de_los_elementos_flotantes">La historia de los elementos flotantes</h2> + +<p>La propiedad {{cssxref("float")}} fue introducida para permitir a los desarrolladores implementar diseños sencillos que incluyeran una imagen flotando dentro de una columna de texto, con el texto envolviendo la parte izquierda o derecha de la imagen. El tipo de cosa que encuentras habitualmente en el diseño de un periódico.</p> + +<p>Pero los desarrolladores web pronto se dieron cuenta de que podían flotar cualquier cosa, no solo imágenes, por lo que su uso se extendió, por ejemplo creando efectos de diseño divertidos como estas <a href="https://css-tricks.com/snippets/css/drop-caps/">letras capitulares</a>.</p> + +<p>Los elementos flotantes han sido usados comúnmente para crear diseños web completos con múltiples columnas situadas unas al lado de las otras (el comportamiento por defecto sería que las columnas se situaran unas debajo de las otras, en el mismo orden en el que aparecen en el código fuente). Ahora hay disponibles técnicas más modernas y mejores, que exploraremos más adelante en este módulo, por lo que el uso de {{cssxref("float")}} de este modo debería contemplarse como una <a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">técnica anticuada</a>.</p> + +<p>En este artículo nos centraremos en el uso apropiado de la propiedad {{cssxref("float")}}.</p> + +<h2 id="Un_ejemplo_de_float_simple">Un ejemplo de float simple</h2> + +<p>Exploremos cómo usar los <em>float</em>. Empezaremos con un ejemplo realmente simple que incluye un bloque de texto flotando alrededor de un elemento. Puedes acompañarnos creando un fichero <code>index.html</code> en tu ordenador, rellenándolo con <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">una plantilla HTML simple</a>, e insertando el código siguiente en los lugares adecuados. Al final de la sección podrás ver un ejemplo en vivo de cómo debería ser el código final.</p> + +<p>Primero, empecemos con algo de HTML simple — añade lo siguiente al cuerpo de tu HTML, eliminando cualquier otra cosa que hubiera antes:</p> + +<pre class="brush: html notranslate"><h1>Ejemplo simple de caja flotante</h1> + +<div class="box">Caja flotante</div> + +<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. </p> + +<p>Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p></pre> + +<p>Ahora aplica el siguiente CSS a tu HTML (usando un elemento {{htmlelement("style")}} o un {{htmlelement("link")}} para separar el fichero <code>.css</code> — tú eliges):</p> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; + font: .9em/1.2 Arial, Helvetica, sans-serif +} + +.box { + width: 150px; + height: 100px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +}</pre> + +<p>Si guardas y recargas la página, verás algo parecido a lo que esperarías: la caja se encuentra por encima del texto, en un flujo normal. Para flotar el texto alrededor, añade las propiedades {{cssxref("float")}} y {{cssxref("margin-right")}} a la regla <code>.box</code>:</p> + +<pre class="brush: css notranslate">.box { + float: left; + margin-right: 15px; + width: 150px; + height: 100px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +}</pre> + +<p>Ahora, si guardas y recargas, podrás ver algo parecido a lo siguiente:</p> + +<div id="Float_1"> +<div class="hidden"> +<h6 id="Float_Example_1">Float Example 1</h6> + +<pre class="brush: html notranslate"><h1>Ejemplo simple de caja flotante</h1> + +<div class="box">Caja flotante</div> + +<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. </p> + +<p>Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> +</pre> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; + font: .9em/1.2 Arial, Helvetica, sans-serif +} + +.box { + float: left; + margin-right: 15px; + width: 150px; + height: 150px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Float_1', '100%', 500) }}</p> + +<p>Analicemos ahora cómo funciona el <em>float</em> — el elemento con el <em>float</em> aplicado (el elemento {{htmlelement("div")}} en este caso) es sacado del flujo normal del documento y está pegado al lado izquierdo de su elemento contenedor padre ({{htmlelement("body")}}, en este caso). Cualquier contenido que esté por debajo del elemento flotado en el flujo normal, ahora lo envolverá, rellenando el espacio a la derecha hasta la parte superior del elemento flotante. Allí se detendrá.</p> + +<p>Flotar el contenido a la derecha tiene exactamente el mismo efecto, pero a la inversa — el elemento flotado se pegará a la derecha, y el contenido lo envolverá por la izquierda. Prueba cambiando el valor de la propiedad <em>float</em> a <code>right</code> y reemplaza {{cssxref("margin-right")}} con {{cssxref("margin-left")}} en el último conjunto de reglas para ver el resultado.</p> + +<p>Si bien podemos agregar un margen al flotante para alejar el texto, no podemos agregar un margen al texto para alejarlo del flotante. Esto se debe a que un elemento flotante se saca del flujo normal y las cajas de los siguientes elementos siguen detrás del flotador. Puedes comprobarlo haciendo algunos cambios en tu ejemplo.</p> + +<p>Añade una clase <code>special</code> al primer párrafo de texto, el que sucede inmediatamente a la caja flotante, y luego añade en tu CSS las siguientes reglas. Esto le dará al párrafo siguiente un color de fondo.</p> + +<pre class="brush: css notranslate">.special { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; +} +</pre> + +<p>Para que el efecto sea más fácil de ver, cambia el <code>margin-right</code> de tu elemento flotante a <code>margin</code>, para obtener espacio alrededor del elemento flotante. Verás que el fondo del párrafo pasa justo por debajo de la caja flotante, como en el ejemplo inferior.</p> + +<div id="Float_2"> +<div class="hidden"> +<h6 id="Float_Example_2">Float Example 2</h6> + +<pre class="brush: html notranslate"><h1>Ejemplo simple de caja flotante</h1> + +<div class="box">Caja flotante</div> + +<p class="special">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. </p> + +<p>Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> </pre> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; + font: .9em/1.2 Arial, Helvetica, sans-serif +} + +.box { + float: left; + margin: 15px; + width: 150px; + height: 150px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} + +.special { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; +} +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Float_2', '100%', 500) }}</p> + +<p>Los cuadros de línea de nuestro siguiente elemento se han acortado para que el texto discurra alrededor del flotador, pero debido a que el flotador se eliminó del flujo normal, el cuadro alrededor del párrafo aún permanece en ancho completo.</p> + +<h2 id="Limpiando_floats">Limpiando floats</h2> + +<p>Hemos visto que el flotador se elimina del flujo normal y que otros elementos se mostrarán a su lado, por lo tanto, si queremos evitar que un elemento siguiente se mueva hacia arriba, debemos limpiar el <em>float</em>. Esto se logra con la propiedad {{cssxref ("clear")}}.</p> + +<p>En el HTML del ejemplo anterior, añade una clase <code>cleared</code> al segundo párrafo debajo del elemento flotante. Luego añade lo siguiente a tu CSS:</p> + +<pre class="brush: css notranslate">.cleared { + clear: left; +} +</pre> + +<div id="Float_3"> +<div class="hidden"> +<h6 id="Float_Example_3">Float Example 3</h6> + +<pre class="brush: html notranslate"><h1>Ejemplo simple de caja flotante</h1> + +<div class="box">Caja flotante</div> + +<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. </p> + +<p class="cleared">Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + </pre> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; + font: .9em/1.2 Arial, Helvetica, sans-serif +} + +.box { + float: left; + margin: 15px; + width: 150px; + height: 150px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} + +.cleared { + clear: left; +} +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Float_3', '100%', 600) }}</p> + +<p>Deberías ver que el siguiente párrafo limpia el elemento flotante y ya no aparece junto a él. La propiedad <code>clear</code> acepta los siguientes valores:</p> + +<ul> + <li><code>left</code>: limpia los elementos flotados a la izquierda.</li> + <li><code>right</code>: limpia los elementos flotados a la derecha.</li> + <li><code>both</code>: limpia cualquier elemento flotado, a la izquierda o a la derecha.</li> +</ul> + +<h2 id="Limpiar_las_cajas_envueltas_alrededor_de_un_float">Limpiar las cajas envueltas alrededor de un float</h2> + +<p>Ahora ya sabes cómo limpiar un elemento que sigue a un elemento flotante, pero observa lo que sucede si tienes un flotante alto y un párrafo corto, con una caja envolviendo a ambos elementos. Modifica tu documento para que el primer párrafo y el cuadro flotante estén envueltos por un {{htmlelement("div")}} con una clase <code>wrapper</code>.</p> + +<pre class="brush: html notranslate"><div class="wrapper"> + <div class="box">Caja flotante</div> + + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate.</p> +</div> +</pre> + +<p>En tu CSS, añade la siguiente regla para la clase <code>.wrapper</code> y después recarga la página:</p> + +<pre class="brush: css notranslate">.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; +}</pre> + +<p>Además, elimina la clase <code>.cleared</code> anterior:</p> + +<pre class="comment-text notranslate" id="ct-0">.cleared { + clear: left; +}</pre> + +<p>Verás que, como en el ejemplo en el que hemos puesto un color de fondo al párrafo, el color de fondo pasa por detrás del elemento flotante.</p> + +<div id="Float_4"> +<div class="hidden"> +<h6 id="Float_Example_4">Float Example 4</h6> + +<pre class="brush: html notranslate"><h1>Ejemplo simple de caja flotante</h1> +<div class="wrapper"> + <div class="box">Caja flotante</div> + + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. </p> +</div> + +<p class="cleared">Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> </pre> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; + font: .9em/1.2 Arial, Helvetica, sans-serif +} + +.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; +} + +.box { + float: left; + margin: 15px; + width: 150px; + height: 150px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Float_4', '100%', 600) }}</p> + +<p>Una vez más, esto se debe a que el flotador se ha sacado del flujo normal. Limpiar el siguiente elemento no ayuda con este problema de limpieza de caja, donde queremos que la parte inferior de la caja envuelva el elemento flotante y envuelva el contenido incluso si el contenido es más corto. Hay tres formas posibles de lidiar con esto, dos que funcionan en todos los navegadores, pero tienen algo de truco, y una tercera, nueva forma de lidiar con esta situación correctamente.</p> + +<h3 id="El_hack_clearfix">El hack clearfix</h3> + +<p>La forma en que esta situación se ha tratado tradicionalmente es utilizando algo conocido como "truco clearfix". Esto implica insertar algún contenido generado después del cuadro que contiene el contenido flotante y envolvente, y configurarlo para limpiar ambos.</p> + +<p>Añade el siguiente CSS al ejemplo:</p> + +<pre class="brush: css notranslate">.wrapper::after { + content: ""; + clear: both; + display: block; +}</pre> + +<p>Ahora recarga la página y la caja debería limpiarse. Esto es básicamente lo missmo que si hubieras añadido un elemento HTML como un <code><div></code> debajo de los elementos y le hubieras añadido la propiedad <code>clear: both</code>.</p> + +<div id="Float_5"> +<div class="hidden"> +<h6 id="Float_Example_5">Float Example 5</h6> + +<pre class="brush: html notranslate"><h1>Ejemplo simple de caja flotante</h1> +<div class="wrapper"> + <div class="box">Caja flotante</div> + + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. </p> +</div> +<p class="cleared">Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> </pre> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; + font: .9em/1.2 Arial, Helvetica, sans-serif +} + +.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; +} + +.box { + float: left; + margin: 15px; + width: 150px; + height: 150px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} + +.wrapper::after { + content: ""; + clear: both; + display: block; +} +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Float_5', '100%', 600) }}</p> + +<h3 id="Usando_overflow">Usando overflow</h3> + +<p>Un método alternativo es establecer la propiedad {{cssxref("overflow")}} del elemento envolvente con un valor distinto de <code>visible</code>.</p> + +<p>Elimina el CSS clearfix que añadiste en la anterior sección y, en su lugar, añade <code>overflow: auto</code> a las reglas de la caja envolvente. De nuevo, la caja debería limpiarse.</p> + +<pre class="brush: css notranslate">.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; + overflow: auto; +}</pre> + +<div id="Float_6"> +<div class="hidden"> +<h6 id="Float_Example_6">Float Example 6</h6> + +<pre class="brush: html notranslate"><h1>Ejemplo simple de caja flotante</h1> +<div class="wrapper"> + <div class="box">Caja flotante</div> + + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. </p> +</div> +<p class="cleared">Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> </pre> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; + font: .9em/1.2 Arial, Helvetica, sans-serif +} + +.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; + overflow: auto; +} + +.box { + float: left; + margin: 15px; + width: 150px; + height: 150px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Float_6', '100%', 600) }}</p> + +<p>Este ejemplo funciona creando lo que se conoce como un <em><strong>block formatting context</strong></em> (BFC) o contexto de formato de bloque. Es como un pequeño diseño dentro de nuestra página dentro del cual todo está contenido, por lo tanto, nuestro elemento flotante está contenido dentro del BFC y el fondo se encuentra detrás de ambos elementos. Esto generalmente funcionará, sin embargo, en ciertos casos, es posible que encuentre barras de desplazamiento no deseadas o sombras recortadas debido a las consecuencias no deseadas del uso del desbordamiento..</p> + +<h3 id="display_flow-root">display: flow-root</h3> + +<p>La manera moderna de resolver este problema es usar el valor <code>flow-root</code> de la propiedad <code>display</code>. Esto existe solo para crear un BFC sin usar hacks; no habrá consecuencias no deseadas cuando lo use. Elimina <code>overflow: auto</code> de la regla <code>.wrapper</code> y añade <code>display: flow-root</code>. Asumiendo que tu <a href="/en-US/docs/Web/CSS/display#Browser_compatibility">navegador sea compatible</a>, la caja se limpiará.</p> + +<pre class="brush: css notranslate">.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; + display: flow-root; +}</pre> + +<div id="Float_7"> +<div class="hidden"> +<h6 id="Float_Example_7">Float Example 7</h6> + +<pre class="brush: html notranslate"><h1>Ejemplo simple de caja flotante</h1> +<div class="wrapper"> + <div class="box">Caja flotante</div> + + <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. </p> +</div> +<p class="cleared">Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> </pre> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; + font: .9em/1.2 Arial, Helvetica, sans-serif +} + +.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + color: #fff; + display: flow-root; +} + +.box { + float: left; + margin: 15px; + width: 150px; + height: 150px; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Float_7', '100%', 600) }}</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahora ya sabes todo lo que tienes que saber sobre los flotadores en el desarrollo web moderno. Consulta el artículo sobre <a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">métodos de diseño anticuados</a> para obtener información de cómo se solían usar, lo que puede serte útil si tienes que trabajar en proyectos antiguos.</p> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Grids", "Learn/CSS/CSS_layout/Positioning", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introduction to CSS layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Normal Flow</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grid</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Multiple-column Layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Legacy Layout Methods</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Supporting older browsers</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Fundamental Layout Comprehension Assessment</a></li> +</ul> diff --git a/files/es/learn/css/css_layout/flujo_normal/index.html b/files/es/learn/css/css_layout/flujo_normal/index.html new file mode 100644 index 0000000000..ffc873938f --- /dev/null +++ b/files/es/learn/css/css_layout/flujo_normal/index.html @@ -0,0 +1,95 @@ +--- +title: Flujo normal +slug: Learn/CSS/CSS_layout/Flujo_normal +translation_of: Learn/CSS/CSS_layout/Normal_Flow +--- +<div>{{LearnSidebar}}</div> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Introduction", "Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout")}}</p> + +<p class="summary">Este artículo explica el flujo normal, o la forma en que se presentan los elementos de la página web si no cambias su compaginación.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Conocer cómo los navegadores presentan de forma predeterminada las páginas web antes de comenzar a hacer cambios.</td> + </tr> + </tbody> +</table> + +<p>Como se detalla en el último artículo de introducción al diseño, los elementos en una página web se distribuyen según el flujo normal si no se aplica ningún CSS que cambie la forma en la que se comportan. Y, como comenzamos a descubrir, puedes cambiar el comportamiento de los elementos, ya sea ajustando su posición en este flujo normal o eliminándolos de este por completo. Comenzar con un documento coherente y bien estructurado que sea legible en el flujo normal es la mejor manera de comenzar cualquier página web. Asegura que tu contenido sea legible, incluso si el usuario usa un navegador muy limitado o un dispositivo como un lector de pantalla que lee el contenido de la página. Además, como el flujo normal está diseñado para que un documento sea legible, al comenzar de esta manera, trabajas en el documento en lugar de luchar contra él a medida que haces cambios en su diseño.</p> + +<p>Antes de profundizar en los diferentes métodos de diseño, vale la pena revisar algunas de las cosas que ya debes haber estudiado en artículos anteriores con respecto al flujo normal de los documentos.</p> + +<h2 id="¿Cómo_se_presentan_por_defecto_los_elementos">¿Cómo se presentan por defecto los elementos?</h2> + +<p>En primer lugar, se toma de las cajas de cada uno de los elementos el contenido, luego se añade cualquier área de relleno, borde y margen alrededor de ellas; es el modelo de cajas que hemos visto antes.</p> + +<p>De manera predeterminada, el contenido de un <a href="/es/docs/Web/HTML/Block-level_elements">elemento de nivel de bloque</a> es el 100% del ancho de su elemento padre y su altura viene determinada por su contenido. Los <a href="/es/docs/Web/HTML/Elementos_en_línea">elementos en línea</a> tienen su altura y anchura determinados por su contenido. No puedes establecer el ancho o la altura de los elementos en línea, simplemente se ubican dentro del contenido de los elementos de nivel de bloque. Si deseas controlar el tamaño de un elemento en línea de esta manera, debes configurarlo para que se comporte como un elemento de nivel de bloque con <code>display: block;</code> (o incluso, <code>display: inline-block;</code>, que combina características de ambos).</p> + +<p>Esto explica los elementos individuales, pero ¿qué hay del modo como los elementos interactúan entre sí? El flujo de diseño normal (mencionado en el artículo de introducción al diseño) es el sistema mediante el cual los elementos se colocan en la ventana gráfica del navegador. De manera predeterminada, los elementos de nivel de bloque se presentan en la <em>dirección del flujo del bloque</em>, en función del <a href="/es/docs/Web/CSS/writing-mode">modo de escritura</a> de los padres (<em>initial</em>: horizontal-tb): cada uno aparecerá en una línea nueva debajo de la última, y estarán separados por cualquier margen que se establezca en ellos. Por lo tanto, en inglés, o en cualquier otro modo de escritura horizontal y de arriba a abajo, los elementos de nivel de bloque se disponen verticalmente.</p> + +<p>Los elementos en línea se comportan de manera diferente: no aparecen en líneas nuevas; en su lugar, se asientan en la misma línea entre sí y con cualquier contenido de texto adyacente (o envuelto), siempre que tengan espacio dentro del ancho del elemento de nivel de bloque primario. Si no hay espacio, el texto o los elementos que desborden bajarán a la línea siguiente.</p> + +<p>Si dos elementos adyacentes tienen algún margen configurado y los dos márgenes se tocan, se mantiene el mayor de los dos y el menor desaparece; esto se llama colapso del margen, y ya lo hemos visto antes.</p> + +<p>Echemos un vistazo a un ejemplo sencillo que explica todo esto:</p> + +<div id="Normal_Flow"> +<pre class="brush: html"><h1>Flujo de los documentos básicos</h1> + +<p>Soy un elemento básico de nivel de bloque. Mis elementos de nivel de bloque adyacentes se encuentran en líneas nuevas debajo de mí.</p> + +<p>Cubrimos por defecto el 100% del ancho de nuestro elemento principal, y somos tan altos como nuestro contenido secundario. Nuestro ancho y alto total es nuestro contenido + área de relleno + ancho/alto del borde.</p> + +<p>Estamos separados por nuestros márgenes. Debido al colapso del margen, estamos separados por el ancho de uno de nuestros márgenes, no por ambos.</p> + +<p>Los elementos en línea <span>como este</span> y <span>este otro</span> se ubican en la misma y la de los nodos de texto adyacentes, mientras hay espacio en la misma línea. Si un elemento en línea desborda, <span>sigue por la línea siguiente, si es posible (como la que contiene este texto)</span>, o simplemente pasa a una línea nueva, como hace esta imagen: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background: rgba(255,84,104,0.3); + border: 2px solid rgb(255,84,104); + padding: 10px; + margin: 10px; +} + +span { + background: white; + border: 1px solid black; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Normal_Flow', '100%', 500) }}</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahora que comprendes el flujo normal y cómo el navegador presenta las cosas por defecto, continúa para comprender cómo cambiar esta pantalla predeterminada para crear el diseño que necesitas.</p> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Introduction", "Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introducción al diseño CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">El flujo normal</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Cuadrícula</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Flotación</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamiento</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Diseño en columnas</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Diseño adaptativo</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Guía para principiantes sobre consultas a media</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Métodos de compaginación heredada</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Compatibilidad con los navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Evaluación del conjunto de de elementos básicos de compaginación </a></li> +</ul> diff --git a/files/es/learn/css/css_layout/grids/index.html b/files/es/learn/css/css_layout/grids/index.html new file mode 100644 index 0000000000..d2632cba2b --- /dev/null +++ b/files/es/learn/css/css_layout/grids/index.html @@ -0,0 +1,696 @@ +--- +title: Cuadrículas +slug: Learn/CSS/CSS_layout/Grids +translation_of: Learn/CSS/CSS_layout/Grids +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout")}}</div> + +<p class="summary">La compaginación en cuadrícula con CSS es un método de diseño de páginas web en dos dimensiones. Te permite distribuir el contenido en filas y columnas, y tiene muchas características que facilitan la creación de diseños complejos. Este artículo te proporciona todo lo que necesitas saber para comenzar con el diseño de páginas web.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conceptos básicos de HTML (véase <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introducción al HTML</a>) y una idea de cómo funciona el CSS (véase <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introducción al CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender los conceptos fundamentales que hay detrás de los métodos de compaginación en cuadrícula y de cómo implementar una compaginación en cuadrícula con CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_la_compaginación_en_cuadrícula">¿Qué es la compaginación en cuadrícula?</h2> + +<p>Una cuadrícula es un conjunto de líneas horizontales y verticales que crean un patrón sobre el que podemos alinear nuestros elementos de diseño. Las cuadrículas nos ayudan a crear diseños de página en que los elementos no saltan ni cambian de ancho cuando nos movemos de una página a otra, y así proporcionan a nuestras páginas web un aspecto más coherente.</p> + +<p>Una cuadrícula en general tiene <strong>columnas</strong>, <strong>filas</strong> y luego espacios entre cada fila y cada columna, conocidos comúnmente como <strong>canales</strong>.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13899/grid.png" style="display: block; height: 553px; margin: 0px auto; width: 1196px;"></p> + +<h2 id="Crear_tu_cuadrícula_con_CSS">Crear tu cuadrícula con CSS</h2> + +<p>Una vez que has decidido qué tipo de cuadrícula necesita tu diseño de página, puedes usar la compaginación en cuadrícula con CSS para crear esa cuadrícula y posicionar elementos en ella. Primero veremos las características básicas de la compaginación en cuadrícula y luego exploraremos cómo crear un método de compaginación de cuadrícula sencilla para tu proyecto.</p> + +<h3 id="Definir_una_cuadrícula">Definir una cuadrícula</h3> + +<p>Como punto de partida, descárgate el <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/grids/0-starting-point.html">archivo de punto de partida</a> y ábrelo en tu editor de texto y tu navegador (también puedes <a href="https://mdn.github.io/learning-area/css/css-layout/grids/0-starting-point.html">verlo en vivo aquí</a>). Hay un ejemplo con un contenedor que tiene algunos elementos hijo. Por defecto, estos se muestran en flujo normal, por lo que las cajas se muestran una debajo de la otra. Vamos a trabajar con este archivo durante la primera parte de este artículo, y vamos a hacer cambios en él para ver cómo se comporta la cuadrícula.</p> + +<p>Para definir una cuadrícula utilizamos el valor <code>grid</code> de la propiedad {{cssxref ("display")}}. Al igual que con el método Flexbox, esto activa la compaginación de cuadrícula y todos los elementos que son hijos directos del contenedor se convierten en elementos de cuadrícula. Añade esto al CSS en tu archivo:</p> + +<pre class="brush: css">.container { + display: grid; +}</pre> + +<p>A diferencia del método Flexbox, los elementos no se ven diferentes inmediatamente. La declaración <code>display: grid</code> te proporciona una cuadrícula de una sola columna, por lo que tus elementos continúan mostrándose uno debajo del otro, como lo hacen en el flujo normal.</p> + +<p>Para ver algo que se parezca más a una cuadrícula, necesitamos añadir columnas a la cuadrícula. Vamos a añadir tres columnas de 200 píxeles. Puedes usar cualquier unidad de longitud o porcentajes para crear estas trazas de columna.</p> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: 200px 200px 200px; +}</pre> + +<p>Añade la segunda declaración a tu regla CSS, luego vuelve a cargar la página y observa que los elementos se reubican uno en cada celda de la cuadrícula que has creado.</p> + +<div id="Grid_1"> +<div class="hidden"> +<h6 id="Ejemplo_sencillo_de_cuadrícula">Ejemplo sencillo de cuadrícula</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} + +.container > div { + border-radius: 5px; + padding: 10px; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); +}</pre> + +<pre class="brush: html"><div class="container"> + <div>Uno</div> + <div>Dos</div> + <div>Tres</div> + <div>Cuatro</div> + <div>Cinco</div> + <div>Seis</div> + <div>Siete</div> +</div> </pre> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: 200px 200px 200px; +} </pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Grid_1', '100%', 400) }}</p> + +<h3 id="Cuadrículas_flexibles_con_la_unidad_fr">Cuadrículas flexibles con la unidad fr</h3> + +<p>Además de crear cuadrículas con longitudes y porcentajes, podemos usar la unidad <code>fr</code> para dimensionar de manera flexible las filas y columnas de la cuadrícula. Esta unidad representa una fracción del espacio disponible en el contenedor de la cuadrícula.</p> + +<p>Cambia tu lista de trazas en la definición siguiente para crear tres trazas <code>1fr</code>.</p> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: 1fr 1fr 1fr; +}</pre> + +<p>Ahora deberías observar que tus trazas son flexibles. La unidad <code>fr</code> distribuye el espacio por proporciones, de modo que puedes dar valores positivos diferentes a sus trazas, por ejemplo, si cambias la definición de la manera siguiente:</p> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: 2fr 1fr 1fr; +}</pre> + +<p>Ahora la primera traza tiene <code>2fr</code> del espacio disponible, y las otras dos trazas tienen <code>1fr</code>, lo que da una primera traza más grande. Puedes mezclar unidades <code>fr</code> y trazas de longitud fija; en tal caso, el espacio que se necesita para las trazas fijas se descuenta del espacio en que se distribuyen las otras trazas.</p> + +<div id="Grid_2"> +<div class="hidden"> +<h6 id="Ejemplo_de_cuadrícula_sencilla_con_unidades_fr">Ejemplo de cuadrícula sencilla con unidades fr</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} + +.container { + display: grid; + grid-template-columns: 2fr 1fr 1fr; +} + +.container > div { + border-radius: 5px; + padding: 10px; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); +}</pre> + +<pre class="brush: html"><div class="container"> + <div>Uno</div> + <div>Dos</div> + <div>Tres</div> + <div>Cuatro</div> + <div>Cinco</div> + <div>Seis</div> + <div>Siete</div> +</div></pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Grid_2', '100%', 400) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: La unidad <code>fr</code> distribuye el espacio <em>disponible</em>, no <em>todo</em> el espacio. Por lo tanto, si una de tus trazas tiene algo grande dentro, habrá menos espacio libre para compartir.</p> +</div> + +<h3 id="Los_espacios_entre_trazas">Los espacios entre trazas</h3> + +<p>Para crear espacios entre trazas, utilizamos las propiedades {{cssxref ("grid-column-gap")}} para los espacios entre columnas, {{cssxref ("grid-row-gap")}} para los espacios entre filas, y {{ cssxref ("grid-gap")}} para configurar ambos a la vez.</p> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + grid-gap: 20px; +}</pre> + +<p>Estos espacios pueden expresarse en cualquier unidad de longitud o en porcentaje, pero no en unidades <code>fr</code>.</p> + +<div id="Grid_3"> +<div class="hidden"> +<h6 id="Ejemplo_2_de_cuadrícula_sencilla_con_unidades_fr">Ejemplo 2 de cuadrícula sencilla con unidades fr</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} + +.container { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + grid-gap: 20px; +} + +.container > div { + border-radius: 5px; + padding: 10px; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); +}</pre> + +<pre class="brush: html"><div class="container"> + <div>Uno</div> + <div>Dos</div> + <div>Tres</div> + <div>Cuatro</div> + <div>Cinco</div> + <div>Seis</div> + <div>Siete</div> +</div> +</pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Grid_3', '100%', 400) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Las propiedades <code>*gap</code> solían tener el prefijo <code>grid-</code>, pero esto se ha cambiado en la especificación, porque la intención es hacerlas compatibles con diversos métodos de diseño. Por el momento, Edge y Firefox admiten las versiones sin prefijo, y las versiones con prefijo se mantienen como un alias, por lo que será seguro usarlas durante algún tiempo. Para quedarte en lo seguro, y que tu código sea más a prueba de balas, puedes duplicar y añadir ambas propiedades.</p> +</div> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: 2fr 1fr 1fr; + grid-gap: 20px; + gap: 20px; +}</pre> + +<h3 id="Repetir_listas_de_trazas">Repetir listas de trazas</h3> + +<p>Puedes repetir todas tus trazas, o una sección de tu lista de trazas, con la notación de repetición. Cambia tu lista de trazas por lo siguiente:</p> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-gap: 20px; +}</pre> + +<p>Ahora vas a tener 3 trazas de <code>1fr</code>, igual que antes. El primer valor que pasas a la función de repetición son las veces que deseas que la lista se repita, mientras que el segundo valor es una lista de trazas, que puede constar de una o más trazas.</p> + +<h3 id="La_cuadrícula_implícita_y_explícita">La cuadrícula implícita y explícita</h3> + +<p>Hasta ahora solo hemos especificado trazas de columna y, sin embargo, también creamos filas para contener nuestro contenido. Este es un ejemplo de una cuadrícula explícita con respecto a una implícita. La cuadrícula explícita es la que creas usando <code>grid-template-columns</code> o <code>grid-template-rows</code>. La cuadrícula implícita se crea cuando el contenido se posiciona fuera de esa cuadrícula, como en nuestras filas. Las cuadrículas explícitas e implícitas son análogas a los ejes principales y transversales del método Flexbox.</p> + +<p>Por defecto, las trazas que se crean en la cuadrícula implícita tienen un tamaño <code>auto</code>, lo que en general significa que son lo bastante grandes para ajustarse a su contenido. Si deseas asignar un tamaño a las trajas de las cuadrícula implícitas, puedes usar las propiedades {{cssxref ("grid-auto-rows")}} y {{cssxref ("grid-auto-columns")}}. Si añades <code>grid-auto-rows</code> con un valor de <code>100px</code> a tu CSS, observa que esas filas que has creado ahora tienen 100 píxeles de alto.</p> + +<div id="Grid_4"> +<div class="hidden"> +<h6 id="Ejemplo_3_de_cuadrícula_sencilla_con_unidades_fr">Ejemplo 3 de cuadrícula sencilla con unidades fr</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} + +.container > div { + border-radius: 5px; + padding: 10px; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); +}</pre> + +<pre class="brush: html"><div class="container"> + <div>Uno</div> + <div>Dos</div> + <div>Tres</div> + <div>Cuatro</div> + <div>Cinco</div> + <div>Seis</div> + <div>Siete</div> +</div></pre> +</div> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-auto-rows: 100px; + grid-gap: 20px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Grid_4', '100%', 400) }}</p> + +<h3 id="La_función_minmax">La función minmax()</h3> + +<p>Nuestras trazas de 100 píxeles de altura no serán muy útiles si en esas trazas añadimos contenido cuya altura sea mayor que 100 píxeles, porque ello causaría un desbordamiento. Puede ser mejor tener trazas cuya altura sea de <em>al menos</em> 100 píxeles y que puedan expandirse si en ellas entra más contenido. Un hecho en realidad básico sobre la web es que nunca sabes qué altura va a tener algo; contenido adicional o tamaños de letra más grandes pueden causar problemas con los diseños que pretendes ser perfectos con todas las dimensiones en píxeles.</p> + +<p>La función <code>minmax</code> permite establecer unos tamaños mínimo y máximo para una traza, por ejemplo, <code>minmax(100px, auto)</code>. El tamaño mínimo es de 100 píxeles, pero el máximo es <code>auto</code>, que se expande para adaptarse al contenido. Prueba a cambiar <code>grid-auto-rows</code> para usar un valor minmax:</p> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: repeat(3, 1fr); + grid-auto-rows: minmax(100px, auto); + grid-gap: 20px; +}</pre> + +<p>Observa que si añades contenido la traza se expande para permitir que se ajuste. Ten en cuenta que la expansión se produce en la dirección de la fila.</p> + +<h3 id="Tantas_columnas_como_quepan">Tantas columnas como quepan</h3> + +<p>Podemos combinar algunas de las cosas que hemos aprendido sobre las listas de trazas, la notación de repetición y la función <code>minmax()</code> para crear un patrón útil. A veces es útil poder pedirle a la cuadrícula que cree tantas columnas como quepan en el contenedor. Para hacer esto establecemos el valor <code>grid-template-columns</code> con la notación <code>repeat()</code>, pero en lugar de pasar un número, pasa la palabra clave <code>auto-fill</code>. Para el segundo parámetro de la función usamos <code>minmax()</code>, con un valor mínimo igual al tamaño mínimo de la traza que nos gustaría tener, y un valor máximo de <code>1fr</code>.</p> + +<p>Prueba esto en tu archivo ahora, con el CSS siguiente:</p> + +<div id="Grid_5"> +<div class="hidden"> +<h6 id="Tantas_columnas_como_quepan_2">Tantas columnas como quepan</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} + +.container > div { + border-radius: 5px; + padding: 10px; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); +}</pre> + +<pre class="brush: html"><div class="container"> + <div>Uno</div> + <div>Dos</div> + <div>Tres</div> + <div>Cuatro</div> + <div>Cinco</div> + <div>Seis</div> + <div>Siete</div> +</div></pre> +</div> + +<pre class="brush: css">.container { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + grid-auto-rows: minmax(100px, auto); + grid-gap: 20px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Grid_5', '100%', 400) }}</p> + +<p>Esto funciona porque la cuadrícula crea tantas columnas de 200 píxeles como caben en el contenedor, luego comparte el espacio restante entre todas las columnas: el máximo es 1fr, que como sabemos, distribuye el espacio de manera uniforme entre las trazas.</p> + +<h2 id="Posicionamiento_sobre_las_líneas_de_base">Posicionamiento sobre las líneas de base</h2> + +<p>Ahora pasamos de crear una cuadrícula a colocar cosas en la cuadrícula. Nuestra cuadrícula siempre tiene líneas; estas líneas comienzan en 1 y se relacionan con el modo de escritura del documento. Por lo tanto, en español, la línea de columna 1 es la de la izquierda de la cuadrícula y la línea de fila 1 es la de la parte superior. En una columna arábiga, la línea 1 estaría en el lado derecho, ya que el árabe se escribe de derecha a izquierda.</p> + +<p>Podemos posicionar los elementos de acuerdo con estas líneas si especificamos las líneas de inicio y final. Hacemos esto con las propiedades siguientes:</p> + +<ul> + <li>{{cssxref("grid-column-start")}}</li> + <li>{{cssxref("grid-column-end")}}</li> + <li>{{cssxref("grid-row-start")}}</li> + <li>{{cssxref("grid-row-end")}}</li> +</ul> + +<p>Todas estas propiedades pueden tener un número de línea como valor. También puedes usar las propiedades abreviadas:</p> + +<ul> + <li>{{cssxref("grid-column")}}</li> + <li>{{cssxref("grid-row")}}</li> +</ul> + +<p>Estas te permiten especificar a la vez las líneas de inicio y final, separadas por un carácter de barra diagonal: <code>/</code>.</p> + +<p>Descarga este <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/grids/8-placement-starting-point.html">archivo de punto de partida</a> o <a href="https://mdn.github.io/learning-area/css/css-layout/grids/8-placement-starting-point.html">míralo en vivo aquí</a>. Ya hay una cuadrícula definida y un elemento sencillo esbozado. Puedes observar que el posicionamiento automático coloca un elemento en cada celda de la cuadrícula que hemos creado.</p> + +<p>Nosotros vamos a utilizar en lugar de ello las líneas de cuadrícula para posicionar sobre la cuadrícula todos los elementos de nuestro sitio web. Añade al final de tu código CSS las reglas siguientes:</p> + +<pre class="brush: css">header { + grid-column: 1 / 3; + grid-row: 1; +} + +article { + grid-column: 2; + grid-row: 2; +} + +aside { + grid-column: 1; + grid-row: 2; +} + +footer { + grid-column: 1 / 3; + grid-row: 3; +}</pre> + +<div id="Grid_6"> +<div class="hidden"> +<h6 id="Posicionamiento_sobre_las_líneas_de_base_2">Posicionamiento sobre las líneas de base</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; + } + + .container { + display: grid; + grid-template-columns: 1fr 3fr; + grid-gap: 20px; + } +header { + grid-column: 1 / 3; + grid-row: 1; +} + +article { + grid-column: 2; + grid-row: 2; +} + +aside { + grid-column: 1; + grid-row: 2; +} + +footer { + grid-column: 1 / 3; + grid-row: 3; +} + +header, +footer { + border-radius: 5px; + padding: 10px; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); +} + +aside { + border-right: 1px solid #999; +}</pre> + +<pre class="brush: html"><div class="container"> + <header>Este es mi blog</header> + <article> + <h1>Mi artículo</h1> + <p>Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + </article> + <aside> + <h2>Otras cosas</h2> + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est.</p> + </aside> + <footer>Contáctame: me@mysite.com</footer> +</div></pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Grid_6', '100%', 400) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: también puedes usar el valor <code>-1</code> para señalar la columna del final o la fila del final, y contar hacia atrás desde el final con valores negativos. Sin embargo, esto solo funciona con la cuadrícula explícita. El valor <code>-1</code> no señala la línea del final de la cuadrícula implícita.</p> +</div> + +<h2 id="Posicionamiento_con_grid-template-areas">Posicionamiento con grid-template-areas</h2> + +<p>Una forma alternativa de posicionar elementos en tu cuadrícula es usar la propiedad {{cssxref ("grid-template-areas")}} y asignar un nombre a los diversos elementos de tu diseño.</p> + +<p>Elimina el posicionamiento sobre las líneas de base del último ejemplo (o vuelve a descargar el archivo para tener un punto de partida nuevo) y añade el código CSS siguiente.</p> + +<pre class="brush: css">.container { + display: grid; + grid-template-areas: + "header header" + "sidebar content" + "footer footer"; + grid-template-columns: 1fr 3fr; + grid-gap: 20px; +} + +header { + grid-area: header; +} + +article { + grid-area: content; +} + +aside { + grid-area: sidebar; +} + +footer { + grid-area: footer; +}</pre> + +<p>Vuelve a cargar la página y observa que tus elementos se han colocado como antes ¡sin necesidad de usar números de línea!</p> + +<div id="Grid_7"> +<div class="hidden"> +<h6 id="Posicionamiento_sobre_las_líneas_de_base_3">Posicionamiento sobre las líneas de base 3</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} + +header, +footer { + border-radius: 5px; + padding: 10px; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); +} + +aside { + border-right: 1px solid #999; +} + +.container { + display: grid; + grid-template-areas: + "header header" + "sidebar content" + "footer footer"; + grid-template-columns: 1fr 3fr; + grid-gap: 20px; +} + +header { + grid-area: header; +} + +article { + grid-area: content; +} + +aside { + grid-area: sidebar; +} + +footer { + grid-area: footer; +}</pre> + +<pre class="brush: html"><div class="container"> + <header>Este es mi blog</header> + <article> + <h1>Mi artículo</h1> + <p>Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + </article> + <aside> <h2>Otras cosas</h2> + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est.</p> + </aside> + <footer>Contáctame: me@mysite.com</footer> +</div></pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Grid_7', '100%', 400) }}</p> + +<p>Las reglas para <code>grid-template-areas</code> son las siguientes:</p> + +<ul> + <li>Hay que tener todas las celdas de la cuadrícula llenas.</li> + <li>Para abarcar el ancho de dos celdas, repite el nombre.</li> + <li>Para dejar una celda vacía, utiliza un punto: <code>.</code>.</li> + <li>Las áreas han de ser rectangulares; por ejemplo, no puedes haber un área en forma de L.</li> + <li>Las áreas no pueden repetirse en lugares diferentes.</li> +</ul> + +<p>Puedes jugar con nuestro diseño, por ejemplo, cambiar el pie de página para que esté solo debajo del contenido, y la barra lateral para abarcar todo. Esta manera de describir un diseño de página es muy adecuada porque resulta obvio a partir del CSS qué sucede exactamente.</p> + +<h2 id="Una_cuadrícula_CSS_formato_de_cuadrícula">Una cuadrícula CSS, formato de cuadrícula</h2> + +<p>Los «formatos» de cuadrícula tienden a basarse en cuadrículas de 12 o 16 columnas, y con las cuadrículas CSS no necesitas ninguna herramienta de terceros para proporcionarte dicho formato, porque ya está en la especificación.</p> + +<p>Descárgate el <a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/grids/11-grid-system-starting-point.html">archivo de punto de partida</a>. Contiene un contenedor con una cuadrícula de 12 columnas definida y el mismo código de marcado que usamos en los dos ejemplos anteriores. Ahora podemos usar el posicionamiento sobre las líneas de base para colocar nuestro contenido en la cuadrícula de 12 columnas.</p> + +<pre class="brush: css">header { + grid-column: 1 / 13; + grid-row: 1; +} + +article { + grid-column: 4 / 13; + grid-row: 2; +} + +aside { + grid-column: 1 / 4; + grid-row: 2; +} + +footer { + grid-column: 1 / 13; + grid-row: 3; +}</pre> + +<div id="Grid_8"> +<div class="hidden"> +<h6 id="Un_método_de_compaginación_en_cuadrícula_con_CSS">Un método de compaginación en cuadrícula con CSS</h6> + +<pre class="brush: css">body { + width: 90%; + max-width: 900px; + margin: 2em auto; + font: .9em/1.2 Arial, Helvetica, sans-serif; +} + +.container { + display: grid; + grid-template-columns: repeat(12, minmax(0,1fr)); + grid-gap: 20px; +} + +header { + grid-column: 1 / 13; + grid-row: 1; +} + +article { + grid-column: 4 / 13; + grid-row: 2; +} + +aside { + grid-column: 1 / 4; + grid-row: 2; +} + +footer { + grid-column: 1 / 13; + grid-row: 3; +} + +header, +footer { + border-radius: 5px; + padding: 10px; + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); +} + +aside { + border-right: 1px solid #999; +}</pre> + +<pre class="brush: html"><div class="container"> + <header>Este es mi blog</header> + <article> + <h1>Mi artículo</h1> + <p>Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + </article> + <aside> <h2>Otras cosas</h2> + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est.</p> + </aside> + <footer>Contáctame: me@mysite.com</footer> +</div></pre> +</div> +</div> + +<p>{{ EmbedLiveSample('Grid_8', '100%', 400) }}</p> + +<p>Si usas el <a href="/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts">inspector de cuadrícula de Firefox</a> para ver una superposición de las líneas de cuadrícula sobre tu diseño, puedes observar cómo funciona nuestra cuadrícula de 12 columnas.</p> + +<p><img alt="Una superposición de la cuadrícula de 12 columnas de nuestro diseño de página." src="https://mdn.mozillademos.org/files/16045/learn-grids-inspector.png" style="height: 1026px; width: 2028px;"></p> + +<h2 id="¡Pon_a_prueba_tus_conocimientos!">¡Pon a prueba tus conocimientos!</h2> + +<p>Has llegado al final de este artículo, pero ¿recuerdas la información más importante? Encontrarás test de prueba que te permitirán verificar que has asimilado esta información antes de continuar en: <a href="/en-US/docs/Learn/CSS/CSS_layout/Grid_skills">Pon a prueba tus conocimientos: Cuadrículas</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En esta descripción general, hemos recorrido las características principales del diseño páginas web con cuadrícula CSS. Deberías poder comenzar a usarlo en tus diseños. Para profundizar en la especificación, lee nuestras guías para el diseño de página con cuadrícula, que puedes encontrar a continuación.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="/en-US/docs/Web/CSS/CSS_Grid_Layout#Guides">Guías de cuadrícula CSS</a></li> + <li><a href="/en-US/docs/Tools/Page_Inspector/How_to/Examine_grid_layouts">Inspector de cuadrícula CSS: Examinar diseños de cuadrícula</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Flexbox", "Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introducción al diseño CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Flujo normal</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Cuadrícula</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Flotación</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamiento</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Diseño en columnas</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Diseño adaptativo</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Guía para principiantes sobre consultas a media</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Métodos de compaginación heredados</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Compatibilidad con navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Evaluación del conjunto de elementos básicos de compaginación</a></li> +</ul> diff --git a/files/es/learn/css/css_layout/index.html b/files/es/learn/css/css_layout/index.html new file mode 100644 index 0000000000..afa1b0f9a0 --- /dev/null +++ b/files/es/learn/css/css_layout/index.html @@ -0,0 +1,87 @@ +--- +title: Diseño CSS +slug: Learn/CSS/CSS_layout +tags: + - Aprender + - CSS + - Floating + - Grids + - Guía + - Landing + - Layout + - Module + - Multiple column + - Positioning + - Principiante + - TopicStub + - flexbox + - float +translation_of: Learn/CSS/CSS_layout +--- +<div>{{draft}}</div> + +<div>{{LearnSidebar}}</div> + +<p class="summary">Llegados a este punto, hemos examinado los fundamentos básicos de CSS: cómo dar estilo al texto y cómo manipular las cajas que incluyen tu contenido. Llegó el momento de explorar cómo colocar tus cajas en el lugar que elijas con respecto a la ventana principal y el resto de cajas. Hemos cubierto ya los prerrequisitos necesarios, así que vamos a sumergirnos en la maquetación CSS, fijándonos en diferentes configuraciones de visualización, métodos de maquetación tradicionales que implican <em>floats </em>y posicionamiento, así como a nuevas herramientas de maquetación en voga, como <em>flexbox</em>.</p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Antes de comenzar este módulo, ya deberías:</p> + +<ol> + <li>Estar familiarizado con HTML, como se expone en el módulo <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introduction to HTML</a>.</li> + <li>Sentirte cómodo con los fundamentos de CSS, que se discuten en <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introduction to CSS</a>.</li> + <li>Entender como diseñar cajas <a href="/en-US/docs/Learn/CSS/Styling_boxes">style boxes</a>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si estás trabajando en un dispositivo donde no tengas la posibilidad de crear tus propios archivos, puedes probar la mayoría de los ejemplos de código en un programa online como <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<p>Estos artículos te proporcionarán instrucciones sobre las herramientas y técnicas básicas de maquetación disponibles en CSS.</p> + +<dl> + <dt><a href="/es/docs/Learn/CSS/CSS_layout/Introduction">Introducción a la maquetación CSS</a></dt> + <dd>En este artículo repasaremos algunas de las características de la maquetación con CSS que ya hemos tratado en módulos previos, como los diferentes valores de {{cssxref("display")}} ; e introduciremos algunos de los conceptos que estudiaremos a lo largo del módulo.</dd> + <dt><a href="https://wiki.developer.mozilla.org/es/docs/Learn/CSS/CSS_layout/Flujo_normal">Normal flow</a></dt> + <dd>Los elementos en las páginas web se presentan de acuerdo con el <em>flujo normal, </em>hasta que hacemos algo que cambie eso. Este artículo explica las bases del flujo normal para aprender como cambiarlo.</dd> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></dt> + <dd><a href="/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_flexbox_to_lay_out_web_applications">Flexbox</a> es una muy reciente tecnología que, soportada ya por numerosos navegadores, está lista para su uso generalizado. Flexbox proporciona las herramientas necesarias para crear rápidamente maquetaciones flexibles y complejas, así como otras funcionalidades que tradicionalmente eran de difícil implementación con CSS. Este artículo explica su funcionamiento básico.</dd> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grids</a></dt> + <dd>Los sistemas de cuadrícula son otra funcionalidad muy utilizada para la maquetación CSS, que tiende a ser implementada mediante <em>floats</em> u otras funciones de maquetación. Visualizas tu maquetación como un número fijo de columnas donde vas incluyendo tu contenido. En este artículo exploraremos la idea básica detrás de un sistema de cuadrícula, y terminaremos experimentando con CSS Grid, una incipiente nueva característica que permite diseñar una cuadricula Web con gran facilidad</dd> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></dt> + <dd>Inicialmente utilizado para imágenes flotantes dentro de bloques de texto, la propiedad {{cssxref("float")}} se ha convertido en una de las herramientas más utilizadas para crear maquetaciones de varias columnas en páginas web. Con la venida de Flexbox y Grid se ha regresado a su propósito original, como lo explica este artículo.</dd> + <dt><a href="https://wiki.developer.mozilla.org/es/docs/Learn/CSS/CSS_layout/Positioning">Posicionamiento</a></dt> + <dd>El posicionamiento te permite sacar elementos del flujo normal de maquetación del documento para hacer que se comporten de manera diferente, p.ej: colocando unos encima de otros, o fijándolos a un lugar de la ventana principal. Este artículo explica los diferentes valores para {{cssxref("position")}} y cómo utilizarlos.</dd> + <dt><a href="https://developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Practical_positioning_examples">Ejemplos prácticos de posicionamiento</a></dt> + <dd>Una vez cubiertas las nociones básicas de posicionamiento en el artículo anterior, vamos ahora a construir un par de ejemplos reales, para explicar las cosas que puedes hacer con el posicionamiento.</dd> + <dt><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Diseño Multi-columna</a></dt> + <dd>El diseño multi-columna te proporciona un método de maquetación de contenido en columnas, como lo podrías ver en un periódico. Este artículo explica como usar esta característica.</dd> + <dt><a href="https://wiki.developer.mozilla.org/es/docs/Learn/CSS/CSS_layout/Diseño_receptivo">Responsive design</a></dt> + <dd>A medida que han aparecido diversos tamaños de pantalla en dispositivos habilitados para la web, apareció un conjunto de practicas que permiten a las páginas web alterar su diseño y apariencia para adaptarse a diferentes anchos de pantalla, resoluciones, etc.Este se conoce como Responsive design (RWD) y es una idea que cambió la forma en que diseñamos páginas web multi-dispositivos, y en este artículo te ayudaremos a entender las principales técnicas que necesitas saber para dominarlo.</dd> + <dt><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Guía de consulta de medios para principiantes</a></dt> + <dd><strong>CSS Media Query </strong>te proporciona una forma de aplicar CSS solo cuando el entorno del navegador y el dispositivo coincide con las reglas que especificaste, por ejemplo "la ventana principal es más ancha de 480 pixels". Las consultas de medios son una parte clave del responsive web design, ya que te permiten crear diferentes diseños dependiendo del tamaño de la ventana principal, así como también puede ser usado para detectar otras cosas acerca del entorno en donde tu página web se está ejecutando, por ejemplo si el usuario está usando una pantalla táctil en lugar de un ratón. En esta guía, aprenderás primero acerca de la sintaxis usada en las consultas de medios, y luego pasar a usarlos en un ejemplo donde se muestra cómo un diseño simple puede hacerse responsive.</dd> + <dt><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Métodos de diseño heredados</a></dt> + <dd>Los sistemas Grid son una característica muy común usada en el diseño CSS, y antes del diseño Grid CSS, tendían a ser implementados usando floats u otras características de diseño. Imagina tu diseño como un conjunto de números de columnas (p.ej. 4, 5 o 12), y luego acomoda tus columnas de contenido dentro de esas columnas imaginarias. En este artículo vamos a explorar cómo funcionan estos métodos para que entiendas como eran usados si trabajas en un proyecto más antiguo. </dd> + <dt><a href="https://wiki.developer.mozilla.org/es/docs/Learn/CSS/CSS_layout/Soporte_a_navegadores_antiguos">Soporte a navegadores antiguos</a></dt> + <dd>En este modulo recomendamos usar Flexbox y Grid como principal método de diseño. Siempre habrán personas que visiten tu página web desde navegadores antiguos, o navegadores que no soportan los métodos que usaste. Este siempre ha sido el caso en la web: a medida que se desarrollan nuevas características, los distintos navegadores priorizan diferentes cosas. Este artículo explica como usar técnicas modernas para la web sin dejar por fuera a los usuarios de tecnologías antiguas. </dd> +</dl> + +<h2 id="Ejercicios">Ejercicios</h2> + +<p>Los siguientes ejercicios comprobarán tu habilidad para maquetar páginas web con CSS.</p> + +<dl> + <dt>Creando una maquetación de varias columnas flexibles</dt> + <dd>Este ejercicio comprobará tu habilidad par crear una maquetación multi-columna, con alguna que otra característica interesante.</dd> + <dt>Creando un <em>widget</em> fijo de control</dt> + <dd>Este ejercicio pone a prueba tu entendimiento sobre el posicionamiento, proponiéndote crear un <em>widget</em> de control con posición fija, que permitirá al usuario acceder a los controles de una aplicación Web, independientemente de dónde se hubiera desplazado en la página.</dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/Learn/CSS/Basics/Layout">https://developer.mozilla.org/en-US/Learn/CSS/Basics/Layout</a></li> +</ul> diff --git a/files/es/learn/css/css_layout/introducción/index.html b/files/es/learn/css/css_layout/introducción/index.html new file mode 100644 index 0000000000..2f409d97c3 --- /dev/null +++ b/files/es/learn/css/css_layout/introducción/index.html @@ -0,0 +1,701 @@ +--- +title: Introducción al diseño en CSS +slug: Learn/CSS/CSS_layout/Introducción +translation_of: Learn/CSS/CSS_layout/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout")}}</div> + +<p class="summary">Este artículo resumirá algunas de las características de diseño de páginas web con CSS que ya hemos mencionado en módulos anteriores, como los diferentes valores de {{cssxref ("display")}}, e introducirá algunos de los conceptos que vamos a tratar en este módulo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Proporcionar una visión general de las técnicas de diseño de páginas web con CSS. Cada técnica se puede aprender con mayor detalle en tutoriales posteriores.</td> + </tr> + </tbody> +</table> + +<p>Las técnicas de diseño de páginas web con CSS nos permiten controlar dónde se ubican los elementos que están contenidos en una página web en relación con su posición predeterminada en el flujo de diseño normal, así como el resto de elementos a su alrededor, su contenedor principal o la vista/ventana principal. Las técnicas de diseño de páginas web que trataremos con más detalle en este módulo son:</p> + +<ul> + <li>Flujo normal</li> + <li>La propiedad {{cssxref ("display")}}</li> + <li>Flexbox</li> + <li>Grid</li> + <li>Floats</li> + <li>Posicionamiento</li> + <li>Diseño de tablas</li> + <li>Diseño a varias columnas</li> +</ul> + +<p>Cada técnica tiene sus usos, ventajas y desventajas, y ninguna técnica está diseñada para usarse de forma aislada. Si entiendes para qué se ha diseñado cada método, te será fácil comprender cuál es la mejor herramienta de diseño para cada tarea.</p> + +<h2 id="Flujo_normal">Flujo normal</h2> + +<p>El flujo normal es el modo como el navegador presenta las páginas HTML de forma predeterminada cuando no haces nada para controlar el diseño de página. Echemos un vistazo rápido a un ejemplo HTML:</p> + +<pre class="brush: html notranslate"><p>Amo a mi gato.</p> + +<ul> + <li>Comprar comida para gatos</li> + <li>Ejercicio</li> + <li>Anímate amigo</li> +</ul> + +<p>¡Fin!</p></pre> + +<p>Por defecto, el navegador mostrará este código de la manera siguiente:</p> + +<p>{{ EmbedLiveSample('Normal_flow', '100%', 200) }}</p> + +<p>Observa aquí cómo se muestra el HTML en el orden exacto en que aparece en el código fuente, con los elementos uno debajo del otro: el primer párrafo, seguido de la lista desordenada, y a continuación el segundo párrafo.</p> + +<p>Los elementos que aparecen uno debajo del otro se describen como <em>elementos de bloque</em>, en contraposición con los <em>elementos de línea</em>, que aparecen uno al lado del otro, como las palabras de un párrafo.</p> + +<div class="note"> +<p><strong>Nota</strong>: La dirección en la que se presentan los contenidos de un elemento de bloque se describe como dirección de los bloques. La dirección de los bloques va de arriba a abajo en un idioma como el español, cuyo modo de escritura es horizontal. Sería horizontal en cualquier idioma con un modo de escritura vertical, como el japonés. Correspondientemente, la dirección de línea es la dirección en la que los contenidos de línea (por ejemplo, una frase) se disponen.</p> +</div> + +<p>Cuando usas CSS para crear un diseño de página web, alejas los elementos del flujo normal, pero para muchos de los elementos de tu página, el flujo normal proporciona exactamente el diseño que necesitas. Por esta razón resulta tan importante comenzar con un documento HTML bien estructurado, porque te permite trabajar ya con la forma en que las cosas se presentan por defecto, en lugar de tener que luchar contra ello.</p> + +<p>Los métodos que permiten cambiar la disposición de los elementos en CSS son los siguientes:</p> + +<ul> + <li><strong>La propiedad {{cssxref ("display")}}</strong>: los valores estándar como <code>block</code>, <code>inline</code> o <code>inline-block</code> pueden cambiar el comportamiento de los elementos en el flujo normal (consulta <a href="/es/docs/Learn/CSS/Building_blocks/El_modelo_de_caja">Tipos de cajas en CSS</a> para obtener más información). Luego hay métodos de diseño completos que se activan con un valor <code>display</code>, por ejemplo <a href="/es/docs/Learn/CSS/CSS_layout/Grids">CSS Grid</a> y <a href="/es/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a>.</li> + <li><strong>Floats</strong>: la aplicación de un valor {{cssxref ("float")}} como <code>left</code> puede hacer que los elementos de nivel de bloque rodeen el elemento por uno de sus lados, como la forma en que las imágenes a veces tienen texto flotando a su alrededor en los diseños de algunas revistas.</li> + <li><strong>La propiedad {{cssxref ("position")}}</strong>: permite controlar con precisión la ubicación de las cajas dentro de otras cajas. El posicionamiento estático es el valor predeterminado en el flujo normal, pero puede hacer que los elementos se distribuyan de manera diferente si se utilizan otros valores, por ejemplo, pueden estar siempre fijados a la parte superior izquierda de la ventana del navegador.</li> + <li><strong>Diseño de tablas</strong>: se pueden usar las características que sirven para diseñar las partes de una tabla HTML en elementos que no son de tabla con <code>display: table</code> y las propiedades asociadas.</li> + <li><strong>Diseño en varias columnas</strong>: las propiedades de <a href="/es/docs/Web/CSS/Columnas_CSS">diseño en varias columnas</a> permiten distribuir el contenido de un bloque en columnas, como en el caso de un periódico.</li> +</ul> + +<h2 id="La_propiedad_display">La propiedad display</h2> + +<p>Los métodos principales para lograr el diseño de páginas web con CSS son todos los valores de la propiedad <code>display</code>. Esta propiedad permite cambiar la forma predeterminada en que algo se muestra. Todo en flujo normal tiene un valor de <code>display</code>, utilizado como la forma como se comportan por defecto los elementos en los que están configurados. Por ejemplo, el hecho de que los párrafos en español se muestran uno debajo del otro se debe a que presentan la configuración <code>display: block</code>. Si creas un enlace alrededor de un texto dentro de un párrafo, ese enlace permanece en línea con el resto del texto y no se divide al pasar a una línea nueva. Esto se debe a que el elemento {{htmlelement ("a")}} es por defecto <code>display: inline</code>.</p> + +<p>Puedes cambiar este comportamiento predeterminado de visualización (<code>display</code>). Por ejemplo, el elemento {{htmlelement ("li")}} es <code>display: block</code> de forma predeterminada, lo que significa que los elementos de la lista se muestran uno debajo del otro en nuestro documento en español. Si cambiamos el valor de visualización a <code>inline</code>, ahora se muestran uno al lado del otro, como lo harían las palabras de una frase. El hecho de que puedas cambiar el valor de <code>display</code> de cualquier elemento significa que puedes elegir elementos HTML por su significado semántico, sin preocuparte por cómo se verán. La forma en que se ven es algo que puedes cambiar.</p> + +<p>Además de poder cambiar la presentación predeterminada de un elemento <code>block</code> a un elemento <code>inline</code> y viceversa, hay algunos métodos de diseño de página más poderosos que se inician como un valor de <code>display</code>. Sin embargo, cuando los uses, en general vas a necesitar propiedades adicionales. Los dos valores más importantes para nuestros propósitos cuando hablamos del diseño de páginas web son <code>display: flex</code> y <code>display: grid</code>.</p> + +<h2 id="Flexbox">Flexbox</h2> + +<p>Flexbox es el nombre corto del <a href="/es/docs/Web/CSS/CSS_Flexible_Box_Layout">módulo de diseño de cajas flexibles</a>, pensado para facilitarnos la distribución de las cosas en una dimensión, ya sea como una fila o como una columna. Para usar el método Flexbox, aplica <code>display: flex</code> al elemento padre de los elementos que deseas distribuir; todos sus elementos hijo directos se convierten en elementos flexibles. Vamos a verlo en un ejemplo sencillo.</p> + +<p>El marcado HTML siguiente nos proporciona un elemento contenedor con una clase <code>wrapper</code> dentro del cual hay tres elementos {{htmlelement ("div")}}. Por defecto, estos elementos se mostrarían como elementos de bloque, uno debajo del otro, en nuestro documento en español.</p> + +<p>Sin embargo, si añadimos <code>display: flex</code> al elemento padre, los tres elementos se organizan en columnas. Esto se debe a que se convierten en <em>elementos flexibles</em> y se ven afectados por algunos valores iniciales que el método Flexbox establece en el contenedor flexible. Se muestran en una fila porque el valor inicial de {{cssxref ("flex-direction")}} establecido en su elemento padre es <code>row</code>. Todos parecen expandirse hasta la altura del elemento de más altura, porque el valor inicial de la propiedad {{cssxref ("align-items")}} establecida en su elemento primario es <code>stretch</code>. Esto significa que los artículos se expanden hasta la altura del contenedor flexible, que en este caso está definida por el artículo de mayor altura. Todos los artículos se alinean al comienzo del contenedor y dejan el espacio que sobra al final de la fila.</p> + +<div id="Flex_1"> +<div class="hidden"> +<h6 id="Ejemplo_Flexbox_1">Ejemplo Flexbox 1</h6> + +<pre class="brush: css notranslate">* {box-sizing: border-box;} + +.wrapper > div { + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} + </pre> +</div> + +<pre class="brush: css notranslate">.wrapper { + display: flex; +} +</pre> + +<pre class="brush: html notranslate"><div class="wrapper"> + <div class="box1">Uno</div> + <div class="box2">Dos</div> + <div class="box3">Tres</div> +</div> +</pre> +</div> + +<p>{{ EmbedLiveSample('Flex_1', '300', '200') }}</p> + +<p>Además de las propiedades anteriores, que pueden aplicarse a contenedores flexibles, también hay propiedades que pueden aplicarse a los elementos flexibles. Estas propiedades, entre otras cosas, pueden cambiar el comportamiento de estos elementos flexibles y permitirles expandirse y contraerse para adaptarse al espacio disponible.</p> + +<p>Como un ejemplo sencillo de esto podemos añadir la propiedad {{cssxref ("flex")}} a todos nuestros elementos secundarios, con un valor de <code>1</code>. Esto hará que todos los elementos crezcan y llenen el contenedor, en lugar de dejar espacio al final. Si hay más espacio, los artículos se ensancharán; si hay menos espacio, se volverán más estrechos. Además, si añades al código otro elemento, todos los elementos se volverán más pequeños para dejarle espacio; ajustarán el tamaño para ocupar la misma cantidad de espacio, cualquiera que sea.</p> + +<div id="Flex_2"> +<div class="hidden"> +<h6 id="Ejemplo_Flexbox_2">Ejemplo Flexbox 2</h6> + +<pre class="brush: css notranslate">* {box-sizing: border-box;} + + .wrapper > div { + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; + }</pre> +</div> + +<pre class="brush: css notranslate">.wrapper { + display: flex; +} + +.wrapper > div { + flex: 1; +} +</pre> + +<pre class="brush: html notranslate"><div class="wrapper"> + <div class="box1">Uno</div> + <div class="box2">Dos</div> + <div class="box3">Tres</div> +</div> +</pre> +</div> + +<p>{{ EmbedLiveSample('Flex_2', '300', '200') }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Esta ha sido una breve introducción de lo que permite el método Flexbox. Para obtener más información, consulta nuestro artículo sobre <a href="/es/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a>.</p> +</div> + +<h2 id="Diseño_de_cuadrícula">Diseño de cuadrícula</h2> + +<p>Mientras que el método Flexbox está pensado para distribuir elementos unidimensionalmente, el diseño de cuadrícula está diseñado para distribuir elementos en dos dimensiones: alinear elementos en filas y columnas.</p> + +<p>Una vez más, puedes activar el diseño de páginas web en cuadrícula con un valor de visualización específico: <code>display: grid</code>. El ejemplo siguiente utiliza un marcado similar al del ejemplo del método Flexbox, con un contenedor y algunos elementos secundarios. Además de usar <code>display: grid</code>, también definimos algunos tramos de filas y columnas en el elemento padre con las propiedades {{cssxref("grid-template-rows")}} y {{cssxref("grid-template-columns")}}. Hemos definido tres columnas, cada una de <code>1fr</code>, y dos filas de <code>100px</code>. No necesitamos poner ninguna regla sobre los elementos secundarios porque se colocan automáticamente en las celdas que nuestra cuadrícula ha creado.</p> + +<div id="Grid_1"> +<div class="hidden"> +<h6 id="Ejemplo_de_cuadrícula_1">Ejemplo de cuadrícula 1</h6> + +<pre class="brush: css notranslate">* {box-sizing: border-box;} + + .wrapper > div { + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; + }</pre> +</div> + +<pre class="brush: css notranslate">.wrapper { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 100px 100px; + grid-gap: 10px; +} +</pre> + +<pre class="brush: html notranslate"><div class="wrapper"> + <div class="box1">Uno</div> + <div class="box2">Dos</div> + <div class="box3">Tres</div> + <div class="box4">Cuatro</div> + <div class="box5">Cinco</div> + <div class="box6">Seis</div> +</div> +</pre> +</div> + +<p>{{ EmbedLiveSample('Grid_1', '300', '330') }}</p> + +<p>Cuando ya tienes una cuadrícula, se puede colocar tus elementos en ella explícitamente en lugar de confiar en el comportamiento de colocación automática que hemos visto arriba. En el segundo ejemplo, hemos definido la misma cuadrícula, pero esta vez con tres elementos secundarios. Hemos establecido la línea de inicio y final de cada elemento con las propiedades {{cssxref ("grid-column")}} y {{cssxref ("grid-row")}}. Esto hace que los elementos abarquen varios tramos.</p> + +<div id="Grid_2"> +<div class="hidden"> +<h6 id="Ejemplo_de_cuadrícula_2">Ejemplo de cuadrícula 2</h6> + +<pre class="brush: css notranslate">* {box-sizing: border-box;} + + .wrapper > div { + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; + }</pre> +</div> + +<pre class="brush: css notranslate">.wrapper { + display: grid; + grid-template-columns: 1fr 1fr 1fr; + grid-template-rows: 100px 100px; + grid-gap: 10px; +} + +.box1 { + grid-column: 2 / 4; + grid-row: 1; +} + +.box2 { + grid-column: 1; + grid-row: 1 / 3; +} + +.box3 { + grid-row: 2; + grid-column: 3; +} +</pre> + +<pre class="brush: html notranslate"><div class="wrapper"> + <div class="box1">Uno</div> + <div class="box2">Dos</div> + <div class="box3">Tres</div> +</div> +</pre> +</div> + +<p>{{ EmbedLiveSample('Grid_2', '300', '330') }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Estos dos ejemplos son solo una pequeña parte del poder del diseño de cuadrículas; para obtener más información, consulta nuestro artículo sobre <a href="/es/docs/Learn/CSS/CSS_layout/Grids">Diseñar cuadrículas</a>.</p> +</div> + +<p>El resto de esta guía expone otros métodos de diseño de páginas web que son menos importantes para las estructuras principales de diseño de tu página web, pero que pueden serte de ayuda para tareas específicas. Si entiendes la naturaleza de cada una de las tareas de diseño de una página web, vas a descubrir enseguida que a menudo vas a ser capaz de discernir qué tipo de diseño se adapta mejor a cada componente de tu diseño particular.</p> + +<h2 id="Floats">Floats</h2> + +<p>El método de flotación de un elemento cambia el comportamiento de ese elemento y de los elementos de nivel de bloque que lo siguen en el flujo normal. El elemento es desplazado hacia la izquierda o hacia la derecha y es eliminado del flujo normal, y el contenido circundante flota alrededor de este elemento.</p> + +<p>La propiedad {{cssxref ("float")}} tiene cuatro valores posibles:</p> + +<ul> + <li><code>left</code>: establece la flotación a la izquierda del elemento.</li> + <li><code>right</code>: establece la flotación a la derecha del elemento.</li> + <li><code>none</code>: especifica que no hay flotación en absoluto. Este es el valor predeterminado.</li> + <li><code>inherit</code>: especifica que el valor de la propiedad <code>float</code> debe heredarse del elemento padre.</li> +</ul> + +<p>En el ejemplo siguiente, establecemos una flotación a la izquierda para un elemento <code><div></code> y le damos un {{cssxref ("margin")}} a la derecha para mantener el texto alejado del elemento. Esto nos da el efecto del texto envuelto alrededor de ese cuadro, y es la mayor parte de lo que necesitas saber sobre la flotación, tal como se utiliza en el diseño web moderno.</p> + +<div id="Float_1"> +<div class="hidden"> +<h6 id="Ejemplo_de_flotación">Ejemplo de flotación</h6> + +<pre class="brush: css notranslate">body { + width: 90%; + max-width: 900px; + margin: 0 auto; +} + +p { + line-height: 2; + word-spacing: 0.1rem; +} + +.box { + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + border-radius: 5px; +} +</pre> +</div> + +<pre class="brush: html notranslate"><h1>Ejemplo sencillo de flotación</h1> + +<div class="box">Float</div> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +</pre> + +<pre class="brush: css notranslate"> +.box { + float: left; + width: 150px; + height: 150px; + margin-right: 30px; +} +</pre> +</div> + +<p>{{ EmbedLiveSample('Float_1', '100%', 600) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: El método de flotación se explica al completo en nuestro artículo sobre <a href="/es/docs/Learn/CSS/CSS_layout/Floats">las propiedades float y clear</a>. El método de flotación es el que se usaba para crear diseños de columnas antes de la aparición de técnicas como los métodos Flexbox y diseño en rejillas. En la red aún puedes toparte con estos métodos. Vamos a exponer todo esto en el artículo sobre <a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">métodos de diseño heredados</a>.</p> +</div> + +<h2 id="Técnicas_de_posicionamiento">Técnicas de posicionamiento</h2> + +<p>El posicionamiento permite mover un elemento desde donde se colocaría cuando está en flujo normal a otra ubicación. El posicionamiento no es un método para crear diseños de página principal, se trata más bien de administrar y ajustar la posición de elementos específicos en la página.</p> + +<p>Sin embargo, hay técnicas útiles para ciertos patrones de diseños de páginas web que se basan en la propiedad {{cssxref ("position")}}. Comprender el posicionamiento también ayuda a comprender el flujo normal y qué implica sacar un elemento del flujo normal.</p> + +<p>Hay cinco tipos de posicionamiento que debes conocer:</p> + +<ul> + <li>El <strong>posicionamiento estático</strong> es el valor por defecto que tiene establecido cada elemento, esto significa sencillamente «coloca el elemento en su posición normal en el flujo de diseño del documento, nada especial que ver aquí».</li> + <li>El <strong>posicionamiento relativo</strong> permite modificar la posición de un elemento en la página y moverlo con respecto a su posición en el flujo normal, lo que incluye superposiciones con otros elementos de la página.</li> + <li>El <strong>posicionamiento absoluto</strong> mueve un elemento completamente fuera del flujo de diseño normal de la página, como si estuviera asentado en una capa separada propia. A partir de aquí, puedes fijarlo en una posición relativa a los bordes del elemento <code><html></code> de la página (o su elemento padre más próximo). Esto es útil para crear efectos complejos de diseño de página, como cuadros con pestañas en que diferentes paneles de contenido se ubican uno encima del otro y se muestran y ocultan según se desee, o paneles de información que por defecto se asientan fuera de la pantalla, pero puedes hacer que se deslicen hacia la pantalla usando un control de tipo botón.</li> + <li>El <strong>posicionamiento fijo</strong> es muy similar al posicionamiento absoluto, excepto que corrige un elemento relativo a la ventana gráfica del navegador, no otro elemento. Esto es útil para crear efectos, como un menú de navegación persistente que siempre permanece en el mismo lugar en la pantalla al contrario que el contenido, que se desplaza.</li> + <li>El <strong>posicionamiento <em>sticky</em> (pegajoso)</strong> es un método de posicionamiento más reciente que hace que un elemento actúe como <code>position: static</code> hasta que alcanza un desplazamiento definido con respecto a la ventana gráfica, en cuyo punto actúa como un elemento con la propiedad <code>position: fixed</code>.</li> +</ul> + +<h3 id="Ejemplo_sencillo_de_posicionamiento">Ejemplo sencillo de posicionamiento</h3> + +<p>Para familiarizarte con estas técnicas de diseño de página, te mostraremos un par de ejemplos rápidos. Todos nuestros ejemplos contarán con el mismo HTML, que es el siguiente:</p> + +<pre class="brush: html notranslate"><h1>Posicionamiento</h1> + +<p>Soy un elemento básico de nivel de bloque.</p> +<p class="positioned">Soy un elemento básico de nivel de bloque.</p> +<p>Soy un elemento básico de nivel de bloque.</p></pre> + +<p>Aplicaremos a este HTML un estilo predeterminado definido por el CSS siguiente:</p> + +<pre class="brush: css notranslate">body { + width: 500px; + margin: 0 auto; +} + +p { + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + margin: 10px; + border-radius: 5px; +} +</pre> + +<p>La salida que se obtiene es la siguiente:</p> + +<p>{{ EmbedLiveSample('Simple_positioning_example', '100%', 300) }}</p> + +<h3 id="El_posicionamiento_relativo">El posicionamiento relativo</h3> + +<p>El posicionamiento relativo permite compensar un elemento desde la posición por defecto que tendría en flujo normal. Esto significa que podrías hacer una tarea como mover un icono un poco hacia abajo para que se alinee con una etiqueta de texto. Para ello, podríamos añadir la regla de posicionamiento relativo siguiente:</p> + +<pre class="brush: css notranslate">.positioned { + position: relative; + top: 30px; + left: 30px; +}</pre> + +<p>Aquí asignamos el valor <code>relative</code> a la propiedad {{cssxref ("position")}} de nuestro párrafo del medio: esto no hace nada por sí solo, así que también añadimos las propiedades {{cssxref ("top")}} y {{cssxref ( "left")}}, que sirven para mover el elemento afectado hacia abajo y a la derecha. Esto puede parecer lo contrario de lo que esperabas, pero debes pensar en ello como un elemento al que se empuja por sus lados superior e izquierdo, lo que resulta en un movimiento a la derecha y abajo.</p> + +<p>Añadir este código dará el resultado siguiente:</p> + +<div id="Relative_1"> +<div class="hidden"> +<h6 id="Ejemplo_de_posicionamiento_relativo">Ejemplo de posicionamiento relativo</h6> + +<pre class="brush: html notranslate"><h1>El posicionamiento relativo</h1> + +<p>Soy un elemento básico de nivel de bloque.</p> +<p class="positioned">Este es mi elemento con posicionamiento relativo. </p> +<p>Soy un elemento básico de nivel de bloque.</p></pre> + +<pre class="brush: css notranslate">body { + width: 500px; + margin: 0 auto; +} + +p { + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + margin: 10px; + border-radius: 5px; +} +</pre> +</div> + +<pre class="brush: css notranslate">.positioned { + position: relative; + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Relative_1', '100%', 300) }}</p> + +<h3 id="El_posicionamiento_absoluto">El posicionamiento absoluto</h3> + +<p>El posicionamiento absoluto se utiliza para eliminar por completo un elemento del flujo normal y colocarlo mediante desplazamientos desde los bordes de un bloque contenedor.</p> + +<p>Volviendo a nuestro ejemplo original no posicionado, podríamos añadir la regla CSS siguiente para implementar el posicionamiento absoluto:</p> + +<pre class="brush: css notranslate">.positioned { + position: absolute; + top: 30px; + left: 30px; +}</pre> + +<p>Aquí le damos a la propiedad {{cssxref ("position")}} de nuestro párrafo del medio un valor de <code>absolute</code>, y le asignamos las mismas propiedades {{cssxref ("top")}} y {{cssxref ("left")}}. Sin embargo, ahora añadir este código da el resultado siguiente:</p> + +<div id="Absolute_1"> +<div class="hidden"> +<h6 id="Ejemplo_de_posicionamiento_absoluto">Ejemplo de posicionamiento absoluto</h6> + +<pre class="brush: html notranslate"><h1>Posicionamiento absoluto</h1> + +<p>Soy un elemento básico de nivel de bloque.</p> +<p class="positioned">Este es mi elemento con posicionamiento absoluto. </p> +<p>Soy un elemento básico de nivel de bloque.</p></pre> + +<pre class="brush: css notranslate">body { + width: 500px; + margin: 0 auto; +} + +p { + background-color: rgb(207,232,220); + border: 2px solid rgb(79,185,227); + padding: 10px; + margin: 10px; + border-radius: 5px; +} +</pre> +</div> + +<pre class="brush: css notranslate">.positioned { + position: absolute; + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Absolute_1', '100%', 300) }}</p> + +<p>¡Este resultado es muy diferente! El elemento posicionado ahora se ha separado por completo del resto del diseño de la página y se superpone encima de este. Los otros dos párrafos ahora se asientan juntos, como si su hermano con posicionamiento absoluto no existiera. Las propiedades {{cssxref ("top")}} y {{cssxref ("left")}} tienen un efecto diferente en elementos con posicionamiento absoluto que en elementos con posicionamiento relativo. En este caso, los desplazamientos se han calculado desde la parte superior e izquierda de la página. Es posible cambiar el elemento padre para que se convierta en este tipo de contenedor, y lo veremos en el artículo sobre <a href="/es/docs/Learn/CSS/CSS_layout/Positioning">posicionamiento</a>.</p> + +<h3 id="Posicionamiento_fijo">Posicionamiento fijo</h3> + +<p>El posicionamiento fijo elimina nuestro elemento del flujo de documentos de la misma manera que el posicionamiento absoluto. Sin embargo, en lugar de contar los desplazamientos en relación con el contenedor, se cuentan con respecto a la ventana gráfica. Como el elemento permanece fijo en relación con la ventana gráfica, podemos crear efectos como un menú que permanece fijo mientras la página se desplaza por debajo de él.</p> + +<p>En este ejemplo nuestro HTML tiene tres párrafos de texto para poder tener una página que se desplace, y un cuadro al que asignamos la propiedad <code>position: fixed</code>.</p> + +<pre class="brush: html notranslate"><h1>Posicionamiento fijo</h1> + +<div class="positioned">Fijo</div> + +<p>Párrafo 1.</p> +<p>Párrafo 2.</p> +<p>Párrafo 3.</p> +</pre> + +<div id="Fixed_1"> +<div class="hidden"> +<h6 id="Ejemplo_de_posicionamiento_fijo">Ejemplo de posicionamiento fijo</h6> + +<pre class="brush: html notranslate"><h1>Posicionamiento fijo</h1> + +<div class="positioned">Fijo</div> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p></pre> + +<pre class="brush: css notranslate">body { + width: 500px; + margin: 0 auto; +} + +.positioned { + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + padding: 10px; + margin: 10px; + border-radius: 5px; +}</pre> +</div> + +<pre class="brush: css notranslate">.positioned { + position: fixed; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Fixed_1', '100%', 200) }}</p> + +<h3 id="Posicionamiento_pegajoso">Posicionamiento pegajoso</h3> + +<p>El posicionamiento pegajoso es el último método de posicionamiento que tenemos a nuestra disposición. Mezcla el posicionamiento estático predeterminado con el posicionamiento fijo. Cuando un elemento tiene la propiedad <code>position: sticky</code>, se desplaza en flujo normal hasta que se alcanzan los desplazamientos con respecto a la ventana gráfica que hemos definido. En ese punto se queda «atascado» como si tuviera configurado un valor <code>position: fixed</code>.</p> + +<div id="Sticky_1"> +<div class="hidden"> +<h6 id="Ejemplo_de_posicionamiento_pegajoso">Ejemplo de posicionamiento pegajoso</h6> + +<pre class="brush: html notranslate"><h1>Posicionamiento pegajoso</h1> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + +<div class="positioned">Pegajoso</div> + +<p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + +<p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> </pre> + +<pre class="brush: css notranslate">body { + width: 500px; + margin: 0 auto; +} + +.positioned { + background: rgba(255,84,104,.3); + border: 2px solid rgb(255,84,104); + padding: 10px; + margin: 10px; + border-radius: 5px; +}</pre> +</div> + +<pre class="brush: css notranslate">.positioned { + position: sticky; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Sticky_1', '100%', 200) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: para obtener más información sobre el posicionamiento, consulta nuestro artículo <a href="/es/docs/Learn/CSS/CSS_layout/Positioning">Posicionamiento</a>.</p> +</div> + +<h2 id="Diseño_de_tablas">Diseño de tablas</h2> + +<p>Las tablas HTML sirven para mostrar datos tabulados, pero hace muchos años, antes incluso de que el CSS básico fuera compatible de forma fiable en todos los navegadores, los desarrolladores web también usaban tablas para hacer el diseño completo de una página web, colocando en las diversas filas y columnas de una tabla los títulos de encabezado de la página, los pies de página, las diferentes columnas, etc. Esto funcionó en ese momento, pero presenta muchos problemas: los diseños de tabla no son flexibles, requieren mucho código de marcado, son difíciles de depurar y no son semánticamente correctos (por ejemplo, los usuarios de lectores de pantalla tienen problemas para navegar por estos diseños de página web con tablas).</p> + +<p>El aspecto que presenta una tabla en una página web cuando usas el código de marcado de una tabla se debe a un conjunto de propiedades CSS que definen el diseño de la tabla. Estas propiedades se pueden usar para diseñar elementos que no son tablas, un uso que a veces se describe como «usar tablas CSS».</p> + +<p>El ejemplo siguiente muestra uno de esos usos; el uso de tablas CSS para el diseño debe considerarse en este punto un método heredado, para aquellas situaciones en las que tienes navegadores muy antiguos que no son compatibles con los métodos Flexbox o Grid.</p> + +<p>Veamos un ejemplo. Primero, un código de marcado sencillo que crea un formulario HTML. Cada elemento de entrada tiene una etiqueta, y también hemos incluido un título dentro de un párrafo. Cada par etiqueta/entrada está delimitado por un elemento {{htmlelement ("div")}}, con fines de compaginación.</p> + +<pre class="brush: html notranslate"><form> + <p>En primer lugar, díganos su nombre y edad.</p> + <div> + <label for="fname">Nombre:</label> + <input type="text" id="fname"> + </div> + <div> + <label for="lname">Apellidos:</label> + <input type="text" id="lname"> + </div> + <div> + <label for="age">Edad:</label> + <input type="text" id="age"> + </div> +</form></pre> + +<p>Ahora, el CSS para nuestro ejemplo. La mayor parte del CSS es bastante común, excepto por los usos de la propiedad {{cssxref ("display")}}. A los elementos {{htmlelement ("form")}}, {{htmlelement ("div")}}, {{htmlelement ("label")}} y {{htmlelement ("input")}} se les dice que se muestren como una tabla, filas de tabla y celdas de tabla, respectivamente; actuarán básicamente como marcas de tabla HTML, y lograrán por defecto la alineación perfecta de las etiquetas y las entradas. Todo lo que hay que hacer es añadir un poco de tamaños, márgenes, etc., para que todo se vea un poco mejor, ¡y listo!</p> + +<p>Observa que se la ha proporcionado al párrafo de encabezado <code>display: table-caption;,</code> lo que hace que actúe como una celda de encabezado ({{htmlelement ("caption")}}) de la tabla; y con <code>caption-side: bottom;</code> se le dice a la celda de encabezado que se asiente en la parte inferior de la tabla con fines de aplicación de estilo, aunque en el código fuente el marcado está antes que los elementos <code><input></code>. Esto permite un poco de flexibilidad.</p> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +form { + display: table; + margin: 0 auto; +} + +form div { + display: table-row; +} + +form label, form input { + display: table-cell; + margin-bottom: 10px; +} + +form label { + width: 200px; + padding-right: 5%; + text-align: right; +} + +form input { + width: 300px; +} + +form p { + display: table-caption; + caption-side: bottom; + width: 300px; + color: #999; + font-style: italic; +}</pre> + +<p>Esto nos da el resultado siguiente:</p> + +<p>{{ EmbedLiveSample('Table_layout', '100%', '170') }}</p> + +<p>También puedes ver este ejemplo en vivo en <a href="https://mdn.github.io/learning-area/css/styling-boxes/box-model-recap/css-tables-example.html">css-tables-example.html</a> (ver el <a href="https://github.com/mdn/learning-area/blob/master/css/styling-boxes/box-model-recap/css-tables-example.html">código fuente</a>).</p> + +<h2 id="Diseño_en_columnas">Diseño en columnas</h2> + +<p>El módulo de diseño en columnas nos proporciona un modo de distribuir el contenido en columnas, de forma similar al modo como el texto fluye en un periódico. Aunque en un contexto web leer en columnas de arriba a abajo no resulta tan útil porque podría obligar a los usuarios a tener que hacer desplazamientos de arriba a abajo, la técnica de organizar el contenido en columnas también puede tener su utilidad.</p> + +<p>Para convertir un bloque en un contenedor, utilizamos la propiedad {{cssxref ("column-count")}}, que le dice al navegador cuántas columnas nos gustaría tener, o {{cssxref ("column-width")}}, que le dice al navegador que llene el contenedor con tantas columnas de al menos ese ancho.</p> + +<p>En el ejemplo siguiente comenzamos con un bloque de HTML dentro de un elemento <code><div></code> que contiene una clase <code>container</code>.</p> + +<pre class="brush: html notranslate"><div class="container"> + <H1>Diseño en columnas</ h1> + + <p>Párrafo 1.</p> + <p>Párrafo 2.</p> + +</div> +</pre> + +<p>Utilizamos un <code>column-width</code> de 200 píxeles en ese contenedor, que crea en el navegador tantas columnas de 200 píxeles como quepan en el contenedor y luego comparte el espacio restante entre las columnas creadas.</p> + +<div id="Multicol_1"> +<div class="hidden"> +<h6 id="Ejemplo_de_diseño_en_columnas">Ejemplo de diseño en columnas</h6> + +<pre class="brush: html notranslate"><div class="container"> + <h1> Diseño en columnas </h1> + + <p> Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nulla luctus aliquam dolor, eu lacinia lorem placerat vulputate. Duis felis orci, pulvinar id metus ut, rutrum luctus orci. Cras porttitor imperdiet nunc, at ultricies tellus laoreet sit amet. Sed auctor cursus massa at porta. Integer ligula ipsum, tristique sit amet orci vel, viverra egestas ligula. Curabitur vehicula tellus neque, ac ornare ex malesuada et. In vitae convallis lacus. Aliquam erat volutpat. Suspendisse ac imperdiet turpis. Aenean finibus sollicitudin eros pharetra congue. Duis ornare egestas augue ut luctus. Proin blandit quam nec lacus varius commodo et a urna. Ut id ornare felis, eget fermentum sapien.</p> + + + <p>Nam vulputate diam nec tempor bibendum. Donec luctus augue eget malesuada ultrices. Phasellus turpis est, posuere sit amet dapibus ut, facilisis sed est. Nam id risus quis ante semper consectetur eget aliquam lorem. Vivamus tristique elit dolor, sed pretium metus suscipit vel. Mauris ultricies lectus sed lobortis finibus. Vivamus eu urna eget velit cursus viverra quis vestibulum sem. Aliquam tincidunt eget purus in interdum. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.</p> + + </div></pre> + +<pre class="brush: css notranslate">body { max-width: 800px; margin: 0 auto; } </pre> +</div> + +<pre class="brush: css notranslate"> .container { + column-width: 200px; + }</pre> +</div> + +<p>{{ EmbedLiveSample('Multicol_1', '100%', 200) }}</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Este artículo ha proporcionado un breve resumen de todas las tecnologías de diseño que debes conocer. ¡Sigue leyendo para obtener más información sobre cada tecnología individual!</p> + +<p>{{NextMenu("Learn/CSS/CSS_layout/Normal_Flow", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introducción al diseño CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Flujo normal</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Cuadrícula</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Flotación</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamiento</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Diseño en columnas</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Diseño adaptativo</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Guía para principiantes sobre consultas a medios</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Métodos de compaginación heredados</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Compatibilidad en navegadores antiguos </a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Evaluación del conjunto de elementos básicos de compaginación</a></li> +</ul> diff --git a/files/es/learn/css/css_layout/positioning/index.html b/files/es/learn/css/css_layout/positioning/index.html new file mode 100644 index 0000000000..3deb33b91f --- /dev/null +++ b/files/es/learn/css/css_layout/positioning/index.html @@ -0,0 +1,469 @@ +--- +title: Positioning +slug: Learn/CSS/CSS_layout/Positioning +translation_of: Learn/CSS/CSS_layout/Positioning +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout/Practical_positioning_examples", "Learn/CSS/CSS_layout")}}</div> + +<p class="summary">El posicionamiento permite sacar elementos del flujo normal del diseño del documento, y hacer que se comporten de manera distinta, por ejemplo sentarse encima de otro o permanecer en el mismo lugar dentro de la ventana navegador. Este artículo explica los diferentes valores {{cssxref("position")}}, y como usarlos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos:</th> + <td>HTML básico (Aprende <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML"> Introducción a HTML</a>), y una idea de cómo trabaja CSS (Aprende <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introducción a CSS</a>.)</td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Entender como trabajar con posicionamiento CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="Flujo_del_Documento">Flujo del Documento</h2> + +<p>El posicionamiento es un tema bastante complejo, así que antes de profundizar en el código volvamos a examinar y ampliar un poco la teoría del diseño para darnos una idea de cómo funciona esto.</p> + +<p>First of all, individual element boxes are laid out by taking the elements' content, then adding any padding, border and margin around them — it's that <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Box_model">box model</a> thing again, which we looked at earlier. By default, a block level element's content is 100% of the width of its parent element, and as tall as its content. Inline elements are all tall as their content, and as wide as their content. You can't set width or height on inline elements — they just sit inside the content of block level elements. If you want to control the size of an inline element in this manner, you need to set it to behave like a block level element with <code>display: block;</code>.</p> + +<p>That explains individual elements, but what about how elements interact with one another? The <strong>normal layout flow</strong> (mentioned in the layout introduction article) is the system by which elements are placed inside the browser's viewport. By default, block level elements are laid out vertically in the viewport — each one will appear on a new line below the last one, and they will be separated by any margin that is set on them.</p> + +<p>Inline elements behave differently — they don't appear on new lines; instead, they sit on the same line as one another and any adjacent (or wrapped) text content, as long as there is space for them to do so inside the width of the parent block level element. If there isn't space, then the overflowing text or elements will move down to a new line.</p> + +<p>If two adjacent elements both have margin set on them and the two margins touch, the larger of the two remains, and the smaller one disappears — this is called <a href="/en-US/docs/Web/CSS/CSS_Box_Model/Mastering_margin_collapsing">margin collapsing</a>, and we have met this before too.</p> + +<p>Let's look at a simple example that explains all this:</p> + +<pre class="brush: html"><h1>Basic document flow</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p>By default we span 100% of the width of our parent element, and we are as tall as our child content. Our total width and height is our content + padding + border width/height.</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements will <span>wrap onto a new line if possible (like this one containing text)</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +}</pre> + +<p>{{ EmbedLiveSample('Document_flow', '100%', 500) }}</p> + +<p>We will be revisiting this example a number of times as we go through this article, as we show the effects of the different positioning options available to us.</p> + +<p>We'd like you to follow along with the exercises on your local computer, if possible — grab a copy of <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/0_basic-flow.html">0_basic-flow.html</a></code> from our Github repo (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/0_basic-flow.html">source code here</a>) and use that as a starting point.</p> + +<h2 id="Introducing_positioning">Introducing positioning</h2> + +<p>The whole idea of positioning is to allow us to override the basic document flow behaviour described above, to produce interesting effects. What if you want to slightly alter the position of some boxes inside a layout from their default layout flow position, to give a slightly quirky, distressed feel? Positioning is your tool. Or if you want to create a UI element that floats over the top of other parts of the page, and/or always sits in the same place inside the browser window no matter how much the page is scrolled? Positioning makes such layout work possible.</p> + +<p>There are a number of different types of positioning that you can put into effect on HTML elements. To make a specific type of positioning active on an element, we use the {{cssxref("position")}} property.</p> + +<h3 id="Static_positioning">Static positioning</h3> + +<p>Static positioning is the default that every element gets — it just means "put the element into its normal position in the document layout flow — nothing special to see here."</p> + +<p>To demonstrate this, and get your example set up for future sections, first add a <code>class</code> of <code>positioned</code> to the second {{htmlelement("p")}} in the HTML:</p> + +<pre class="brush: html"><p class="positioned"> ... </p></pre> + +<p>Now add the following rule to the bottom of your CSS:</p> + +<pre class="brush: css">.positioned { + position: static; + background: yellow; +}</pre> + +<p>If you now save and refresh, you'll see no difference at all, except for the updated background color of the 2nd paragraph. This is fine — as we said before, static positioning is the default behaviour!</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/1_static-positioning.html">1_static-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/1_static-positioning.html">see source code</a>).</p> +</div> + +<h3 id="Relative_positioning">Relative positioning</h3> + +<p>Relative positioning is the first position type we'll take a look at. This is very similar to static positioning, except that once the positioned element has taken its place in the normal layout flow, you can then modify its final position, including making it overlap other elements on the page. Go ahead and update the position declaration in your code:</p> + +<pre class="brush: css">position: relative;</pre> + +<p>If you save and refresh at this stage, you won't see a change in the result at all — so how do you modify the element's position? You need to use the {{cssxref("top")}}, {{cssxref("bottom")}}, {{cssxref("left")}}, and {{cssxref("right")}} properties, which we'll explain in the next section.</p> + +<h3 id="Introducing_top_bottom_left_and_right">Introducing top, bottom, left, and right</h3> + +<p>{{cssxref("top")}}, {{cssxref("bottom")}}, {{cssxref("left")}}, and {{cssxref("right")}} are used alongside {{cssxref("position")}} to specify exactly where to move the positioned element to. To try this out, add the following declarations to the <code>.positioned</code> rule in your CSS:</p> + +<pre>top: 30px; +left: 30px;</pre> + +<div class="note"> +<p><strong>Note</strong>: The values of these properties can take any <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS/Values_and_units">units</a> you'd logically expect — pixels, mm, rems, %, etc.</p> +</div> + +<p>If you now save and refresh, you'll get a result something like this:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>Relative positioning</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">By default we span 100% of the width of our parent element, and we are as tall as our child content. Our total width and height is our content + padding + border width/height.</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +.positioned { + position: relative; + background: yellow; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Introducing_top_bottom_left_and_right', '100%', 500) }}</p> + +<p>Cool, huh? Ok, so this probably wasn't what you were expecting — why has it moved to the bottom and right if we specified top and left? Illogical as it may initially sound, this is just the way that relative positioning works — you need to think of an invisible force that pushes the side of the positioned box, moving it in the opposite direction. So for example, if you specify <code>top: 30px;</code>, a force pushes the top of the box, causing it to move downwards by 30px.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/2_relative-positioning.html">2_relative-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/2_relative-positioning.html">see source code</a>).</p> +</div> + +<h3 id="Absolute_positioning">Absolute positioning</h3> + +<p>Absolute positioning brings very different results. Let's try changing the position declaration in your code as follows:</p> + +<pre>position: absolute;</pre> + +<p>If you now save and refresh, you should see something like so:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>Absolute positioning</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">By default we span 100% of the width of our parent element, and we are as tall as our child content. Our total width and height is our content + padding + border width/height.</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +.positioned { + position: absolute; + background: yellow; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Absolute_positioning', '100%', 420) }}</p> + +<p>First of all, note that the gap where the positioned element should be in the document flow is no longer there — the first and third elements have closed together like it no longer exists! Well, in a way, this is true. An absolutely positioned element no longer exists in the normal document layout flow. Instead, it sits on its own layer separate from everything else. This is very useful — it means that we can create isolated UI features that don't interfere with the position of other elements on the page — for example popup information boxes and control menus, rollover panels, UI features that can be dragged and dropped anywhere on the page, and so on.</p> + +<p>Second, notice that the position of the element has changed — this is because {{cssxref("top")}}, {{cssxref("bottom")}}, {{cssxref("left")}}, and {{cssxref("right")}} behave in a different way with absolute positioning. Instead of specifying the direction the element should move in, they specify the distance the element should be from each containing element's sides. So in this case, we are saying that the absolutely positioned element should sit 30px from the top of the "containing element", and 30px from the left.</p> + +<div class="note"> +<p><strong>Note</strong>: You can use {{cssxref("top")}}, {{cssxref("bottom")}}, {{cssxref("left")}}, and {{cssxref("right")}} to resize elements if you need to. Try setting <code>top: 0; bottom: 0; left: 0; right: 0;</code> and <code>margin: 0;</code> on your positioned elements and see what happens! Put it back again afterwards...</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: Yes, margins still affect positioned elements. Margin collapsing doesn't, however.</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/3_absolute-positioning.html">3_absolute-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/3_absolute-positioning.html">see source code</a>).</p> +</div> + +<h3 id="Positioning_contexts">Positioning contexts</h3> + +<p>Which element is the "containing element" of an absolutely positioned element? By default, it is the {{htmlelement("html")}} element — the positioned element is nested inside the {{htmlelement("body")}} in the HTML source, but in the final layout, it is 30px away from the top and left of the edge of the page, which is the {{htmlelement("html")}} element. This is more accurately called the element's <strong>positioning context</strong>.</p> + +<p>We can change the <strong>positioning context</strong> — which element the absolutely positioned element is positioned relative to. This is done by setting positioning on one of the element's other ancestors — one of the elements it is nested inside (you can't position it relative to an element it is not nested inside). To demonstrate this, add the following declaration to your body rule:</p> + +<pre>position: relative;</pre> + +<p>This should give the following result:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>Positioning context</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">Now I'm absolutely positioned relative to the <code>&lt;body&gt;</code> element, not the <code>&lt;html&gt;</code> element!</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; + position: relative; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +.positioned { + position: absolute; + background: yellow; + top: 30px; + left: 30px; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Positioning_contexts', '100%', 420) }}</p> + +<p>The positioned element now sits relative to the {{htmlelement("body")}} element.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/4_positioning-context.html">4_positioning-context.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/4_positioning-context.html">see source code</a>).</p> +</div> + +<h3 id="Introducing_z-index">Introducing z-index</h3> + +<p>All this absolute positioning is good fun, but there is another thing we haven't considered yet — when elements start to overlap, what determines which elements appear on top of which other elements? In the example we've seen so far, we only have one positioned element in the positioning context, and it appears on the top, since positioned elements win over non-positioned elements. What about when we have more than one?</p> + +<p>Try adding the following to your CSS, to make the first paragraph absolutely positioned too:</p> + +<pre>p:nth-of-type(1) { + position: absolute; + background: lime; + top: 10px; + right: 30px; +}</pre> + +<p>At this point you'll see the first paragraph colored green, moved out of the document flow, and positioned a bit above from where it originally was. It is also stacked below the original <code>.positioned</code> paragraph, where the two overlap. This is because the <code>.positioned</code> paragraph is the second paragraph in the source order, and positioned elements later in the source order win over positioned elements earlier in the source order.</p> + +<p>Can you change the stacking order? Yes, you can, by using the {{cssxref("z-index")}} property. "z-index" is a reference to the z-axis. You may recall from previous points in the source where we discussed web pages using horizontal (x-axis) and vertical (y-axis) coordinates to work out positioning for things like background images and drop shadow offsets. (0,0) is at the top left of the page (or element), and the x- and y-axes run across to the right and down the page (for left to right languages, anyway.)</p> + +<p>Web pages also have a z-axis — an imaginary line that runs from the surface of your screen, towards your face (or whatever else you like to have in front of the screen). {{cssxref("z-index")}} values affect where positioned elements sit on that axis — positive values move them higher up the stack, and negative values move them lower down the stack. By default, positioned elements all have a <code>z-index</code> of auto, which is effectively 0.</p> + +<p>To change the stacking order, try adding the following declaration to your <code>p:nth-of-type(1)</code> rule:</p> + +<pre>z-index: 1;</pre> + +<p>You should now see the finished example:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>z-index</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">Now I'm absolutely positioned relative to the <code>&lt;body&gt;</code> element, not the <code>&lt;html&gt;</code> element!</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + margin: 0 auto; + position: relative; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +.positioned { + position: absolute; + background: yellow; + top: 30px; + left: 30px; +} + +p:nth-of-type(1) { + position: absolute; + background: lime; + top: 10px; + right: 30px; + z-index: 1; +} +</pre> +</div> + +<p>{{ EmbedLiveSample('Introducing_z-index', '100%', 400) }}</p> + +<p>Note that <code>z-index</code> only accepts unitless index values; you can't specify that you want one element to be 23 pixels up the Z-axis — it doesn't work like that. Higher values will go above lower values, and it is up to you what values you use. Using 2 and 3 would give the same effect as 300 and 40000.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/5_z-index.html">5_z-index.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/5_z-index.html">see source code</a>).</p> +</div> + +<h3 id="Fixed_positioning">Fixed positioning</h3> + +<p>There is one more type of positioning to cover — fixed. This works in exactly the same way as absolute positioning, with one key difference — whereas absolute positioning fixes an element in place relative to the {{htmlelement("html")}} element or its nearest positioned ancestor, fixed positioning fixes an element in place relative to the browser viewport itself. This means that you can create useful UI items that are fixed in place, like persisting navigation menus.</p> + +<p>Let's put together a simple example to show what we mean. First of all, delete the existing <code>p:nth-of-type(1)</code> and <code>.positioned</code> rules from your CSS.</p> + +<p>Now, update the <code>body</code> rule to remove the <code>position: relative;</code> declaration and add a fixed height, like so:</p> + +<pre>body { + width: 500px; + height: 1400px; + margin: 0 auto; +}</pre> + +<p>Now we're going to give the {{htmlelement("h1")}} element <code>position: fixed;</code>, and get it to sit at the top center of the viewport. Add the following rule to your CSS:</p> + +<pre>h1 { + position: fixed; + top: 0; + width: 500px; + margin: 0 auto; + background: white; + padding: 10px; +}</pre> + +<p>The <code>top: 0;</code> is required to make it stick to the top of the screen; we then give the heading the same width as the content column and use the faithful old <code>margin: 0 auto;</code> trick to center it. We then give it a white background and some padding, so the content won't be visible underneath it.</p> + +<p>If you save and refresh now, you'll see a fun little effect whereby the heading stays fixed, and the content appears to scroll up and disappear underneath it. But we could improve this more — at the moment some of the content starts off underneath the heading. This is because the positioned heading no longer appears in the document flow, so the rest of the content moves up to the top. We need to move it all down a bit; we can do this by setting some top margin on the first paragraph. Add this now:</p> + +<pre>p:nth-of-type(1) { + margin-top: 60px; +}</pre> + +<p>You should now see the finished example:</p> + +<div class="hidden"> +<pre class="brush: html"><h1>Fixed positioning</h1> + +<p>I am a basic block level element. My adjacent block level elements sit on new lines below me.</p> + +<p class="positioned">I'm not positioned any more...</p> + +<p>We are separated by our margins. Because of margin collapsing, we are separated by the width of one of our margins, not both.</p> + +<p>inline elements <span>like this one</span> and <span>this one</span> sit on the same line as one another, and adjacent text nodes, if there is space on the same line. Overflowing inline elements <span>wrap onto a new line if possible — like this one containing text</span>, or just go on to a new line if not, much like this image will do: <img src="https://mdn.mozillademos.org/files/13360/long.jpg"></p></pre> + +<pre class="brush: css">body { + width: 500px; + height: 1400px; + margin: 0 auto; +} + +p { + background: aqua; + border: 3px solid blue; + padding: 10px; + margin: 10px; +} + +span { + background: red; + border: 1px solid black; +} + +h1 { + position: fixed; + top: 0px; + width: 500px; + margin: 0 auto; + background: white; + padding: 10px; +} + +p:nth-of-type(1) { + margin-top: 60px; +}</pre> + +<p> </p> +</div> + +<p>{{ EmbedLiveSample('Fixed_positioning', '100%', 400) }}</p> + +<div class="note"> +<p><strong>Note</strong>: You can see the example at this point live at <code><a href="http://mdn.github.io/learning-area/css/css-layout/positioning/6_fixed-positioning.html">6_fixed-positioning.html</a></code> (<a href="https://github.com/mdn/learning-area/blob/master/css/css-layout/positioning/6_fixed-positioning.html">see source code</a>).</p> +</div> + +<h3 id="Experimental_position_sticky">Experimental: position sticky</h3> + +<p>There is a new positioning value available called <code>position: sticky</code>, support for which is not very widespread yet. This is basically a hybrid between relative and fixed position, which allows a positioned element to act like it is relatively positioned until it is scrolled to a certain threshold point (e.g. 10px from the top of the viewport), after which it becomes fixed. See our <a href="/en-US/docs/Web/CSS/position#Sticky_positioning">position: sticky reference entry</a> for more details and an example.</p> + +<h2 id="Summary">Summary</h2> + +<p>I'm sure you had fun playing with basic positioning — it is one of the essential tools behind creating complex CSS layouts and UI features. With that in mind, in the next article we'll have even more fun with positioning — there we'll go a step further and start to build up some real world useful things with it.</p> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Floats", "Learn/CSS/CSS_layout/Practical_positioning_examples", "Learn/CSS/CSS_layout")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introduction to CSS layout</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Floats</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Positioning</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Practical_positioning_examples">Practical positioning examples</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Grids</a></li> +</ul> + +<p> </p> diff --git a/files/es/learn/css/css_layout/soporte_a_navegadores_antiguos/index.html b/files/es/learn/css/css_layout/soporte_a_navegadores_antiguos/index.html new file mode 100644 index 0000000000..18065a1da5 --- /dev/null +++ b/files/es/learn/css/css_layout/soporte_a_navegadores_antiguos/index.html @@ -0,0 +1,237 @@ +--- +title: Soporte a navegadores antiguos +slug: Learn/CSS/CSS_layout/Soporte_a_navegadores_antiguos +translation_of: Learn/CSS/CSS_layout/Supporting_Older_Browsers +--- +<div>{{LearnSidebar}}</div> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Legacy_Layout_methods", "Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension", "Learn/CSS/CSS_layout")}}</p> + +<p class="summary">En este módulo recomendamos utilizar Flexbox y Grid como las herramientas principales para tus diseños. Sin embargo, habrá visitantes a tu sitio web que usen navegadores antiguos o navegadores que no admiten los métodos que has utilizado. Este siempre será el caso en la red: a medida que se desarrollan funciones nuevas, los diferentes navegadores priorizan cosas diferentes. Este artículo explica cómo usar técnicas web modernas sin perjudicar a los usuarios con tecnologías más antiguas.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y nociones de cómo funciona el CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender cómo proporcionar compatibilidad para tus diseños en navegadores antiguos que podrían no admitir las funciones que deseas utilizar.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Cuál_es_la_vista_del_navegador_para_tu_sitio">¿Cuál es la vista del navegador para tu sitio?</h2> + +<p>Cada sitio web es diferente en términos de público objetivo. Antes de decidir el enfoque a seguir, averigua la cantidad de visitantes que visitan tu sitio que utilizan navegadores antiguos. Esto es sencillo si se trata de un sitio web que simplemente modificas o reemplazas, porque probablemente haya análisis disponibles que te indiquen la tecnología que la gente utiliza. Si el sitio no tiene funciones de análisis o se trata de un sitio nuevo, hay sitios como <a href="http://gs.statcounter.com/">Statcounter</a> que pueden proporcionar estadísticas filtradas por ubicación.</p> + +<p>También debes considerar el tipo de dispositivos y la forma en que las personas usan tu sitio; por ejemplo, puedes esperar un número de dispositivos móviles superior al promedio. La accesibilidad y las personas que utilizan tecnología de asistencia siempre deben tenerse en cuenta, pero para algunos sitios pueden ser aspectos aún más críticos. Según experiencia propia, los desarrolladores a menudo se preocupan demasiado por la experiencia de usuario de un 1% de usuarios que usan una versión antigua de Internet Explorer, y no consideran en absoluto el número mucho mayor de usuarios que tiene necesidades de accesibilidad especiales.</p> + +<h2 id="¿Qué_compatibilidad_presentan_las_funciones_que_vas_a_usar">¿Qué compatibilidad presentan las funciones que vas a usar?</h2> + +<p>Una vez conozcas qué tipo de navegadores utiliza la gente que accede a tu sitio, puedes evaluar cualquier tecnología que desees utilizar según su compatibilidad y con qué facilidad es posible proporcionar una alternativa a los visitantes que no disponen de esa tecnología. Tratamos de facilitarte esta experiencia proporcionando información de compatibilidad de los navegadores en cada una de las páginas que detallan una propiedad CSS. Por ejemplo, echa un vistazo a la página de {{cssxref ("grid-template-columns")}}. En la parte inferior de esta página hay una tabla que enumera los navegadores principales, junto con la versión en la que comenzaron a admitir esta propiedad.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16047/browser-table.png" style="height: 1178px; width: 2102px;"></p> + +<p>Otra forma popular de averiguar la compatibilidad de una característica es el sitio web <a href="https://caniuse.com/">Can I Use</a>. Este sitio enumera la mayoría de las características de la Plataforma Web con información sobre el estado de compatibilidad de tu navegador. Puedes ver las estadísticas de uso por ubicación, cosa que resulta útil si trabajas en un sitio cuyos usuarios son de un territorio particular. Incluso puedes vincular tu cuenta de Google Analytics para obtener un análisis basado en tus datos de usuario.</p> + +<p>Conocer las tecnologías de tus usuarios y las compatibilidades de las funciones que tal vez quieras usar te proporcionan una buena base para tomar todas tus decisiones y saber cuál es la mejor manera de dar compatibilidad a todos tus usuarios.</p> + +<h2 id="Compatibilidad_no_significa_«verse_igual»">Compatibilidad no significa «verse igual»</h2> + +<p>Es posible que un sitio web no tenga el mismo aspecto en todos los navegadores, porque algunos de tus usuarios lo verán en un teléfono y otros en el ordenador. Del mismo modo, algunos de tus usuarios tendrán una versión antigua del navegador y otros el navegador más reciente. Es posible que algunos de tus usuarios estén escuchando el contenido leído por un lector de pantalla, o hayan ampliado la página para poderla leer. Dar compatibilidad a todos significa servir una versión de tus contenidos diseñada estratégicamente para que se vea genial con los navegadores modernos, pero aún sea utilizable en un nivel básico para los usuarios con navegadores más antiguos.</p> + +<p>Un nivel básico de compatibilidad proviene de estructurar bien tus contenidos para que el flujo normal de tu página tenga sentido. Un usuario con un teléfono con funciones muy limitadas puede que no obtenga buena parte de tu CSS, pero el contenido fluirá de una manera que la lectura resulte fácil. Por lo tanto, un documento HTML bien estructurado siempre debe ser tu punto de partida. <em>¿Tu contenido tiene sentido si eliminas tu hoja de estilo?</em></p> + +<p>Una opción es dejar esta vista simple del sitio como alternativa para las personas que utilizan navegadores muy antiguos o limitados. Si la cantidad de personas que visitan el sitio con estos navegadores es pequeña, quizá no tenga sentido comercial dedicar tiempo a tratar de proporcionarles una experiencia similar a la de las personas que utilizan navegadores modernos. Sería mejor dedicar el tiempo a cosas que proporcionen accesibilidad al sitio, y servir así a muchos más usuarios. Hay un punto medio entre una página HTML simple y todos esos recursos, y CSS realmente ha logrado que proporcionar estas soluciones alternativas resulte bastante sencillo.</p> + +<h2 id="Crear_soluciones_alternativas_en_CSS">Crear soluciones alternativas en CSS</h2> + +<p>Las especificaciones CSS contienen información que explica qué hace el navegador cuando se aplican dos métodos de diseño al mismo elemento. Esto significa que hay una definición de lo que sucede si un elemento flotante, por ejemplo, también es un elemento Grid que usa diseño de cuadrícula CSS. Combina esta información con el conocimiento de que los navegadores ignoran el CSS que no entienden, y tienes una manera de crear diseños simples utilizando las <a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">técnicas heredadas</a> que ya hemos expuesto, que luego se sobrescriben con tu diseño de cuadrícula en los navegadores modernos que lo entienden.</p> + +<p>En el ejemplo siguiente hemos especificado tres elementos de flotación <code><div></code> para que se muestren en una fila. Cualquier navegador que no sea compatible con el método de compaginación <a href="/es/docs/Learn/CSS/CSS_layout/Grids">CSS Grid</a> verá la hilera de cajas como un diseño con el método de flotación. Un elemento de flotación que se convierte en un elemento de cuadrícula pierde el comportamiento de flotación, lo que significa que al convertir el contenedor en un contenedor de cuadrícula, los elementos de flotación se convierten en elementos de cuadrícula. Si el navegador admite el diseño de cuadrícula, muestra la vista de cuadrícula; si no, ignora las propiedades relacionadas con el diseño de cuadrícula y utiliza el diseño de flotación.</p> + +<div id="Example1"> +<pre class="brush: css">* {box-sizing: border-box;} + +.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + max-width: 400px; + display: grid; + grid-template-columns: 1fr 1fr 1fr; +} + +.item { + float: left; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; +} +</pre> + +<pre class="brush: html"><div class="wrapper"> + <div class="item">Artículo uno</div> + <div class="item">Artículo dos</div> + <div class="item">Artículo tres</div> +</div> +</pre> + +<p>{{ EmbedLiveSample('Example1', '100%', '200') }}</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: La propiedad {{cssxref ("clear")}} tampoco tiene efecto una vez que el elemento al que se le aplica se convierte en un elemento de cuadrícula, por lo que podrías tener una compaginación con un pie <code>clear</code>, que luego pase a ser un elemento de compaginación en cuadrícula.</p> +</div> + +<h3 id="Métodos_de_soluciones_alternativas">Métodos de soluciones alternativas</h3> + +<p>Numerosos métodos de compaginación se pueden usar de manera similar a este ejemplo con comportamiento de flotación. Puedes elegir el que tenga más sentido para el patrón de compaginación que necesitas crear.</p> + +<dl> + <dt><strong><code>float</code></strong> y <strong><code>clear</code></strong></dt> + <dd>Como se muestra arriba, las propiedades <em>float</em> o <em>clear</em> dejan de afectar a la compaginación si los elementos afectados por estas propiedades pasan a ser de tipo flexible o de cuadrícula.</dd> + <dt>display: inline-block;</dt> + <dd>Este método se puede utilizar para crear compaginaciones en columnas; si un elemento tiene establecido un comportamiento <code>display: inline-block</code> pero se convierte a elemento con compaginación de tipo flexible o de cuadrícula, el comportamiento <code>inline-block</code> se ignora.</dd> + <dt>display: table;</dt> + <dd>El método de creación de tablas CSS que se describe en la <a href="/es/docs/Learn/CSS/CSS_layout/Introducción">introducción</a> de estos artículos puede utilizarse como opción alternativa. Los elementos que tienen diseños de tabla CSS pierden este comportamiento si se convierten en elementos con comportamiento flexible o de cuadrícula. Es importante destacar que no se crearán las cajas sin nombre que fueron creadas para arreglar la estructura de tabla.</dd> + <dt>Compaginación en columnas</dt> + <dd>Para ciertos tipos de compaginación puedes usar <a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">multi-col</a> como opción alternativa; si tu contenedor tiene alguna propiedad <code>column-*</code> definida y se convierte en un contenedor con comportamiento de cuadrícula, se anula el comportamiento en columnas.</dd> + <dt>Flexbox como opción alternativa a la cuadrícula</dt> + <dd><a href="/es/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a> tiene una compatibilidad mayor con los navegadores que Grid porque es compatible con Internet Explorer 10 y 11, aunque te recomendamos que consultes la información que encontrarás más adelante en este artículo sobre la compatibilidad bastante irregular y confusa de Flexbox en navegadores más antiguos. Si conviertes un contenedor flexible en un contenedor de cuadrícula, se ignorará cualquier propiedad <code>flex</code> aplicada a los elementos secundarios.</dd> +</dl> + +<p>Observa que si usas el CSS de esta manera puedes proporcionar una experiencia de usuario decente para ajustar muchas compaginaciones en navegadores antiguos. Añadimos una compaginación más simple basada en técnicas antiguas y con buena compatibilidad, y luego usamos el CSS más nuevo para crear la compaginación que va a ver más del 90% de tu público. Sin embargo, hay casos en los que el código alternativo va a tener que incluir algo que también van a interpretar los navegadores nuevos. Un buen ejemplo de esto es si queremos añadir anchos en porcentaje a nuestros elementos de flotación para que el aspecto de las columnas reproduzca mejor la visualización en cuadrícula, expandiendo para llenar el contenedor.</p> + +<p>En la compaginación de flotación, el porcentaje se calcula con respecto al contenedor: 33,333% es un tercio del ancho del contenedor. Sin embargo, en el método Grid ese 33,333% se calcula con respecto al área de la cuadrícula en la que el elemento está ubicado, por lo que en realidad se convierte en un tercio del tamaño que queremos una vez que se introduce la compaginación en cuadrícula.</p> + +<div id="Example2"> +<pre class="brush: css">* {box-sizing: border-box;} + +.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + max-width: 400px; + display: grid; + grid-template-columns: 1fr 1fr 1fr; +} + +.item { + float: left; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; + width: 33.333%; +} +</pre> + +<pre class="brush: html"><div class="wrapper"> + <div class="item">Artículo uno</div> + <div class="item">Artículo dos</div> + <div class="item">Artículo tres</div> +</div> +</pre> + +<p>{{ EmbedLiveSample('Example2', '100%', '200') }}</p> +</div> + +<p>Para tratar este problema, necesitamos tener un modo de detectar si Grid es compatible y, por lo tanto, si anulará el ancho. El CSS tiene una solución.</p> + +<h2 id="Consultar_las_propiedades">Consultar las propiedades</h2> + +<p>Consultar las propiedades te permite comprobar si un navegador admite alguna característica CSS en particular. Esto significa que puedes escribir algunos CSS para navegadores que no admitan una propiedad determinada y luego verificar si el navegador es compatible, y añadir tu elegante diseño de ser así.</p> + +<p>Si añadimos al ejemplo anterior una consulta de las propiedades, podemos usarla para volver a establecer a <code>auto</code> los anchos de nuestros elementos, si sabemos que hay compatibilidad para la compaginación en cuadrícula.</p> + +<div id="Example3"> +<pre class="brush: css">* {box-sizing: border-box;} + +.wrapper { + background-color: rgb(79,185,227); + padding: 10px; + max-width: 400px; + display: grid; + grid-template-columns: 1fr 1fr 1fr; +} + +.item { + float: left; + border-radius: 5px; + background-color: rgb(207,232,220); + padding: 1em; + width: 33.333%; +} + +@supports (display: grid) { + .item { + width: auto; + } +} +</pre> + +<pre class="brush: html"><div class="wrapper"> + <div class="item">Elemento uno</div> + <div class="item">Elemento dos</div> + <div class="item">Elemento tres</div> +</div> +</pre> + +<p>{{ EmbedLiveSample('Example3', '100%', '200') }}</p> +</div> + +<p>La compatibilidad para la consulta de propiedades es muy buena en todos los navegadores modernos, pero debes tener en cuenta que son los navegadores que no admiten CSS Grid los que tampoco admiten la consulta de propiedades. Esto significa que para esos navegadores funcionará un enfoque como el que acabamos de detallar. Lo que hacemos es escribir primero nuestro CSS anterior sin hacer ninguna consulta de propiedades. Los navegadores que no admiten Grid y que no admiten la consulta de propiedades utilizan esa información de diseño que pueden entender e ignoran por completo todo lo demás. Los navegadores que admiten la consulta de propiedades también admiten CSS Grid y, por lo tanto, ejecutan el código de cuadrícula y el código de la consulta de propiedades.</p> + +<p>La especificación para la consulta de propiedades también incluye la posibilidad de probar si un navegador no admite una propiedad; esto solo es útil si el navegador admite consultas de propiedades. En el futuro bastará con el enfoque de verificar la falta de compatibilidad, porque los navegadores que no tienen compatibilidad para la consulta de propiedades desaparecen. Por ahora, sin embargo, utiliza el enfoque de usar el CSS anterior y luego sobrescribirlo para obtener la mejor compatibilidad.</p> + +<h2 id="Versiones_anteriores_de_Flexbox">Versiones anteriores de Flexbox</h2> + +<p>En versiones anteriores de navegadores, puedes encontrar versiones anteriores de la especificación Flexbox. En el momento de escribir esto se trata principalmente de un problema con Internet Explorer 10, que usa el prefijo <code>-ms-</code> para Flexbox. Esto también significa que algunos artículos y tutoriales están obsoletos; <a href="https://css-tricks.com/old-flexbox-and-new-flexbox/">esta guía útil</a> te ayuda a verificarlo y también puede ayudarte si necesitas compatibilidad Flexbox en navegadores muy antiguos.</p> + +<h2 id="La_versión_prefijada_de_Grid_de_Internet_Explorer_10_y_11">La versión prefijada de Grid de Internet Explorer 10 y 11</h2> + +<p>La especificación CSS Grid se prototipó inicialmente en Internet Explorer 10; esto significa que si bien IE10 e IE11 no tienen compatibilidad de cuadrícula <em>moderna</em>, sí tienen una versión de compaginación en cuadrícula, que es muy útil, aunque diferente de la especificación moderna que documentamos en este sitio. Las implementaciones de IE10 y 11 tienen el prefijo <code>-ms-</code>, lo que significa que puedes usarlo para estos navegadores y los navegadores que no sean de Microsoft lo ignorarán. Sin embargo, Edge todavía comprende la sintaxis anterior, así que ten cuidado de que todo se sobrescriba de forma segura en tu cuadrícula de CSS moderna.</p> + +<p>La guía de <a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/CSS_Grid_and_Progressive_Enhancement">Mejora progresiva en la compaginación en cuadrícula</a> puede ayudarte a comprender la versión de la cuadrícula de Internet Explorer, y hemos incluido algunos enlaces útiles adicionales al final de este artículo. Sin embargo, a menos que tengas una gran cantidad de visitantes con versiones anteriores de Internet Explorer, puede que te resulte mejor centrarte en crear una reserva que funcione para todos los navegadores no compatibles.</p> + +<h2 id="Pruebas_con_navegadores_antiguos">Pruebas con navegadores antiguos</h2> + +<p>Dado que la mayoría de los navegadores ya son compatibles con Flexbox y Grid, puede resultar en efecto difícil hacer pruebas con navegadores más antiguos. Una forma es utilizar una herramienta de prueba en línea como Sauce Labs, como se detalla en el módulo de <a href="/es/docs/Learn/Herramientas_y_pruebas/Cross_browser_testing">comprobación de compatibilidad entre navegadores</a>.</p> + +<p>También puedes descargar e instalar máquinas virtuales y ejecutar versiones anteriores de navegadores en un entorno de tu propio ordenador. Tener acceso a versiones anteriores de Internet Explorer es particularmente útil, y para ese propósito, Microsoft ha puesto a disposición de los usuarios una <a href="https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/">variedad de máquinas virtuales de descarga gratuita</a>. Están disponibles para los sistemas operativos Mac, Windows y Linux, por lo que resultan una manera excelente de hacer pruebas con los navegadores Windows antiguos y modernos, incluso si no utilizas una computadora con sistema Windows.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahora tienes el conocimiento para usar con confianza técnicas como Grid y Flexbox, crear soluciones alternativas para navegadores más antiguos y utilizar cualquier técnica nueva que pueda surgir en el futuro.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://hacks.mozilla.org/2016/08/using-feature-queries-in-css/">Uso de consultas de propiedades en CSS</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Backwards_Compatibility_of_Flexbox">Compatibilidad con versiones anteriores de Flexbox</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout/CSS_Grid_and_Progressive_Enhancement">Compaginación en cuadrícula CSS y mejora progresiva</a></li> + <li><a href="https://www.smashingmagazine.com/2017/11/css-grid-supporting-browsers-without-grid/">Uso de CSS Grid: Compatibilidad con navegadores sin comportamiento de cuadrícula</a></li> + <li><a href="https://24ways.org/2012/css3-grid-layout/">Un tutorial que usa las versiones IE10 y 11 de Grid</a></li> + <li><a href="https://rachelandrew.co.uk/archives/2016/11/26/should-i-try-to-use-the-ie-implementation-of-css-grid-layout/">¿Debo tratar de usar la implementación IE10 de Grid Layout?</a></li> + <li><a href="https://24ways.org/2017/cascading-web-design/">Diseño web en cascada con consulta de propiedades</a></li> + <li><a href="https://gridbyexample.com/learn/2016/12/24/learning-grid-day24/">Uso de las consultas de propiedades (vídeo)</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/CSS/CSS_layout/Legacy_Layout_methods", "Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension", "Learn/CSS/CSS_layout")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Introduction">Introducción al diseño CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Normal_Flow">Flujo normal</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Grids">Cuadrícula</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Floats">Flotación</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Positioning">Posicionamiento</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Multiple-column_Layout">Diseño en columnas</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Responsive_Design">Diseño adaptativo</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Media_queries">Guía para principiantes sobre consultas a medios</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Legacy_Layout_Methods">Métodos de compaginación heredados</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Supporting_Older_Browsers">Compatibilidad con navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/CSS/CSS_layout/Fundamental_Layout_Comprehension">Evaluación del conjunto de elementos básicos de compaginación</a></li> +</ul> diff --git a/files/es/learn/css/first_steps/comenzando_css/index.html b/files/es/learn/css/first_steps/comenzando_css/index.html new file mode 100644 index 0000000000..1da9edb582 --- /dev/null +++ b/files/es/learn/css/first_steps/comenzando_css/index.html @@ -0,0 +1,264 @@ +--- +title: Empezar con CSS +slug: Learn/CSS/First_steps/Comenzando_CSS +tags: + - Aprender + - CSS + - Clases + - Ejemplo + - Elementos + - Estado + - Principiante + - Selectores + - Sintaxis +translation_of: Learn/CSS/First_steps/Getting_started +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/First_steps/What_is_CSS", "Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps")}}</div> + +<p class="summary">En este artículo aplicaremos CSS a un documento HTML sencillo para aprender algunos elementos prácticos sobre este lenguaje.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajo con archivos</a> y conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender los conceptos básicos para vincular un documento CSS a un archivo HTML y dar a un texto un formato sencillo con CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="Empezamos_con_algo_de_HTML">Empezamos con algo de HTML</h2> + +<p>Nuestro punto de partida es un documento HTML. Puedes copiar el código de abajo si quieres trabajar en tu ordenador. Guarda el siguiente código como <code>index.html</code> en una carpeta de tu equipo.</p> + +<pre class="brush: html notranslate"><!doctype html> +<html lang="es"> +<head> + <meta charset="utf-8"> + <title>Empezamos con el CSS</title> +</head> + +<body> + + <h1>Soy un título de nivel uno</h1> + + <p>Este es un párrafo de texto. En el texto hay un <span>elemento span</span> +y también un <a href="http://example.com">enlace</a>.</p> + + <p>Este es el segundo párrafo. Contiene un elemento <em>destacado</em>.</p> + + <ul> + <li>Punto uno</li> + <li>Punto dos</li> + <li>Punto <em>tres</em></li> + </ul> + +</body> + +</html> +</pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Si lees esto en un dispositivo o un entorno donde no puedes crear archivos fácilmente, no te preocupes. A continuación hay editores de código en vivo que van a permitirte escribir ejemplos de código en esta misma página.</p> +</div> + +<h2 id="Agregar_CSS_a_un_documento">Agregar CSS a un documento</h2> + +<p>Lo primero que se debe hacer es decirle al documento HTML que hay algunas reglas CSS que queremos que use. Hay tres formas diferentes de aplicar CSS a un documento HTML, sin embargo, por ahora, veremos la forma más habitual y útil de hacerlo: vincular el CSS desde el encabezado del documento.</p> + +<p>Crea un archivo en la misma carpeta que tu documento HTML y guárdalo como <code>styles.css</code>. La extensión <code>.css</code> muestra que es un archivo CSS.</p> + +<p>Para vincular <code>styles.css</code> a <code>index.html</code>, añade la siguiente línea en algún lugar dentro del {{htmlelement ("head")}} del documento HTML:</p> + +<pre class="brush: html notranslate"><link rel="stylesheet" href="styles.css"></pre> + +<p>Este elemento {{htmlelement ("link")}} le dice al navegador que hay una hoja de estilo con el atributo <code>rel</code> y la ubicación de esa hoja de estilo como el valor del atributo <code>href</code>. Puedes probar si el CSS funciona añadiendo una regla a <code>styles.css</code>. Usando el editor de código, añade lo siguiente al archivo CSS:</p> + +<pre class="brush: css notranslate">h1 { + color: red; +}</pre> + +<p>Guarda los archivos HTML y CSS antes de volver a cargar la página en un navegador web. Ahora el título de nivel uno de la parte superior del documento debería ser rojo. Si esto sucede, ¡felicidades!: has aplicado correctamente un poco de CSS a un documento HTML. Si no lo hace, verifica que hayas escrito todo correctamente.</p> + +<p>Puedes continuar trabajando en <code>styles.css</code> localmente o usar nuestro editor interactivo para continuar con este tutorial. El editor interactivo actúa como si el CSS del primer panel estuviera vinculado al documento HTML, tal como lo hemos hecho con el documento anterior.</p> + +<h2 id="Dar_formato_a_elementos_HTML">Dar formato a elementos HTML</h2> + +<p>Al poner nuestro título de encabezado en rojo, ya hemos demostrado que podemos elegir un elemento HTML y darle formato. Hacemos esto con un <em>selector de elementos</em>: un selector que coincide directamente con el nombre de un elemento HTML. Para determinar todos los párrafos del documento, se usa el selector <code>p</code>. Para hacer que todos los párrafos se vean verdes se usa:</p> + +<pre class="brush: css notranslate">p { + color: green; +}</pre> + +<p>Puedes determinar múltiples selectores a la vez, separándolos con una coma. Si queremos que todos los párrafos y todos los elementos de la lista sean verdes, el código se verá así:</p> + +<pre class="brush: css notranslate">p, li { + color: green; +}</pre> + +<p>Pruébalo en el editor interactivo que encontrarás a continuación (edita los cuadros de código) o en tu documento CSS.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/started1.html", '100%', 900)}} </p> + +<h2 id="Cambiar_el_comportamiento_predeterminado_de_los_elementos">Cambiar el comportamiento predeterminado de los elementos</h2> + +<p>Cuando miramos un documento HTML bien marcado, incluso con algo tan simple como nuestro ejemplo, podemos ver que el navegador facilita la legibilidad de este documento HTML al añadir un estilo predeterminado. Los títulos se muestran grandes y en negrita, y la lista tiene viñetas. Esto sucede porque los navegadores tienen hojas de estilo internas que contienen estilos predeterminados, los cuales se aplican a todas las páginas por defecto. Sin ellos, todo el texto se uniría en un grupo y tendríamos que darle formato desde cero. Todos los navegadores modernos muestran el contenido HTML por defecto de la misma manera.</p> + +<p>Sin embargo, a menudo querrás algo diferente a la elección que ha hecho el navegador. Esto se puede solucionar con el simple hecho de escoger el elemento HTML que deseas cambiar y utilizar una regla CSS para cambiar su apariencia. Un buen ejemplo es <code><ul></code>, que muestra una lista desordenada. Tiene viñetas y, si decidimos que no las queremos, podemos eliminarlas de este modo:</p> + +<pre class="brush: css notranslate">li { + list-style-type: none; +}</pre> + +<p>Ahora, intenta añadir esto a tu CSS.</p> + +<p>Es muy conveniente consultar en MDN la propiedad <code>list-style-type</code> para ver qué valores admite. Echa un vistazo a la página de <code><a href="/en-US/docs/Web/CSS/list-style-type">list-style-type</a></code> y encontrarás un ejemplo interactivo en la parte superior para probar diferentes valores (todos los permitidos se detallan más abajo en esa misma página).</p> + +<p>Al mirar esa página, descubrirás que, además de eliminar las viñetas de la lista, también puedes cambiarlas. Intenta cambiarlas por unas cuadradas utilizando el valor <code>square</code>.</p> + +<h2 id="Añadir_una_clase">Añadir una clase</h2> + +<p>Hasta ahora, hemos utilizado elementos cuyo nombre se basa en el nombre de elemento que reciben en HTML. Esto funciona siempre que se desee que todos los elementos de ese tipo tengan el mismo aspecto en el documento. La mayoría de las veces no es el caso, por lo que deberás encontrar una manera de seleccionar un subconjunto de los elementos sin que cambien los demás. La forma más común de hacer esto es añadir una clase al elemento HTML y determinarla.</p> + +<p>En tu documento HTML, añade al segundo elemento de la lista un <a href="/es/docs/Web/HTML/Atributos_Globales/class">atributo de clase</a>. Debería verse así:</p> + +<pre class="brush: html notranslate"><ul> + <li>Punto uno</li> + <li <strong>class = "special"</strong>>Punto dos</li> + <li>Punto <em>tres</em></li> +</ul></pre> + +<p>En tu CSS, puedes seleccionar una clase <code>special</code> creando un selector que comience con un carácter de punto final. Añade lo siguiente a tu archivo CSS:</p> + +<pre class="brush: css notranslate">.special { + color: orange; + font-weight: bold; +}</pre> + +<p>Guarda y actualiza para ver cuál es el resultado.</p> + +<p>Puedes aplicar la clase <code>special</code> a cualquier elemento de la página que desees que tenga el mismo aspecto que este elemento de lista. Por ejemplo, es posible que desees que el <code><span></code> del párrafo también sea naranja y en negrita. Intenta añadirle una <code>class</code> <code>special</code>, luego vuelve a cargar la página y observa qué sucede.</p> + +<p>A veces verás reglas con un selector que enumera el selector de elementos HTML junto con la clase:</p> + +<pre class="brush: css notranslate">li.special { + color: orange; + font-weight: bold; +}</pre> + +<p>Esta sintaxis significa «determina cualquier elemento <code>li</code> que tenga una clase special». Si hicieras esto, ya no podrías aplicar la clase a un elemento <code><span></code> u otro elemento simplemente añadiéndole la clase; tendrías que añadir ese elemento a la lista de selectores:</p> + +<pre class="brush: css notranslate">li.special, +span.special { + color: orange; + font-weight: bold; +}</pre> + +<p>Como puedes imaginar, algunas clases pueden aplicarse a muchos elementos y no queremos tener que seguir editando el CSS cada vez que algo nuevo necesita adoptar ese estilo. Por lo tanto, a veces es mejor eludir el elemento y simplemente referirse a la clase, a menos que sepas que vas a querer crear algunas reglas especiales para un solo elemento y tal vez quieras asegurarte de que no se apliquen a otros elementos.</p> + +<h2 id="Dar_formato_según_la_ubicación_en_un_documento">Dar formato según la ubicación en un documento</h2> + +<p>Hay momentos en los que querrás que algo se vea diferente en función de dónde esté en el documento. Hay múltiples selectores que pueden hacerlo, pero por ahora veremos solo un par. En nuestro documento hay dos elementos <code><em></code>: uno dentro de un párrafo y el otro dentro de un elemento de la lista. Para seleccionar solo un <code><em></code> que esté anidado dentro de un elemento <code><li></code>, podemos usar un selector llamado <strong>combinador descendente</strong>, que simplemente toma la forma de un espacio entre otros dos selectores.</p> + +<p>Añade la siguiente regla a la hoja de estilo.</p> + +<pre class="brush: css notranslate">li em { + color: rebeccapurple; +}</pre> + +<p>Este selector separará cualquier elemento <code><em></code> que esté dentro de (un descendiente de) <code><li></code>. Entonces, en tu documento de ejemplo, deberías encontrar que el <code><em></code> del tercer elemento de la lista es morado, pero el que hay en el párrafo no ha cambiado.</p> + +<p>Otra cosa que puedes probar es dar formato un párrafo que venga directamente a continuación de un título que esté en el mismo nivel de jerarquía en el HTML. Para hacerlo, coloca un <code>+</code> (un <strong>combinador hermano adyacente</strong>) entre los selectores.</p> + +<p>Intenta añadir también esta regla a la hoja de estilo:</p> + +<pre class="brush: css notranslate">h1 + p { + font-size: 200%; +}</pre> + +<p>El ejemplo que encontrarás a continuación incluye las dos reglas anteriores. Intenta añadir una regla para que un <code>span</code> dentro de un párrafo se vuelva rojo. Sabrás si lo has hecho bien si el <code><span></code> en el primer párrafo se vuelve rojo pero el que hay en el primer elemento de la lista no cambia de color.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/started2.html", '100%', 1100)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Como puedes ver, el CSS nos ofrece varias formas de seleccionar elementos, y hasta ahora solo hemos arañado la superficie. Examinaremos todos estos selectores y muchos más en los artículos correspondientes a <a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS">Selectores</a> que encontrarás más adelante.</p> +</div> + +<h2 id="Dar_formato_según_el_estado">Dar formato según el estado</h2> + +<p>El último tipo de estilo que veremos en este tutorial es la capacidad de dar formato a los elementos en función de su estado. Un ejemplo sencillo es el estilo de los enlaces. Cuando damos formato a un enlace, necesitamos seleccionar el elemento <code><a href="/en-US/docs/Web/HTML/Element/a"><a></a></code> (anclaje). Tiene diferentes estados dependiendo de si se ha visitado o no, se pasa por encima, o se presiona con el teclado o se hace clic (se activa). Puedes usar CSS para dar formato a estos diferentes estados. El CSS que encontrarás a continuación presenta en color rosa los enlaces que no se han visitado y en verde los que sí.</p> + +<pre class="brush: css notranslate">a:link { + color: pink; +} + +a:visited { + color: green; +}</pre> + +<p>Puedes cambiar la apariencia del enlace, por ejemplo, eliminando el subrayado, lo que se logra mediante la siguiente regla:</p> + +<pre class="brush: css notranslate">a:hover { + text-decoration: none; +}</pre> + +<p>En el ejemplo que encontrarás a continuación, puedes jugar con diferentes valores para los distintos estados de un enlace. Hemos añadido las reglas anteriores y ahora nos damos cuenta de que el color rosa es demasiado claro y difícil de leer, ¿por qué no cambiarlo a otro que se vea mejor? ¿Puedes poner los enlaces en negrita?</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/started3.html", '100%', 900)}} </p> + +<p>Hemos eliminado el subrayado del enlace cuando el ratón se pasa por encima, y se puede eliminar de todos los estados de un enlace. Sin embargo, vale la pena recordar que en una página web real deberás asegurarte de que los visitantes sepan reconocer que se trata de un enlace. Que aparezca subrayado puede ser una pista importante para que las personas se den cuenta de que pueden hacer clic en una palabra dentro del párrafo, ya que es a lo que están acostumbrados. Al igual que con todo en CSS, existe la posibilidad de que tus cambios resten accesibilidad al documento. Intentaremos resaltar estas posibles dificultades en los lugares apropiados.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: a menudo verás que se menciona la <a href="/es/docs/Learn/Accessibility">accesibilidad</a> en estas lecciones y en MDN. Cuando hablamos de accesibilidad nos referimos al requisito de que nuestras páginas web sean comprensibles y usables para todas las personas.</p> + +<p>Puede que tu visitante acceda a la página desde un ordenador con ratón o trackpad, o un teléfono inteligente con pantalla táctil. O puede que use un lector de pantalla que lea el contenido del documento, así como puede que necesite un tamaño de texto más grande o navegar por la página usando solo el teclado.</p> + +<p>Un documento HTML simple es, generalmente, accesible para todos. Es importante que el documento no pierda accesibilidad a medida que vayas aplicándole estilo.</p> +</div> + +<h2 id="Combinaciones_de_selectores_y_combinadores">Combinaciones de selectores y combinadores</h2> + +<p>Vale la pena señalar que puedes hacer múltiples combinaciones de selectores y combinadores. Por ejemplo:</p> + +<pre class="brush: css notranslate">/* selecciona cualquier elemento <span> que se encuentre dentro de un <p>, que esté dentro de un <artículo> */ +artículo p span { ... } + +/* selecciona cualquier <p> que se encuentre directamente después de <ul>, que va directamente después de <h1> */ +h1 + ul + p { ... }</pre> + +<p>También puedes combinar varios tipos juntos. Intenta añadir lo siguiente al código:</p> + +<pre class="brush: css notranslate">body h1 + p .special { + color: yellow; + background-color: black; + padding: 5px; +}</pre> + +<p>Dará formato a cualquier elemento con la clase <code>special</code>, dentro de un elemento <code><p></code> que venga justo después de <code><h1></code>, el cual se encuentra dentro de <code><body></code>. ¡Uf!</p> + +<p>En el HTML original que proporcionamos, el único elemento al que esto aplica estilo es <code><span class="special"></code>.</p> + +<p>No te preocupes si ahora mismo te parece complicado: irás acostumbrarte a medida que escribas más CSS.</p> + +<h2 id="Para_terminar">Para terminar</h2> + +<p>En este tutorial, hemos visto varias formas con las que se puede diseñar un documento usando CSS. Desarrollaremos este conocimiento a medida que avancemos con el resto de las lecciones. Sin embargo, ahora ya sabes lo suficiente como para aplicar estilo al texto, aplicar CSS en función de diferentes formas de determinar elementos en el documento y buscar propiedades y valores en la documentación de MDN.</p> + +<p>En el próximo artículo, veremos cómo se estructura el CSS.</p> + +<p>{{PreviousMenuNext("Learn/CSS/First_steps/What_is_CSS", "Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">¿Qué es el CSS?</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Empezar con CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Cómo se estructura el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Cómo funciona el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Pon en práctica tus conocimientos nuevos</a></li> +</ol> diff --git a/files/es/learn/css/first_steps/como_funciona_css/index.html b/files/es/learn/css/first_steps/como_funciona_css/index.html new file mode 100644 index 0000000000..920212e080 --- /dev/null +++ b/files/es/learn/css/first_steps/como_funciona_css/index.html @@ -0,0 +1,156 @@ +--- +title: Cómo funciona CSS +slug: Learn/CSS/First_steps/Como_funciona_CSS +translation_of: Learn/CSS/First_steps/How_CSS_works +--- +<p>{{LearnSidebar}}<br> + {{PreviousMenuNext("Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps/Using_your_new_knowledge", "Learn/CSS/First_steps")}}</p> + +<p class="summary">Hemos aprendido los conceptos básicos de CSS, para qué sirve y cómo escribir hojas de estilo simples. En esta lección vamos a echar un vistazo a cómo un navegador crea una página web a partir de CSS y HTML.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico</a> instalado, conocimientos básicos de cómo <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a> y conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender los conceptos básicos de cómo el navegador analiza el CSS y el HTML y lo que sucede cuando encuentra un CSS que no entiende.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Cómo_funciona_realmente_el_CSS">¿Cómo funciona realmente el CSS?</h2> + +<p>Cuando un navegador muestra un documento, ha de combinar el contenido con la información de estilo del documento. Procesa el documento en una serie de etapas, que enumeraremos a continuación. Ten en cuenta que este es un modelo muy simplificado de lo que sucede cuando un navegador carga una página web y que cada navegador gestiona el proceso de manera diferente. Pero esto es más o menos lo que sucede.</p> + +<ol> + <li>El navegador carga el HTML (por ejemplo, lo recibe de la red).</li> + <li>Convierte el {{Glossary("HTML")}} en un {{Glossary("DOM")}} (<em>Modelo de objetos del documento</em>). El DOM representa el documento en la memoria del ordenador. Lo explicaremos más detalladamente en la sección siguiente.</li> + <li>Entonces, el navegador va a buscar la mayor parte de los recursos vinculados al documento HTML, como las imágenes y los videos incrustados... ¡y también el CSS vinculado! JavaScript aparece un poco más adelante en el proceso, pero no vamos a hablar de ello aún para evitar complicar las cosas.</li> + <li>El navegador analiza el CSS y ordena en diferentes «cubos» las diferentes reglas según el tipo de selector. Por ejemplo, elemento, clase, ID, y así sucesivamente. Para cada tipo de selector que encuentres, calcula qué reglas deben aplicarse y a qué nodos en el DOM se les aplica el estilo según corresponda (este paso intermedio se llama árbol de renderización).</li> + <li>El árbol de renderización presenta la estructura en que los nodos deben aparecer después de aplicarle las reglas.</li> + <li>En la pantalla se muestra el aspecto visual de la página (esta etapa se llama pintura).</li> +</ol> + +<p>El siguiente diagrama ofrece una visión sencilla de este proceso.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/11781/rendering.svg" style="height: auto; max-width: 635px; width: 100%;"></p> + +<h2 id="Acerca_del_DOM">Acerca del DOM</h2> + +<p>Un DOM tiene una estructura en forma de árbol. Cada elemento, atributo o bloque en el lenguaje de marcado se convierte en un {{Glossary("Node/DOM","nodo DOM")}} con estructura de árbol. Los nodos se definen por su relación con otros nodos DOM. Algunos elementos son padres de nodos secundarios, y estos nodos hijos tienen hermanos.</p> + +<p>Comprender el DOM te ayuda a diseñar, depurar y mantener tu CSS porque en el DOM es donde tu CSS se encuentra con el contenido del documento. Cuando comiences a trabajar con las herramientas DevTools (o herramientas del desarrollador) del navegador, te moverás por el DOM mientras seleccionas elementos con el fin de ver qué reglas se aplican.</p> + +<h2 id="Una_representación_real_de_un_DOM">Una representación real de un DOM</h2> + +<p>En lugar de una explicación larga y aburrida, veamos un ejemplo para entender cómo un código HTML se convierte en DOM.</p> + +<p>Tomemos el siguiente código HTML:</p> + +<pre class="brush: html notranslate"><p> + Usaremos: + <span>Hojas</span> + <span>de estilo</span> + <span>en cascada</span> +</p> +</pre> + +<p>En el DOM, el nodo que se corresponde con nuestro elemento <code><p></code> es un padre. Sus hijos son un nodo de texto y los tres nodos correspondientes a nuestros elementos <code><span></code>. Los nodos <code>SPAN</code> son también los <span style="background-color: #f5f6f5;">padres</span>, y los nodos de texto sus hijos:</p> + +<pre class="notranslate">P +├─ "Usaremos:" +├─ SPAN +| └─ "Hojas" +├─ SPAN +| └─ "de estilo" +└─ SPAN + └─ "en cascada" +</pre> + +<p>Así es como un navegador interpreta el código HTML anterior, interpreta el árbol DOM y luego lo muestra en el navegador, así:</p> + +<p>{{EmbedLiveSample('Una_representación_real_de_un_DOM', '100%', 55)}}</p> + +<div class="hidden"> +<pre class="brush: css notranslate">p {margin:0;}</pre> +</div> + +<h2 id="La_aplicación_de_CSS_al_DOM">La aplicación de CSS al DOM</h2> + +<p>Pongamos que hemos añadido un poco de CSS a nuestro documento, para darle estilo. Una vez más, el HTML es el siguiente:</p> + +<pre class="brush: html notranslate"><p> + Usaremos: + <span>Hojas</span> + <span>de estilo</span> + <span>en cascada</span> +</p></pre> + +<p>Supongamos que le aplicamos el CSS siguiente:</p> + +<pre class="brush: css notranslate">span { + border: 1px solid black; + background-color: lime; +}</pre> + +<p>El navegador analizará el código HTML y creará un DOM a partir de este. A continuación, analizará el CSS. Dado que la única regla disponible en el CSS tiene un selector <code>span</code>, el navegador ¡ordenará el CSS muy rápidamente! Aplicará la regla a cada uno de los tres <code><span></code>, que mostrarán en pantalla la representación visual final.</p> + +<p>La salida actualizada es la siguiente:</p> + +<p>{{EmbedLiveSample ( 'La_aplicación_de_CSS_al_DOM', '100%', 55)}}</p> + +<p>En nuestro artículo <a href="/es/docs/Learn/CSS/Building_blocks/Depurar_el_CSS">Depurar el CSS</a> que encontrarás en el siguiente módulo, vamos a utilizar las herramientas DevTools del navegador para depurar posibles problemas en el CSS. También aprenderemos más sobre cómo el navegador interpreta el CSS.</p> + +<h2 id="¿Qué_ocurre_si_un_navegador_encuentra_CSS_que_no_entiende">¿Qué ocurre si un navegador encuentra CSS que no entiende?</h2> + +<p>En una <a href="/es/docs/Learn/CSS/First_steps/Qu%C3%A9_es_CSS#Soporte_del_navegador">lección anterior</a> mencionamos que no todos los navegadores implementan las novedades de CSS en el mismo momento. Además, no todo el mundo utiliza la última versión de un navegador. Dado que el CSS está en desarrollo constante y, por lo tanto, por delante de lo que los navegadores pueden reconocer, puede que te preguntes qué sucede si un navegador encuentra un selector o una declaración CSS que no reconoce.</p> + +<p>La respuesta es que no hace nada y simplemente pasa a la siguiente parte del CSS.</p> + +<p>Si un navegador analiza tus reglas y encuentra una propiedad o un valor que no entiende, lo ignora y avanza hasta la declaración siguiente. Esto sucederá si has cometido un error y has escrito mal una propiedad o un valor, o si la propiedad o el valor son demasiado nuevos y el navegador aún no los admite.</p> + +<p>Del mismo modo, si un navegador encuentra un selector que no entiende, lo ignorará y pasará al siguiente.</p> + +<p>En el siguiente ejemplo hemos utilizado la ortografía británica para la propiedad color, que invalida la propiedad porque no la reconoce. Así que el párrafo no se muestra en azul. Sin embargo, se han aplicado todos los demás estilos del CSS; solo se ha ignorado la línea que no es válida.</p> + +<div id="Skipping_example"> +<pre class="brush: html notranslate"><p>Quiero este texto en grande, en negrita y en color azul.</p></pre> + +<pre class="brush: css notranslate">p { + font-weight: bold; + colour: blue; /* Ortografía incorrecta de la propiedad color */ + font-size: 200%; +}</pre> +</div> + +<p>{{EmbedLiveSample('Skipping_example', '100%', 200)}}</p> + +<p>Este comportamiento es muy útil. Significa que puedes utilizar el CSS nuevo como una mejora, a sabiendas de que no se producirá ningún error si no se entiende: o bien el navegador entiende la característica nueva o no lo hace. Combinado con el funcionamiento del modo en cascada con el hecho de que los navegadores utilizarán la última CSS que encuentren en la hoja de estilo, cuando haya dos reglas con el mismo nivel de especificidad, también puedes ofrecer alternativas para los navegadores que no admiten el CSS nuevo.</p> + +<p>Esto funciona especialmente bien cuando quieres utilizar un valor que es bastante nuevo que no admiten todos los navegadores. Por ejemplo, algunos navegadores antiguos no entienden <code>calc()</code> como valor. Podríamos dar un valor de sustitución para el ancho de una caja en píxeles, y a continuación dar un ancho con un valor <code>calc()</code> de <code>100% - 50px</code>. Los navegadores antiguos usarán la versión en píxeles y harán caso omiso de la indicación <code>calc()</code>, porque no la entienden. Los navegadores nuevos interpretarán la línea del ancho en píxeles, pero la anularán al llegar a la línea de <code>calc()</code> porque aparece después en la cascada.</p> + +<pre class="brush: css notranslate">.box { + width: 500px; + width: calc(100% - 50px); +}</pre> + +<p>En lecciones posteriores veremos muchas más formas de cómo admitir navegadores diferentes.</p> + +<h2 id="Y_finalmente">Y finalmente</h2> + +<p>Casi has terminado este módulo; solo nos queda una cosa más por hacer. En el próximo artículo, <a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">pondrás en práctica tu conocimiento nuevo</a> para cambiar el estilo de un ejemplo y probarte con un poco de CSS en el proceso.</p> + +<p>{{PreviousMenuNext("Learn/CSS/First_steps/How_CSS_is_structured", "Learn/CSS/First_steps/Using_your_new_knowledge", "Learn/CSS/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">¿Qué es CSS?</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Empezar con CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Cómo se estructura el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Cómo funciona el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Pon en práctica tus conocimientos nuevos</a></li> +</ol> diff --git a/files/es/learn/css/first_steps/como_se_estructura_css/index.html b/files/es/learn/css/first_steps/como_se_estructura_css/index.html new file mode 100644 index 0000000000..a3e9bb94b8 --- /dev/null +++ b/files/es/learn/css/first_steps/como_se_estructura_css/index.html @@ -0,0 +1,512 @@ +--- +title: Cómo se estructura el CSS +slug: Learn/CSS/First_steps/Como_se_estructura_CSS +translation_of: Learn/CSS/First_steps/How_CSS_is_structured +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}</div> + +<p class="summary">Ahora que ya sabes qué es el CSS y conoces sus conceptos básicos, es hora de profundizar un poco más en la estructura del lenguaje en sí. Ya hemos visto muchos de los conceptos que aparecen en este artículo; puedes volver para recapitular si más adelante encuentras conceptos confusos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajo con archivos</a>, conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y una idea de <a href="/es/docs/Learn/CSS/First_steps/Como_funciona_CSS">cómo funciona el CSS</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender en detalle las estructuras de sintaxis fundamentales de CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="Aplicar_CSS_al_HTML">Aplicar CSS al HTML</h2> + +<p>Lo primero que veremos son los tres métodos para aplicar CSS a un documento.</p> + +<h3 id="Hoja_de_estilo_externa">Hoja de estilo externa</h3> + +<p>En <a href="/es/docs/Learn/CSS/First_steps/Comenzando_CSS">Empezar con el CSS</a>, vinculamos una hoja de estilo externa a nuestra página. Este es el método más común y útil para adjuntar CSS a un documento, porque puedes vincular el CSS a varias páginas y dar estilo a todas ellas con la misma hoja de estilo. En la mayoría de los casos, las diferentes páginas de un sitio web se verán más o menos iguales, de modo que puedes usar el mismo conjunto de reglas para el aspecto y la interacción básicos.</p> + +<p>Una hoja de estilo externa significa que el CSS está escrito en un archivo independiente con una extensión <code>.css</code> y que lo vinculas desde un elemento <code><link></code> de HTML:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Mi experimento CSS</title> + <link rel="stylesheet" href="styles.css"> + </head> + <body> + <h1>¡Hola, mundo!</h1> + <p>Este es mi primer ejemplo de CSS</p> + </body> +</html></pre> + +<p>El archivo CSS podría parecerse a esto:</p> + +<pre class="brush: css notranslate">h1 { + color: blue; + background-color: yellow; + border: 1px solid black; +} + +p { + color: red; +}</pre> + +<p>El atributo <code>href</code> del elemento {{htmlelement("link")}} tiene que hacer referencia a un archivo de tu sistema de archivos.</p> + +<p>En el ejemplo anterior, el archivo CSS está en la misma carpeta que el documento HTML, pero puedes colocarlo en otro lugar y especificar la ruta adecuada. Por ejemplo:</p> + +<pre class="brush: html notranslate"><!-- Dentro de un subdirectorio llamado styles dentro del directorio de trabajo --> +<link rel="stylesheet" href="styles/style.css"> + +<!-- Dentro de un subdirectorio llamado general, que está en un subdirectorio llamado styles, dentro del directorio de trabajo --> +<link rel="stylesheet" href="styles/general/style.css"> + +<!-- Sube un nivel de directorio, y luego dentro de un subdirectorio llamado styles --> +<link rel="stylesheet" href="../styles/style.css"></pre> + +<h3 id="Hoja_de_estilo_interna">Hoja de estilo interna</h3> + +<p>Una hoja de estilo interna es cuando no hay ningún archivo CSS externo, sino que colocas tu CSS dentro de un elemento {{htmlelement("style")}} contenido dentro del elemento {{htmlelement("head")}} del HTML.</p> + +<p>En este caso, el HTML se vería así:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Mi experimento CSS</title> + <style> + h1 { + color: blue; + background-color: yellow; + border: 1px solid black; + } + + p { + color: red; + } + </style> + </head> + <body> + <h1>¡Hola, mundo!</h1> + <p>Este es mi primer ejemplo de CSS</p> + </body> +</html></pre> + +<p>Esto puede ser útil en algunas circunstancias (tal vez estés trabajando con un sistema de administración de contenido donde no sea posible modificar los archivos CSS directamente), pero no es tan eficiente como las hojas de estilo externas: en una página web, deberías repetir el CSS en cada página y actualizarlo en varios lugares en caso de que hubiera que hacer cambios.</p> + +<h3 id="Estilos_en_línea">Estilos en línea</h3> + +<p>Los estilos en línea son declaraciones CSS que afectan a un solo elemento, contenido dentro de un atributo de <code>style</code>:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Mi experimento CSS</title> + </head> + <body> + <h1 style="color: blue;background-color: yellow;border: 1px solid black;">¡Hola mundo!</h1> + <p style="color:red;">Este es mi primer ejemplo de CSS</p> + </body> +</html></pre> + +<p><strong>¡No hagas esto a menos que realmente tengas que hacerlo!</strong> Es realmente malo a la hora de realizar el mantenimiento (puede que tengas que actualizar la misma información varias veces en un mismo documento), y además mezcla tu información CSS para la presentación con tu información HTML para la estructura, lo que dificulta la lectura y la comprensión del código. Mantener los diferentes tipos de código separados facilita trabajar con ellos.</p> + +<p>Hay ciertos lugares donde los estilos en línea son más comunes, o incluso aconsejables. Es posible que tengas que recurrir a ellos si realmente tu entorno de trabajo es restrictivo (tal vez el CMS solo te permita editar el cuerpo del HTML). También verás que se usan mucho en el correo electrónico en formato HTML para lograr la máxima compatibilidad con el mayor número de clientes.</p> + +<h2 id="Juguemos_con_el_CSS_de_este_artículo">Juguemos con el CSS de este artículo</h2> + +<p>En este artículo hay mucho CSS con el que jugar. Para hacerlo, recomendamos crear un nuevo directorio/carpeta en el ordenador, dentro de la cual deberás crear una copia de los siguientes dos archivos:</p> + +<p><strong>index.html:</strong></p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <title>Mis experimentos CSS</title> + <link rel="stylesheet" href="styles.css"> + </head> + <body> + + <p>Crea tu HTML de prueba aquí</p> + + </body> +</html></pre> + +<p><strong>styles.css:</strong></p> + +<pre class="brush: css notranslate">/* Crea tu CSS de prueba aquí */ + +p { + color: red; +}</pre> + +<p>Entonces, cuando te encuentres con un CSS con el que desees experimentar, reemplaza el contenido <code><body></code> del HTML con algo de HTML sin estilos y añade CSS a tu archivo de CSS para darle estilo.</p> + +<p>Si no estás en un sistema donde puedas crear archivos fácilmente, puedes utilizar el editor interactivo que encontrarás a continuación para experimentar.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/experiment-sandbox.html", '100%', 800)}} </p> + +<p>¡Sigue leyendo y disfruta!</p> + +<h2 id="Selectores">Selectores</h2> + +<p>No se puede hablar de CSS sin mencionar los selectores, de los cuales ya hemos descubierto varios tipos diferentes en la lección <a href="/es/docs/Learn/CSS/First_steps/Comenzando_CSS">Empezar con el CSS</a>. Un selector es, como determinamos, un elemento de nuestro documento HTML para aplicarle estilo. Si los estilos no se aplican correctamente, es probable que el selector no coincida con lo que crees que debería coincidir.</p> + +<p>Cada regla CSS comienza con un selector o una lista de selectores que indican al navegador a qué elemento o elementos deben aplicarse dichas reglas. Todos los siguientes son ejemplos de selectores válidos o listas de selectores.</p> + +<pre class="brush: css notranslate">h1 +a:link +.manythings +#onething +* +.box p +.box p:first-child +h1, h2, .intro</pre> + +<p><strong>Prueba a crear algunas reglas CSS que usen los selectores anteriores y algo de HTML sin estilos. Si no conoces alguna de las sintaxis anteriores, ¡prueba a buscarla en MDN!</strong></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Aprenderás mucho más sobre los selectores en nuestros tutoriales sobre <a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS">selectores CSS</a> de la próxima lección.</p> +</div> + +<h3 id="Especificidad">Especificidad</h3> + +<p>A menudo habrá situaciones en las que dos selectores podrían determinar un mismo elemento HTML. Considera la siguiente hoja de estilo, en que definimos una regla con un selector <code>p</code> que establecerá los párrafos en color azul, y también una clase que establecerá los elementos seleccionados en color rojo.</p> + +<pre class="brush: css notranslate">.special { + color: red; +} + +p { + color: blue; +}</pre> + +<p>Digamos que en nuestro documento HTML hay un párrafo con una clase <code>special</code>. Ambas reglas podrían aplicarse. ¿Cuál ganará? ¿De qué color crees que será nuestro párrafo?</p> + +<pre class="brush: html notranslate"><p class="special">¿De qué color soy?</p></pre> + +<p>El lenguaje CSS tiene reglas para controlar cuál ganará en caso de colisión; reciben el nombre de <strong>cascada</strong> y <strong>especificidad</strong>. En el siguiente bloque de códigos hemos definido dos reglas para el selector <code>p</code>, pero el párrafo termina siendo de color azul. Esto se debe a que la declaración que lo establece en azul aparece más abajo en la hoja de estilo, y los estilos posteriores anulan a los anteriores. Así funciona la regla de la cascada.</p> + +<pre class="brush: css notranslate">p { + color: red; +} + +p { + color: blue; +}</pre> + +<p>Sin embargo, en el caso de nuestro primer bloque, que contiene un selector de clase y otro de elementos, la clase ganará. Esto hará que el párrafo sea rojo, incluso aunque aparezca antes en la hoja de estilo. Una clase se describe de forma más específica o con más especificidad que el selector de elementos, razón por la que gana.</p> + +<p><strong>Prueba el ejemplo anterior: añade el HTML a tu experimento, luego pon las dos reglas <code>p { ... }</code> a tu hoja de estilo. A continuación, cambia el primer selector <code>p</code> por <code>.special</code> para ver cómo cambia el estilo.</strong></p> + +<p>Las reglas de especificidad y de cascada pueden parecer un poco complicadas al principio. Son más fáciles de entender a medida que se van adquiriendo conocimientos de CSS. En nuestro artículo sobre <a href="/es/docs/Learn/CSS/Building_blocks/Cascada_y_herencia">Cascada y herencia</a>, que abordaremos en la próxima lección, se explicará en detalle, incluyendo cómo calcular la especificidad. Por ahora, solo has de saber que existe y que a veces el CSS no se aplica como esperas porque algo más en la hoja de estilo tiene una mayor especificidad. El hecho de identificar que más de una regla podría aplicarse a un elemento es el primer paso para solucionar estos problemas.</p> + +<h2 id="Propiedades_y_valores">Propiedades y valores</h2> + +<p>En su nivel más básico, el CSS consta de dos componentes básicos:</p> + +<ul> + <li><strong>Propiedades</strong>: Identificadores legibles por los humanos que indican qué características de estilo (por ejemplo, <code><a href="/en-US/docs/Web/CSS/font-size">font-size</a></code>, <code><a href="/en-US/docs/Web/CSS/width">width</a></code>, <code><a href="/en-US/docs/Web/CSS/background-color">background-color</a></code>) deseas cambiar.</li> + <li><strong>Valores</strong>: A cada propiedad especificada se le asigna un valor que indica cómo quieres que cambien esas características de estilo (por ejemplo, lo que quieres que cambie de la fuente, el ancho o el color de fondo).</li> +</ul> + +<p>La siguiente imagen resalta una sola propiedad y valor. El nombre de la propiedad es <code>color</code> y el valor <code>blue</code>.</p> + +<p><img alt="Una declaración resaltada en el CSS" src="https://mdn.mozillademos.org/files/16498/declaration.png" style="border: 1px solid #cccccc; display: block; height: 218px; margin: 0 auto; width: 471px;"></p> + +<p>Una propiedad emparejada con un valor se denomina <em>declaración CSS</em>. Las declaraciones CSS se colocan dentro de los <em>bloques de declaración CSS</em>. La siguiente imagen muestra nuestro CSS con el bloque de declaración resaltado.</p> + +<p><img alt="Un bloque de declaración resaltado" src="https://mdn.mozillademos.org/files/16499/declaration-block.png" style="border: 1px solid #cccccc; display: block; height: 218px; margin: 0 auto; width: 471px;"></p> + +<p>Finalmente, los bloques de declaración CSS se combinan con <em>selectores</em> para producir <em>conjuntos de reglas CSS</em> (o <em>reglas CSS</em>). Nuestra imagen contiene dos reglas, una para el selector <code>h1</code> y otra para el selector <code>p</code>. La regla para <code>h1</code> está resaltada.</p> + +<p><img alt="La regla para h1 resaltada" src="https://mdn.mozillademos.org/files/16500/rules.png" style="border: 1px solid #cccccc; display: block; height: 218px; margin: 0 auto; width: 471px;"></p> + +<p>Establecer las propiedades de CSS según valores específicos es la función principal del lenguaje CSS. El motor CSS calcula qué declaraciones se aplican a cada elemento de una página para darle la compaginación y los estilos adecuados.</p> + +<div class="blockIndicator warning"> +<p><strong>Importante:</strong> Las propiedades y valores de CSS son sensibles a mayúsculas y minúsculas. La propiedad y el valor de cada par están separados por dos puntos (<code>:</code>).</p> +</div> + +<p><strong>Prueba a buscar diferentes valores de las siguientes propiedades y escribe reglas CSS que se puedan aplicar a diferentes elementos HTML: </strong></p> + +<ul> + <li><strong>{{cssxref("font-size")}}</strong></li> + <li><strong>{{cssxref("width")}}</strong></li> + <li><strong>{{cssxref("background-color")}}</strong></li> + <li><strong>{{cssxref("color")}}</strong></li> + <li><strong>{{cssxref("border")}}</strong></li> +</ul> + +<div class="warning"> +<p><strong>Importante</strong>: Si una propiedad es desconocida o si un valor no es válido para una propiedad determinada, la declaración se considera <em>inválida</em> y el motor CSS del navegador la ignora por completo.</p> +</div> + +<div class="warning"> +<p><strong>Importante</strong>: En CSS (y otros estándares web) se ha acordado establecer como estándar la ortografía en inglés de los EE. UU. para solucionar las incertidumbres idiomáticas. Por ejemplo, <em>siempre</em> hay que escribir <code>color</code>. Si se escribe <code>colour</code>, no funcionará.</p> +</div> + +<h3 id="Las_funciones">Las funciones</h3> + +<p>Si bien la mayoría de valores son palabras clave relativamente simples o valores numéricos, es posible que algunos valores tomen la forma de una función. Un ejemplo sería la función <code>calc()</code>. Esta función te permite hacer operaciones matemáticas sencillas desde tu CSS, por ejemplo:</p> + +<div id="calc_example"> +<pre class="brush: html notranslate"><div class="external"> <div class="box">La caja interior es del 90% - 30px.</div></div></pre> + +<pre class="brush: css notranslate">.outer { + border: 5px solid black; +} + +.box { + padding: 10px; + width: calc(90% - 30px); + background-color: rebeccapurple; + color: white; +}</pre> +</div> + +<p>Esto se traduce así:</p> + +<p>{{EmbedLiveSample('calc_example', '100%', 200)}}</p> + +<p>Una función consta del nombre de la función y, a continuación, unos paréntesis entre los que se colocan los valores permitidos para esa función. En el caso del ejemplo <code>calc()</code> anterior, pedimos que el ancho de esta caja sea del 90% del ancho del bloque que la contiene, menos 30 píxeles. Esto no es algo que podamos calcular con anticipación y simplemente introducir el valor en el CSS, ya que no sabemos cuál será el 90%. Como con todos los valores, la página correspondiente del proyecto MDN tendrá ejemplos de uso para que puedas ver cómo funciona.</p> + +<p>Otro ejemplo serían los diversos valores para {{cssxref ("transform")}}, como <code>rotate()</code>.</p> + +<div id="transform_example"> +<pre class="brush: html notranslate"><div class="box"></div></pre> + +<pre class="brush: css notranslate">.box { + margin: 30px; + width: 100px; + height: 100px; + background-color: rebeccapurple; + transform: rotate(0.8turn) +}</pre> +</div> + +<p>El resultado del código anterior se ve así:</p> + +<p>{{EmbedLiveSample('transform_example', '100%', 200)}}</p> + +<p><strong>Prueba a buscar diferentes valores de las siguientes propiedades y escribe reglas CSS que se apliquen a diferentes elementos HTML: </strong></p> + +<ul> + <li><strong>{{cssxref("transform")}}</strong></li> + <li><strong>{{cssxref ("background-image")}}, en particular a valores de gradiente</strong></li> + <li><strong>{{cssxref("color")}}, en particular a valores rgb/rgba/hsl/hsla</strong></li> +</ul> + +<h2 id="rules">@rules</h2> + +<p>Las <code><a href="/es/docs/Web/CSS/At-rule">@rules</a></code> (leído "at-rules" en inglés) dan al CSS algunas instrucciones sobre cómo comportarse. Algunas <code>@rules</code> son simples, con el nombre de la regla y un valor. Por ejemplo, para importar una hoja de estilo adicional a tu hoja de estilo CSS principal, puedes usar <code>@import</code>:</p> + +<pre class="brush: css notranslate">@import 'styles2.css';</pre> + +<p>Una de las <code>@rules</code> más comunes con las que te encontrarás es <code>@media</code>, que permite usar <a href="/es/docs/Web/CSS/Media_Queries">consultas a medios</a> para aplicar CSS solo cuando se dan ciertas condiciones (por ejemplo, cuando la resolución de la pantalla supera un valor determinado o la anchura supera un valor concreto).</p> + +<p>En el CSS que se muestra a continuación, tenemos una hoja de estilo que le da al elemento <code><body></code> un color de fondo rosado. Sin embargo, luego usamos <code>@media</code> para crear una sección de nuestra hoja de estilo que solo se aplicará en los navegadores con una ventana gráfica de más de 30em de ancho. Si el navegador es más ancho que 30em, el color de fondo será azul.</p> + +<pre class="brush: css notranslate">body { + background-color: pink; +} + +@media (min-width: 30em) { + body { + background-color: blue; + } +}</pre> + +<p>Encontrarás otras <code>@rules</code> a lo largo de estas lecciones.</p> + +<p><strong>Prueba a añadir una consulta a medios en tu CSS que cambie los estilos según el ancho de la ventana gráfica. Cambia el ancho de la ventana de tu navegador para ver el resultado.</strong></p> + +<h2 id="Abreviaturas">Abreviaturas</h2> + +<p>Algunas propiedades como {{cssxref("font")}}, {{cssxref("background")}}, {{cssxref("padding")}}, {{cssxref("border")}} y {{ cssxref("margin")}} se llaman <strong>propiedades abreviadas</strong>. Esto se debe a que permiten establecer varios valores de propiedad en una sola línea, lo que ahorra tiempo y ordena el código.</p> + +<p>Por ejemplo, esta línea:</p> + +<pre class="brush: css notranslate">/* En propiedades abreviadas con 4 valores, como margin y padding (relleno), los valores se aplican + según el orden: arriba, derecha, abajo e izquierda (en sentido horario desde la parte superior). También hay otros + tipos de abreviaturas, como las propiedades abreviadas con 2 valores que establecen el relleno/margen, + arriba/abajo, y luego izquierda/derecha */ +padding: 10px 15px 15px 5px;</pre> + +<p>Hace lo mismo que todas estas juntas:</p> + +<pre class="brush: css notranslate">padding-top: 10px; +padding-right: 15px; +padding-bottom: 15px; +padding-left: 5px;</pre> + +<p>Mientras que esta línea:</p> + +<pre class="brush: css notranslate">background: red url(bg-graphic.png) 10px 10px repeat-x fixed;</pre> + +<p>Hace lo mismo que todas estas juntas:</p> + +<pre class="brush: css notranslate">background-color: red; +background-image: url(bg-graphic.png); +background-position: 10px 10px; +background-repeat: repeat-x; +background-scroll: fixed;</pre> + +<p>Ahora mismo no pretendemos enseñarlos exhaustivamente: encontrarás muchos ejemplos más adelante en el curso. Te aconsejamos que busques los nombres de las propiedades abreviadas en nuestra <a href="/es/docs/Web/CSS/Referencia_CSS">referencia CSS</a> para obtener más información.</p> + +<p><strong>Prueba a añadir las declaraciones anteriores a tu CSS para ver cómo afecta al estilo de tu HTML. Experimenta con diferentes valores.</strong></p> + +<div class="blockIndicator warning"> +<p><strong>Advertencia</strong>: Si bien las propiedades abreviadas a menudo permiten ahorrarte valores, luego restablecerán a sus valores iniciales cualquier valor que no incluyas. Esto asegura que se use un conjunto de valores razonable. Sin embargo, puede resultar confuso si esperas que la propiedad abreviada solo cambie los valores que has introducido.</p> +</div> + +<h2 id="Comentarios">Comentarios</h2> + +<p>Al igual que con el HTML, te recomendamos que hagas comentarios en tu CSS para que te ayuden a comprender cómo funciona su código cuando vuelvas a utilizarlo al cabo de varios meses, así como para ayudar a otros que vayan a trabajar con él a entenderlo.</p> + +<p>Los comentarios en el CSS comienzan con <code>/*</code> y terminan con <code>*/</code>. En el bloque de código que encontrarás a continuación, hemos usado comentarios para marcar el inicio de las diferentes secciones de código. Esto es útil para ayudarnos a movernos por la base de código a medida que aumenta: puedes buscar los comentarios en tu editor de código.</p> + +<pre class="brush: css notranslate">/* con elementos básicos de aplicación de estilo */ +/* -------------------------------------------------------------------------------------------- */ +body { + font: 1em/150% Helvética, Arial, sans-serif; + padding: 1em; + margin: 0 auto; + max-width: 33em; +} + +@media (min-width: 70em) { + /* Prestemos especial atención al tamaño de fuente global. En una pantalla o una ventana grande, + aumentamos el tamaño de la fuente para conseguir una mejor legibilidad */ + body { + font-size: 130%; + } +} + +h1 {font-size: 1.5em;} + +/* Familiarización con algunos elementos anidados específicos en el DOM */ +/* -------------------------------------------------------------------------------------------- */ +div p, #id:first-line { + background-color: red; + border-radius: 3px; +} + +div p { + margin: 0; + padding: 1em; +} + +div p + p { + padding-top: 0; +}</pre> + +<p>Los comentarios también son útiles para <em>comentar</em> temporalmente ciertas partes del código con fines de prueba, por ejemplo, si tratas de encontrar qué parte de tu código causa un error. En el siguiente ejemplo, hemos comentado las reglas para el selector <code>.special</code>.</p> + +<pre class="brush: css notranslate">/*.special { + color: red; +}*/ + +p { + color: blue; +}</pre> + +<p><strong>Añade algunos comentarios al CSS para acostumbrarte a usarlos.</strong></p> + +<h2 id="Espacio_en_blanco">Espacio en blanco</h2> + +<p>Por espacio en blanco nos referimos los espacios en sí, tabuladores y retornos de carro o intros. De la misma manera que el HTML, el navegador ignora el espacio en blanco dentro del CSS. El valor del espacio en blanco es que puede mejorar la legibilidad.</p> + +<p>En el siguiente ejemplo, cada declaración (y el principio/fin de regla) está en una línea propia; esta es posiblemente una buena forma de escribir el CSS, ya que facilita el mantenimiento y la comprensión:</p> + +<pre class="brush: css notranslate">body { + font: 1em/150% Helvética, Arial, sans-serif; + padding: 1em; + margin: 0 auto; + max-width: 33em; +} + +@media (min-width: 70em) { + body { + font-size: 130%; + } +} + +h1 { + font-size: 1.5em; +} + +div p, +#id:first-line { + background-color: red; + border-radius: 3px; +} + +div p { + margin: 0; + padding: 1em; +} + +div p + p { + padding-top: 0; +} +</pre> + +<p id="Very_compact">Podrías escribir exactamente el mismo CSS eliminando la mayoría de los espacios en blanco; este bloque de código es funcionalmente idéntico al primer ejemplo, pero seguro que estarás de acuerdo en que resulta algo más difícil de leer:</p> + +<pre class="brush: css notranslate">body {font: 1em/150% Helvetica, Arial, sans-serif; padding: 1em; margin: 0 auto; max-width: 33em;} +@media (min-width: 70em) { body {font-size: 130%;} } + +h1 {font-size: 1.5em;} + +div p, #id:first-line {background-color: red; border-radius: 3px;} +div p {margin: 0; padding: 1em;} +div p + p {padding-top: 0;} +</pre> + +<p>La manera que elijas para disponer el código suele ser una preferencia personal, aunque cuando comiences a trabajar en equipo es posible que encuentres que el equipo ya tiene su propia guía de estilo que especifica una convención acordada a seguir.</p> + +<div class="blockIndicator warning"> +<p><strong>Importante:</strong> Aunque los valores de las declaraciones CSS se separan por espacios, <strong>los nombres de propiedad nunca tienen espacios</strong>.</p> +</div> + +<p>Por ejemplo, las siguientes declaraciones de CSS son válidas:</p> + +<pre class="brush: css notranslate">margin: 0 auto; +padding-left: 10px;</pre> + +<p>Pero las siguientes no lo son:</p> + +<pre class="brush: css notranslate">margin: 0auto; +padding- left: 10px;</pre> + +<p>¿Ves los errores de espaciado? <code>0auto</code> no se reconoce como un valor válido para la propiedad de <code>margin</code> (<code>0</code> y <code>auto</code> son dos valores separados) y el navegador no reconoce <code>padding-</code> como una propiedad válida. El valor correcto de propiedad (<code>padding-left</code>) se ha separado por un espacio perdido.</p> + +<p>Debes asegurarte siempre de separar los valores distintos entre sí por al menos un espacio, pero mantén los nombres de las propiedades y los valores de las propiedades juntos.</p> + +<p><strong>Prueba a jugar con los espacios en blanco de tu CSS y observa qué es lo que se rompe y lo que no.</strong></p> + +<h2 id="¿Qué_sigue">¿Qué sigue?</h2> + +<p>Resulta útil entender un poco cómo el navegador toma tu HTML y tu CSS y los convierte en una página web, razón por la cual en el próximo artículo (<a href="/es/docs/Learn/CSS/First_steps/Como_funciona_CSS">Cómo funciona el CSS</a>) veremos ese proceso.</p> + +<p>{{PreviousMenuNext("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}</p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">¿Qué es el CSS?</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Empezar con el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Cómo se estructura el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Cómo funciona CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Pon en práctica tus conocimientos nuevos</a></li> +</ol> diff --git a/files/es/learn/css/first_steps/index.html b/files/es/learn/css/first_steps/index.html new file mode 100644 index 0000000000..0213277d94 --- /dev/null +++ b/files/es/learn/css/first_steps/index.html @@ -0,0 +1,52 @@ +--- +title: Primeros pasos en CSS +slug: Learn/CSS/First_steps +tags: + - Aprender + - CSS + - Principiante + - modulo + - primeros pasos +translation_of: Learn/CSS/First_steps +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">CSS (Cascading Style Sheets - en español Hojas de Estilo en Cascadas) es usado para darle estilo y diseño a las páginas Web — por ejemplo, para cambiar la fuente de letra, color, tamaño y el espaciado de tu contenido; dividir en múltiples columnas, o agregar animaciones y otras propiedades decorativas. Este modulo provee un inicio suave para tu ruta de aprendizaje hacia el dominio de CSS con su funcionamiento básico, como luce su sintaxis, y cómo puedes comenzar a utilizarlo y añadir estilo a HTML.</p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Antes de comenzar este módulo, deberías:</p> + +<ol> + <li>Estar familiarizado y tener conocimiento básico sobre el uso de computadores e internet básico (p.ej. navegando, consumiendo contenido en Internet.)</li> + <li>Un entorno básico de trabajo configurado, como se detalla en la sección de <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">Instalación de software básico</a>, y saber como crear y administrar archivos, o lo puedes ver en el módulo <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">Manejando los archivos</a>.</li> + <li>Conocimiento básico de HTML, como se muestra en <a href="https://developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si estás trabajando en un computador/tabla/otro dispositivo en el cual no puedes crear o almacenar tus propios archivos, podrías probar (la mayoría) de los ejemplos de código en un editor de código en línea como <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<p>Este módulo contiene los siguientes artículos, que te guiarán a través de toda la teoría básica de CSS, y te proveerá oportunidades para comprobar algunas de tus habilidades.</p> + +<dl> + <dt><a href="/es/docs/Learn/CSS/First_steps/Qu%C3%A9_es_CSS">¿Qué es CSS?</a></dt> + <dd><strong>{{Glossary("CSS")}}</strong> (Cascading Style Sheets) te permite crear páginas Webs atractivas, pero ¿Cómo funciona por debajo? Este artículo explica que es CSS, con ejemplos simples de sintaxis, y cubre algunos temas clave sobre este lenguaje.</dd> + <dt><a href="/es/docs/Learn/CSS/First_steps/Comenzando_CSS">Empezar con CSS</a></dt> + <dd>En este artículo se tomarná un documento HTML simple y se le aplicará CSS, aprendiendo algunas cosas prácticas mientras lo haces.</dd> + <dt><a href="/es/docs/Learn/CSS/First_steps/Como_se_estructura_CSS">Como se estructura CSS</a></dt> + <dd>Ahora que sabes que es CSS y de su uso básico, es momento de sumergirnos un poco más dentro de la estructura del propio lenguaje. Ya hemos conocido muchos de los conceptos discutidos aquí; puedes volver a este resumen en el futuro si necesitas reforzar conocimientos o si tienes dudas sobre algun concepto.</dd> + <dt><a href="/es/docs/Learn/CSS/First_steps/Como_funciona_CSS">Como trabaja CSS</a></dt> + <dd>Hemos aprendido lo básico de CSS, para que es y como escribir una hoja de estilo sencilla. En esta lección echaremos un vistazo a como los navegadores web reciben CSS y HTML y los convierten en una página web.</dd> + <dt><a href="/es/docs/Learn/CSS/First_steps/Usa_tu_nuevo_conocimiento">Usando tu nuevo conocimiento</a></dt> + <dd>Con las cosas que has aprendido en las últimas lecciones encontrarás que usando CSS puedes editar el formato de documentos de texto simple, para agregarles tu propio estilo. Este artículo te da la oportunidad de hacerlo.</dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<dl> + <dt><a href="https://teach.mozilla.org/activities/intermediate-web-lit/">Conocimiento práctico intermedio Web 1: Introducción a CSS (en Inglés)</a> </dt> + <dd>Un excelente curso de Mozilla foundation que explora y prueba muchas de las habilidades de las que se habla en el módulo de <em>Introducción al CSS</em>. Aprende acerca de como agregar estilo a los elementos HTML en una página web, selectores CSS, atributos, y valores.</dd> +</dl> diff --git a/files/es/learn/css/first_steps/qué_es_css/index.html b/files/es/learn/css/first_steps/qué_es_css/index.html new file mode 100644 index 0000000000..eb4f8e8a8a --- /dev/null +++ b/files/es/learn/css/first_steps/qué_es_css/index.html @@ -0,0 +1,127 @@ +--- +title: ¿Qué es el CSS? +slug: Learn/CSS/First_steps/Qué_es_CSS +tags: + - Beginner + - CSS + - Introduction to CSS + - Learn + - Modules + - Specifications + - Syntax +translation_of: Learn/CSS/First_steps/What_is_CSS +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps")}}</div> + +<p class="summary">Las hojas de estilo en cascada (<strong>{{Glossary("CSS")}}</strong>, cascading style sheets) permiten crear páginas web atractivas. Pero ¿cómo funcionan realmente? En este artículo explicaremos qué es el CSS con un ejemplo de sintaxis sencillo y describiremos algunos términos clave sobre este lenguaje.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">tener instalado el software básico</a>, conocimientos básicos de cómo <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a> y nociones de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender qué es CSS.</td> + </tr> + </tbody> +</table> + +<p>En el módulo <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>, exponemos qué es el HTML y cómo se usa para definir documentos destinados a leerse en un navegador web. Los títulos se verán más grandes que el texto y los párrafos empezarán en una línea nueva y habrá un espacio entre ellos. Los enlaces aparecerán en un color diferente y subrayados para distinguirlos del resto del texto. Vienen predeterminados por el navegador y, en la práctica, son estilos muy básicos que el navegador aplica al HTML para asegurarse, básicamente, de que sean legibles incluso si el autor de la página no especifica un estilo explícito.</p> + +<p><img alt="Los estilos predeterminados utilizados por el navegador" src="https://mdn.mozillademos.org/files/16493/html-example.png" style="border: 1px solid #cccccc; height: 594px; width: 1385px;"></p> + +<p>Sin embargo, Internet sería un lugar muy aburrido si todas las páginas web se vieran así. Usando CSS se pueden controlar con precisión cómo se ven los elementos HTML en el navegador, que presentará para las etiquetas de marcado el diseño que cada uno desee.</p> + +<h2 id="¿Para_qué_sirve_el_CSS">¿Para qué sirve el CSS?</h2> + +<p>Como hemos mencionado, el CSS es un lenguaje informático que especifica cómo se presentan los documentos a los usuarios: cómo se diseñan, compaginan, etc.</p> + +<p>Un <strong>documento</strong> suele ser un archivo de texto estructurado con un lenguaje de marcado: {{Glossary("HTML")}} es el más común, pero también existen otros como {{Glossary("SVG")}} o {{Glossary("XML")}}.</p> + +<p><strong>Presentar</strong> un documento a un usuario significa convertirlo en un formulario que el público pueda utilizar. Los {{Glossary("Navegador", "navegadores")}}, como por ejemplo {{Glossary("Mozilla Firefox", "Firefox")}}, {{Glossary("Google Chrome", "Chrome")}} o {{Glossary("Microsoft Edge", "Edge")}}, están diseñados para presentar documentos visualmente en una pantalla de ordenador, un proyector o una impresora.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Un navegador también recibe el nombre de {{Glossary("Agente de usuario", "agente de usuario")}}, que consiste en un programa informático que representa a una persona dentro del sistema. Los navegadores son el modelo principal de agente de usuario en el que pensamos cuando hablamos de CSS, pero no son el único. Hay otros documentos de usuario disponibles, como los que convierten documentos HTML y CSS en PDF para imprimir.</p> +</div> + +<p>El CSS se puede usar para estilos de texto muy básicos como, por ejemplo, cambiar el <a href="/es/docs/Web/CSS/color_value">color</a> y el <a href="/en-US/docs/Web/CSS/font-size">tamaño</a> de los encabezados y los enlaces. Se puede utilizar para crear un diseño, como podría ser <a href="/en-US/docs/Web/CSS/Layout_cookbook/Column_layouts">convertir una columna de texto en una composición</a> con un área de contenido principal y una barra lateral para información relacionada. Incluso se puede usar para crear efectos de <a href="/es/docs/Web/CSS/CSS_Animations">animación</a>. Echa un vistazo a los enlaces de este párrafo para ver ejemplos específicos.</p> + +<h2 id="Sintaxis_del_CSS">Sintaxis del CSS</h2> + +<p>El CSS es un lenguaje basado en reglas: cada usuario define las reglas que especifican los grupos de estilos que van a aplicarse a elementos particulares o grupos de elementos de la página web. Por ejemplo: «Quiero que el encabezado principal de mi página se muestre en letras grandes de color rojo».</p> + +<p>El código siguiente muestra una regla CSS muy simple que proporcionaría el estilo descrito en el párrafo anterior:</p> + +<pre class="brush: css notranslate">h1 { + color: red; + font-size: 5em; +}</pre> + +<p>La regla se abre con un {{Glossary("CSS Selector", "selector")}}. Este <em>selecciona</em> el elemento HTML que vamos a diseñar. En este caso, diseñaremos encabezados de nivel uno ({{htmlelement ("h1")}}).</p> + +<p>Luego tenemos un conjunto de llaves <code>{ }</code>. Entre estas habrá una o más <strong>declaraciones</strong>, que tomarán la forma de pares de <strong>propiedad</strong> y <strong>valor</strong>. Cada par especifica cada una de las propiedades de los elementos seleccionados y el valor que queremos dar a esa propiedad.</p> + +<p>Antes de los dos puntos, tenemos la propiedad; y después, el valor. Las {{Glossary("property/CSS", "propiedades")}} CSS admiten diferentes valores, dependiendo de qué propiedad se esté especificando. En el ejemplo anterior, tenemos la propiedad <code>color</code>, que puede tomar varios <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS#Color">valores de color</a>. También tenemos la propiedad de <code>font-size</code>, que puede tomar varias <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS#N%C3%BAmeros_longitudes_y_porcentajes">unidades de tamaño</a> como valor.</p> + +<p>Una hoja de estilo CSS contendrá muchas de estas reglas, escritas una tras otra.</p> + +<pre class="brush: css notranslate">h1 { + color: red; + font-size: 5em; +} + +p { + color: black; +}</pre> + +<p>Algunos valores se aprenden rápidamente, mientras que otros deberán buscarse. Las páginas de propiedades individuales que hay en el proyecto MDN proporcionan una forma rápida de buscar propiedades y sus valores en caso de olvidarlos o desear saber qué más se puede usar como valor.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar enlaces a todas las páginas de las propiedades CSS (junto con otras características CSS) enumeradas en la <a href="/es/docs/Web/CSS/Referencia_CSS">referencia CSS</a> del proyecto MDN. Alternativamente, deberías acostumbrarte a buscar «mdn <em>css-feature-name</em>» en tu motor de búsqueda favorito siempre que necesites obtener más información sobre una función CSS. Por ejemplo, intenta buscar «mdn color» y «mdn font-size».</p> +</div> + +<h2 id="Módulos_CSS">Módulos CSS</h2> + +<p>Como hay tantas cosas que se podrían diseñar usando CSS, el lenguaje se divide en <em>módulos</em>. Verás referencias a estos módulos a medida que explores en MDN y observarás que muchas de las páginas de documentación están organizadas en torno a un módulo en particular. Por ejemplo, puedes echar un vistazo a la referencia MDN del módulo <a href="/en-US/docs/Web/CSS/CSS_Backgrounds_and_Borders">Fondos y bordes</a> para averiguar cuál es su propósito, qué otras propiedades y características diferentes contiene. También encontrarás enlaces a la <em>especificación CSS</em> que define la tecnología (ver más abajo).</p> + +<p>En esta fase, no debes preocuparte demasiado sobre cómo se estructura el CSS, sin embargo, puede facilitarte la búsqueda de información si, por ejemplo, sabes que es probable que cierta propiedad se encuentre entre otras similares y, por lo tanto, en la misma especificación. </p> + +<p>Volvamos al módulo de Fondos y bordes para un ejemplo específico: puedes pensar que tiene lógica que las propiedades <code><a href="/es/docs/Web/CSS/background-color">background-color</a></code> y <code><a href="/es/docs/Web/CSS/border-color">border-color</a></code> se definan en este módulo. Y llevas toda la razón.</p> + +<h3 id="Especificaciones_CSS">Especificaciones CSS</h3> + +<p>Todas las tecnologías de estándares web (HTML, CSS, JavaScript, etc.) se definen en extensos documentos denominados especificaciones, publicados por organizaciones de estándares (como {{glossary("W3C")}}, {{glossary("WHATWG")}}, {{glossary("ECMA")}} o {{glossary("Khronos")}}) que definen con precisión cómo se supone que deben comportarse esas tecnologías.</p> + +<p>El caso de CSS no es diferente: lo desarrolla un grupo del W3C llamado <a href="https://www.w3.org/Style/CSS/">CSS Working Group</a>. Este grupo está compuesto por representantes de proveedores de navegadores y otras compañías interesadas en CSS. También hay otras personas, conocidas como <em>expertos invitados</em>, que actúan como voces independientes y no están vinculados a ninguna organización.</p> + +<p>El CSS Working Group desarrolla o especifica características nuevas del CSS. Algunas veces lo hacen porque un navegador en particular está interesado en alguna capacidad, otras porque los diseñadores y desarrolladores web piden una característica, y otras porque el grupo ha identificado un requisito. El CSS está en desarrollo constante y todos los días presenta nuevas características disponibles. Sin embargo, un elemento clave sobre el CSS es que toda la comunidad se esfuerza mucho en no cambiar nunca nada que pueda perjudicar los sitios web antiguos. ¡Un sitio web creado en el año 2000, que utiliza el poco CSS disponible que había en ese momento, aún debería poder utilizarse hoy en día!</p> + +<p>Como recién llegado al CSS, es probable que encuentres las especificaciones abrumadoras: están destinadas a que los ingenieros las utilicen para implementar soporte de sus características en los agentes de usuario en que trabajan, no para que lo lean los desarrolladores web para comprender el CSS. Muchos desarrolladores experimentados preferirán consultar la documentación disponible en MDN u otros tutoriales. Sin embargo, vale la pena saber que existen y comprender la relación que hay entre el CSS que estás utilizando, el soporte del navegador (ver más abajo) y las especificaciones.</p> + +<h2 id="Soporte_del_navegador">Soporte del navegador</h2> + +<p>Una vez se ha especificado el CSS, solo es útil en el desarrollo de páginas web si uno o más navegadores lo han implementado. Esto significa que el código se ha escrito para convertir las instrucciones que se especifican en nuestro archivo CSS en algo que se pueda mostrar en pantalla. Veremos este proceso más en profundidad en el artículo <a href="/es/docs/Learn/CSS/First_steps/Como_funciona_CSS">Cómo funciona el CSS</a>. Es inusual que todos los navegadores puedan implementar una misma característica al mismo tiempo, por lo que suele haber una brecha en la que se pueden usar algunas partes del CSS en algunos navegadores pero no en otros. Por este motivo, es útil poder verificar el estado de implementación. En cada una de las páginas de propiedades que hay en la MDN se puede ver el estado de la propiedad de interés, por lo que se puede saber si será posible utilizarla en un sitio web.</p> + +<p>Lo que sigue es el gráfico de datos de compatibilidad para la propiedad CSS <code><a href="/es/docs/Web/CSS/font-family">font-family</a></code>.</p> + +<p>{{Compat("css.properties.font-family")}}</p> + +<h2 id="¿Qué_viene_ahora">¿Qué viene ahora?</h2> + +<p>Ahora que comprendes mínimamente qué es el CSS, pasemos a <a href="/es/docs/Learn/CSS/First_steps/Comenzando_CSS">Comenzar con CSS</a>, donde puedes empezar a escribir algo de CSS tú mismo.</p> + +<p>{{NextMenu("Learn/CSS/First_steps/Getting_started", "Learn/CSS/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/en-US/docs/Learn/CSS/First_steps/What_is_CSS">¿Qué es el CSS?</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Getting_started">Comenzar con CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_is_structured">Cómo se estructura el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/How_CSS_works">Cómo funciona el CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Pon en práctica tus conocimientos nuevos</a></li> +</ol> diff --git a/files/es/learn/css/first_steps/usa_tu_nuevo_conocimiento/index.html b/files/es/learn/css/first_steps/usa_tu_nuevo_conocimiento/index.html new file mode 100644 index 0000000000..bff4f103bf --- /dev/null +++ b/files/es/learn/css/first_steps/usa_tu_nuevo_conocimiento/index.html @@ -0,0 +1,100 @@ +--- +title: Usa tu nuevo conocimiento +slug: Learn/CSS/First_steps/Usa_tu_nuevo_conocimiento +tags: + - Aprendizaje + - CSS + - Principiante +translation_of: Learn/CSS/First_steps/Using_your_new_knowledge +--- +<p>{{LearnSidebar}}{{PreviousMenu("Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}</p> + +<p class="summary">Con las cosas que has aprendido en las últimas lecciones, puedes darle formato a documentos de texto simple utilizando CSS para agregar tu propio estilo a ellos. Esta evaluación te da una posibilidad de hacer eso.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Antes de intentar esta evaluación, deberías haber trabajado a través del módulo de CSS básico, y también comprender HTML básico (estudia la <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introducción a HTML</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Utilizar algún CSS y probar conocimiento recién adquirido.</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Puedes trabajar en el editor en vivo más abajo, o puedes descargar el punto de partida para trabajar con tu propio editor. Esta es una página HTML, con el inicio del CSS en el <code><head></code> del documento. Si prefieres, puedes mover este CSS a un archivo separado cuando crees el ejemplo en tu computador. Alternativamente, puedes usar una herramienta en línea como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a> para trabajar en las tareas.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Si te atascas, pide ayuda — mira la sección <a class="external external-icon" href="https://wiki.developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML/Prueba_tus_habilidades:_Enlaces#Evaluaci%C3%B3n_o_ayuda_adicional" rel="noopener">Evaluación o ayuda adicional</a> al final de esta página.</p> +</div> + +<h2 id="Trabajando_con_CSS">Trabajando con CSS</h2> + +<p>Los siguientes ejemplos muestran una biografía, que ha sido estilizada usando CSS. Las propiedades CSS que se han utilizado son las siguientes - cada una enlaza a su página de propiedades en MDN, que te entregará más ejemplos de su uso:</p> + +<ul> + <li>{{cssxref("font-family")}}</li> + <li>{{cssxref("color")}}</li> + <li>{{cssxref("border-bottom")}}</li> + <li>{{cssxref("font-weight")}}</li> + <li>{{cssxref("font-size")}}</li> + <li>{{cssxref("text-decoration")}}</li> +</ul> + +<p>Se ha usado una mezcla de selectores, elementos de estilo como <code><h1></code> y <code><h2></code>, y también una clase para el título del trabajo.</p> + +<p>Usa CSS para cambiar el aspecto de esta biografía, cambiando los valores de las propiedades iniciales.</p> + +<ol> + <li>Coloca en rosado el nivel <code><h1></code>, usando el color CSS <code>hotpink</code>.</li> + <li>Da al encabezado un {{cssxref("border-bottom")}} de 10px con puntos (<code>dotted</code>), que use el color CSS <code>purple</code>.</li> + <li>Coloca en cursiva el <code><h2></code>.</li> + <li>Al <code>ul</code> utilizado para los detalles de contacto un {{cssxref("background-color")}} <code>#eeeeee</code>, y un {{cssxref("border")}} de <code>5px solid purple</code>. Usa algo de {{cssxref("padding")}} para empujar el texto lejos del borde.</li> + <li>Cambia los enlaces a verde cuando pase el cursor sobre ellos.</li> +</ol> + +<p>Deberías conseguir algo parecido a esta página:</p> + +<p><img alt="Screenshot of how the example should look after completing the assessment." src="https://mdn.mozillademos.org/files/17035/learn-css-basics-assessment.png" style="height: 1199px; width: 1104px;"></p> + +<p>Posteriormente intenta buscar algunas propiedades no mencionadas en esta página en la <a href="/en-US/docs/Web/CSS/Reference">referencia de CSS de MDN</a> y ¡arriésgate!.</p> + +<p>Recuerda que no existen respuestas equivocadas acá - En esta etapa en tu aprendizaje puedes tener un poco de diversión.</p> + +<p>{{EmbedGHLiveSample("css-examples/learn/getting-started/biog.html", '100%', 1600)}} </p> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Si deseas que tu trabajo sea evaluado, o estás atorado y quieres solicitar ayuda:</p> + +<ol> + <li>Pon tu trabajo en un editor en línea con capacidad de compartir como <a class="external external-icon" href="https://codepen.io/" rel="noopener">CodePen</a>, <a class="external external-icon" href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a class="external external-icon" href="https://glitch.com/" rel="noopener">Glitch</a>.</li> + <li>Escribe una publicación solicitando evaluacion y/o ayuda en el <a class="external external-icon" href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Tu publicación debería incluir: + <ul> + <li>Un título descriptivo como "Requiero evaluacion para Primeros pasos en CSS".</li> + <li>Detalles de lo que ya has intentado, y que te gustaría que hiciéramos, por ejemplo, si estas atascado y necesitas ayuda, o quieres una evaluación.</li> + <li>Un enlace al ejemplo que quieres que sea evaluado o por el que necesitas ayuda en un editor en linea con capacidad de compartir (como se mencionó en el paso 1 más arriba). Esta es una buena práctica - Es muy dificil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la tarea o página de evaluacion actual, para que podamos encontrar la pregunta con la cual necesitas ayuda.</li> + </ul> + </li> +</ol> + +<h2 id="¿Qué_sigue">¿Qué sigue?</h2> + +<p>Felicitaciones por completar este primer modulo!. Deberías tener un buen entendimiento general de CSS, y ser capaz de comprender bastante de los que está sucediendo en una hoja de estilo. En el módulo siguiente, <a href="/en-US/docs/Learn/CSS/Building_blocks">bloques de construccion CSS</a>, revisaremos en profundidad algunas áreas clave.</p> + +<p>{{PreviousMenu("Learn/CSS/First_steps/How_CSS_works", "Learn/CSS/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ol> + <li><a href="/es/docs/Web/CSS/Como_iniciar/Que_es_CSS">¿Qué es CSS?</a></li> + <li><a href="/es/docs/Learn/CSS/First_steps/Comenzando_CSS">Empezando con CSS</a></li> + <li><a href="/es/docs/Learn/CSS/First_steps/Como_se_estructura_CSS">Cómo se estructura el CSS</a></li> + <li><a href="/es/docs/Learn/CSS/First_steps/Como_funciona_CSS">Cómo funciona CSS</a></li> + <li><a href="/en-US/docs/Learn/CSS/First_steps/Using_your_new_knowledge">Usa tu nuevo conocimiento</a></li> +</ol> diff --git a/files/es/learn/css/index.html b/files/es/learn/css/index.html new file mode 100644 index 0000000000..ce384edeb2 --- /dev/null +++ b/files/es/learn/css/index.html @@ -0,0 +1,63 @@ +--- +title: CSS +slug: Learn/CSS +tags: + - CSS + - Codificación + - Depuración + - Necesidades + - Principiante + - Tema + - concreción + - longitud +translation_of: Learn/CSS +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Las Hojas de estilo en cascada (del ingles <em>Cascading Stylesheets</em> {{glossary("CSS")}}) es la siguiente tecnología que aprenderemos después de {{glossary("HTML")}}. Mientras que HTML se utiliza para definir la estructura y la semántica del contenido, CSS se usa para darle estilo y posicionarlo visualmente. CSS se puede usar, por ejemplo, para cambiar la fuente, el color, el tamaño y el espaciado del contenido, para formar multiples columnas, añadir animaciones y otros elementos decorativos.</p> + +<h2 id="Itinerario_de_aprendizaje">Itinerario de aprendizaje</h2> + +<p>Antes de empezar con CSS deberemos conocer los fundamentos de HTML. Podemos trabajar este contenido en <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">introducción a HTML</a> para posteriormente aprender:</p> + +<ul> + <li>CSS, comenzando por el módulo de Introducción a CSS</li> + <li><a href="/es/docs/Learn/HTML#Módulos">Módulos HTML</a> más avanzados</li> + <li><a href="/es/docs/Learn/JavaScript">JavaScript</a>, y cómo usarlo para añadir funcionalidad dinamica a las pagina web</li> +</ul> + +<p>Se recomienda aprender HTML y CSS al mismo tiempo, trabajando de forma conjunta ambas disciplinas. CSS aporta un valor añadido a HTML y no podrás aprender CSS sin controlar HTML.</p> + +<p>Antes de comenzar con este tema, deberemos tener conocimientos básicos sobre el uso de ordenadores y sobre el uso pasivo de la Web (navegar y consumir contenido). Es recomendable tener configurado un entorno de desarrollo como el detallado en <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">Instalación de software básico</a>, y saber crear y gestionar archivos como se detalla en <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">Manejando archivos</a> — ambos forman parte del módulo <a href="/es/docs/Learn/Getting_started_with_the_web">Primeros pasos en la Web</a> para principiantes.</p> + +<p>Se recomienda trabajar el módulo <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web">Primeros pasos en la Web</a> antes de entrar a este tema, aunque no es completamente necesario; gran parte de lo tratado en el artículo de CSS básico también se trata en el módulo de introducción a CSS, aunque con mucho más detalle.</p> + +<h2 id="Módulos">Módulos</h2> + +<p>Este tema contiene los siguientes módulos en el orden recomendado de aprendizaje. Recomendamos comenzar por el primero.</p> + +<dl> + <dt><a href="/es/docs/Learn/CSS/Introduction_to_CSS">Introducción a CSS</a></dt> + <dd>Este módulo explica los conceptos básicos sobre el funcionamiento de CSS, incluyendo selectores y propiedades, escritura de reglas CSS, aplicación de CSS a HTML, cómo especificar longitud, color y otras unidades en CSS, organización en cascada y herencia, conceptos de encajonado básicos y depuración de CSS.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Styling_text">Estilo del texto</a></dt> + <dd>Aquí veremos cómo aplicar estilos al texto, tipos de letra, negrita, cursiva, espaciado, interlineado y sombreado, entre otras funciones relativas al texto. Terminaremos el módulo aplicando tipos a nuestra página, configurando listas y enlaces.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Styling_boxes">Estilos por cajas</a></dt> + <dd>A continuación veremos la aplicación de estilos por cajas, fundamental en el diseño de páginas web. En este módulo analizaremos el modelo de cajas para después aprender a controlar el diseño de las cajas ajustando rellenos, marcos y márgenes, personalizando colores de fondo, imágenes y otras características, además de divertidas funcionalidades como el sombreado y los filtros sobre las cajas.</dd> + <dt><a href="/en-US/docs/Learn/CSS/CSS_layout">Diseño CSS</a></dt> + <dd>Llegados a este punto ya conocemos lo básico de CSS, como darle estilo al texto, y cómo dar estilo y manipular el contenido de las cajas. Es momento de ver cómo ubicar las cajas correctamente con respecto a la ventana de visualización y a otra. Hemos cubierto los requisitos necesarios para poder meternos de lleno en el diseño CSS, ver diferentes ajustes de visualización, metodos tradicionales de diseño con pivotes y posicionamiento, y nuevas herramientas de diseño como flexbox.</dd> + <dt>Diseño Adaptable (RBD Responsive Web Design)</dt> + <dd>Con la gran variedad de dispositivos capaces de navegar por la Web actualmente, el <a href="https://developer.mozilla.org/en-US/Apps/Progressive/Responsive">diseño web adaptable </a>(RWD) es una habilidad imprescindible para el diseño web. En este módulo veremos principios básicos y herramientas de RWD, como aplicar diferentes CSS a un documento dependiendo de las características del dispositivo como el ancho de la pantalla, la orientación y la resolución; veremos las tecnologías disponibles para mostrar videos e imágenes dependiendo de estas características.</dd> +</dl> + +<h2 id="Resolución_de_problemas_con_CSS">Resolución de problemas con CSS</h2> + +<p><a href="https://developer.mozilla.org/es/docs/Learn/CSS/S%C3%A1bercomo">Uso de CSS para resolver problemas comunes</a> proporciona vínculos a secciones que explican cómo usar CSS para resolver problemas comunes cuando se está creando una página web.</p> + +<div class="section"> +<h2 id="Ver_También">Ver También</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/en-US/docs/Web/CSS">CSS en MDN</a></dt> + <dd>Principal entrada para la documentación de CSS en MDN, donde encontrarás documentación detallada de todas las funcionalidades del lenguaje CSS. ¿Quieres saber todos los valores posibles de una propiedad? Este es tu sitio.</dd> +</dl> +</div> diff --git a/files/es/learn/css/introduction_to_css/fundamental_css_comprehension/index.html b/files/es/learn/css/introduction_to_css/fundamental_css_comprehension/index.html new file mode 100644 index 0000000000..b53db2df02 --- /dev/null +++ b/files/es/learn/css/introduction_to_css/fundamental_css_comprehension/index.html @@ -0,0 +1,117 @@ +--- +title: Comprensión de los fundamentos de CSS +slug: Learn/CSS/Introduction_to_CSS/Fundamental_CSS_comprehension +tags: + - CSS + - Estilo + - Evaluación + - Modelo de Caja + - Principiante + - Selectores + - Sintaxis + - comentários + - reglas +translation_of: Learn/CSS/Building_blocks/Fundamental_CSS_comprehension +--- +<div class="boxed translate-rendered"> +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/CSS/Introduction_to_CSS/Debugging_CSS", "Learn/CSS/Introduction_to_CSS")}}</div> + +<p class="summary">Has avanzado mucho en este módulo, debes sentirte orgulloso de haber llegado hasta el final. El último paso antes de terminar es intentar el examen del módulo — que incluye completar varios ejercicios para crear el último diseño — una tarjeta de presentación/de jugador/perfil de redes sociales.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Antes de intentar esta evaluación, debería haber revisado todos los artículos en este módulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Probar la comprensión de los fundamentos de la teoría, sintaxis y mecánica de CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_Partida">Punto de Partida</h2> + +<p>Para comenzar esta evaluación, debes:</p> + +<ul> + <li>Ve y coge el <a href="https://github.com/mdn/learning-area/blob/master/css/introduction-to-css/fundamental-css-comprehension/index.html">archivo HTML del ejercicio</a>, y el <a href="https://github.com/mdn/learning-area/blob/master/css/introduction-to-css/fundamental-css-comprehension/chris.jpg">archivo de imagen asociada</a>, y guárdalos en un nuevo directorio en tu ordenador local. Si quieres usar tu propio archivo de imagen y rellenar tu propio nombre, eres bienvenido - sólo asegúrate de que la imagen es cuadrada.</li> + <li>Coge el <a href="https://github.com/mdn/learning-area/blob/master/css/introduction-to-css/fundamental-css-comprehension/style-resources.txt">archivo de texto de los recursos CSS</a> — este contiene un conjunto de selectores y conjuntos de reglas en estado puro que necesitarás estudiar y combinar para responder a parte de esta evaluación.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Alternativamente, se puede utilizar un sitio como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> o <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> para hacer la evaluación. Puede pegar el HTML y completar el CSS en uno de estos editores en línea, y usar <a href="http://mdn.github.io/learning-area/css/introduction-to-css/fundamental-css-comprehension/chris.jpg">esta URL</a> para apuntar el elemento <code><img></code> al archivo de imagen. Si el editor en línea que estás usando no tiene un panel CSS separado, no dudes en ponerlo en un elemento <code><style></code> en el encabezado del documento.</p> +</div> + +<h2 id="Resumen_del_Proyecto">Resumen del Proyecto</h2> + +<p>Se le ha proporcionado un poco de HTML puro y una imagen, y necesitas escribir el CSS necesario para darle estilo a una pequeña tarjeta de presentación en línea, que tal vez pueda servir como una tarjeta de jugador o de perfil en redes sociales. Las siguientes secciones describen lo que debes hacer.</p> + +<p>Configuración básica:</p> + +<ul> + <li>En primer lugar, crea un nuevo archivo en el mismo directorio que tus archivos HTML y de imagen. Llámalo algo realmente imaginativo como <code>style.css</code>.</li> + <li>Vincula tu CSS a tu archivo HTML mediante un elemento <code><link></code>.</li> + <li>Las dos primeras reglas en el archivo de recursos CSS son tuyas, ¡GRATIS! Después de que hayas terminado de regocijarte de tu buena fortuna, cópialas y pégalas en la parte superior de tu nuevo archivo CSS. Úsalas como prueba para asegurarte de que tu CSS se aplica correctamente a tu HTML.</li> + <li> + <p>Sobre las dos reglas, agregue un comentario CSS con algún texto dentro para indicar que se trata de un conjunto de estilos generales para toda la página. "Estilos generales de la página" sería suficiente. También agrega tres comentarios más en la parte inferior del archivo CSS para indicar estilos específicos para la configuración del contenedor de la tarjeta, estilos específicos para el header y footer (encabezado y pie de página), y estilos específicos para el contenido principal de la tarjeta de presentación. De ahora en adelante, los estilos subsiguientes añadidos a la hoja de estilo deben organizarse en el lugar apropiado.</p> + </li> +</ul> + +<p>Encargandonos de los selectores y conjuntos de reglas proporcionados:</p> + +<ul> + <li>A continuación, nos gustaría que examinaras los cuatro selectores y calcularas la especificidad de cada uno. Escríbelas en algún lugar donde las puedas encontrar más tarde, como en un comentario en la parte superior de tu CSS.</li> + <li>Ahora es el momento de poner el selector correcto en el conjunto de reglas correcto! Tienes cuatro pares de selectores y reglas que coinciden en tus recursos de CSS. Hazlo ahora y agrégalos a tu archivo CSS. Necesitaras: + <ul> + <li>Asignar al contenedor principal de tarjetas un ancho/alto fijo (width/height), color de fondo sólido (background-color), borde (border) y radio de borde (border-radius), entre otras cosas.</li> + <li>Asigna al header un degradado (linear-gradient) de fondo que va de más oscuro a más claro, además de esquinas redondeadas que encajan con las esquinas redondeadas establecidas en el contenedor principal de tarjetas.</li> + <li>Asigna al pie de página un degradado (linear-gradient) de fondo que vaya de más claro a más oscuro, además de esquinas redondeadas que encajen con las esquinas redondeadas establecidas en el contenedor principal de tarjetas.</li> + <li>Asigna a la imagen un float a la derecha para que se pegue al lado derecho del contenido principal de la tarjeta de presentación, y dale una altura máxima (max-height) del 100% (un truco inteligente que asegura que crecerá/encogerá para que se mantenga a la misma altura que el contenedor principal, sin importar a que altura se trasforme).</li> + </ul> + </li> + <li>¡Cuidado! Hay dos errores en los conjuntos de reglas proporcionados. Utilizando cualquier técnica que conozcas, localízalas y arréglalas antes de seguir adelante.</li> +</ul> + +<p>Nuevos conjuntos de reglas que necesitas escribir:</p> + +<ul> + <li>Escribe un conjunto de reglas que apunte tanto al header de la tarjeta como al footer de la misma, dándoles una altura total de 50px, (que incluye una altura de contenido de 30px y un padding de 10px en todos los lados). Pero expresalo en <code>em</code>s.</li> + <li>El margen por defecto aplicado a los elementos <code><h2></code> y <code><p></code> por el navegador interferirá con nuestro diseño, así que escribe una regla que apunte a todos estos elementos y establezca su margen en 0.</li> + <li>Para evitar que la imagen se derrame del contenido principal de la tarjeta de presentación (el elemento <code><article></code>), necesitamos darle una altura específica. Ajustar la altura del <code><article></code> a 120px, expresada en <code>em</code>s. También asigna un background-color negro semitransparente, resultando en un tono ligeramente más oscuro que deja que el color rojo del fondo brille un poco también.</li> + <li>Escribe un conjunto de reglas que le asigne al <code><h2></code> un font-size efectivo de 20px (pero expresado en <code>em</code>s) y una line-height (altura de línea) apropiada para colocarlo en el centro de la caja de contenido del header. Recuerde que la altura de la caja de contenido debe ser de 30px - esto te proporciona todos los números que necesitas para calcular la line-height.</li> + <li>Escribe un conjunto de reglas que le asigne al <code><p></code> dentro del footer un font-size efectivo de 15px (pero expresado en <code>em</code>s) y una line-height apropiada para colocarlo en el centro de la caja de contenido del footer. Recuerda que la altura de la caja de contenido debe ser de 30px - esto te proporciona todos los números que necesitas para calcular la line-height.</li> + <li>Como último toque, asigna al párrafo dentro del <code><article></code> un padding apropiado para que su borde izquierdo se alinee con el <code><h2></code> y el párrafo del footer, y ajuste su color para que sea bastante claro y sea fácil de leer.</li> +</ul> + +<p>Otras cosas en las que pensar:</p> + +<ul> + <li>Obtendrás puntos adicionales si escribes tu CSS para una legibilidad máxima, con una declaración separada en cada línea..</li> + <li>Deberás incluir <code>.card</code> al principio de la cadena de selección en todas tus reglas, para que estas reglas no interfieran con el estilo de cualquier otro elemento si la tarjeta de presentación se pusiera en una página con un montón de otro contenido.</li> +</ul> + +<h2 id="Consejos_y_Sugerencias">Consejos y Sugerencias</h2> + +<ul> + <li>No necesitas editar el HTML de ninguna manera, excepto para aplicar el CSS a tu HTML.</li> + <li>Cuando intentes calcular el valor <code>em</code> que necesita para representar una cierta longitud de píxel, piensa en el tamaño de fuente base que tiene el elemento raíz (<code><html></code>) , y por el que necesita multiplicarse para obtener el valor deseado. Eso te dará tu valor, al menos en un caso sencillo como este.</li> +</ul> + +<h2 id="Ejemplo">Ejemplo</h2> + +<p>La siguiente captura de pantalla muestra un ejemplo de cómo debe ser el diseño terminado:</p> + +<p><img alt="A view of the finished business card, show a reader header and footer, and a darker center panel containing the main details and image." src="https://mdn.mozillademos.org/files/12616/business-card.png" style="display: block; margin: 0 auto;"></p> + +<p> </p> + +<h2 id="Evaluación">Evaluación</h2> + +<p>Si estás siguiendo esta evaluación como parte de un curso organizado, deberías ser capaz de entregar tu trabajo a tu profesor/mentor para que lo califique. Si eres autodidacta, entonces puedes obtener la guía de puntuación fácilmente preguntando en el hilo del <a href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">Discurso del Área de Aprendizaje</a>, o en el canal IRC <a href="irc://irc.mozilla.org/mdn">#mdn</a> en <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Haz el ejercicio primero - ¡No hay nada que ganar haciendo trampa!</p> + +<p>{{PreviousMenu("Learn/CSS/Introduction_to_CSS/Debugging_CSS", "Learn/CSS/Introduction_to_CSS")}}</p> +</div> diff --git a/files/es/learn/css/styling_text/fuentes_web/index.html b/files/es/learn/css/styling_text/fuentes_web/index.html new file mode 100644 index 0000000000..7bfa162217 --- /dev/null +++ b/files/es/learn/css/styling_text/fuentes_web/index.html @@ -0,0 +1,197 @@ +--- +title: Fuentes web +slug: Learn/CSS/Styling_text/Fuentes_web +translation_of: Learn/CSS/Styling_text/Web_fonts +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/Styling_text/Styling_links", "Learn/CSS/Styling_text/Typesetting_a_homepage", "Learn/CSS/Styling_text")}}</div> + +<p class="summary">En el primer artículo del módulo, exploramos las características básicas del CSS disponibles para aplicar estilos a tipos de letra y al texto. En este artículo vamos a ir más lejos: exploraremos en detalle las tipografías web, que permiten que te descargues tipos de letra personalizados junto con tu página web para lograr un estilo de texto más variado y personalizado.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>) y de CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a>), <a href="/es/docs/Learn/CSS/Styling_text/Fundamentals">texto CSS y los fundamentos de la fuente</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a aplicar tipos de letra a una página web, ya sea desde un servicio de terceros o desde tu código.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen_de_las_familias_de_tipos_de_letra">Resumen de las familias de tipos de letra</h2> + +<p>Como observamos en el artículo <a href="/es/docs/Learn/CSS/Styling_text/Fundamentals">Texto y tipos de letra</a>, puedes controlar los tipos de letra que aplicas a tu HTML con la propiedad {{cssxref ("font-family")}}. Este atributo toma uno o más nombres de familia de tipos de letra y el navegador recorre esta lista hasta que encuentra un tipo de letra disponible en el sistema en el que se ejecuta:</p> + +<pre class="brush: css notranslate">p { + font-family: Helvetica, "Trebuchet MS", Verdana, sans-serif; +}</pre> + +<p>Este sistema funciona bien, pero las opciones de tipo de letra tradicionales de los desarrolladores web eran limitadas. Solo hay un puñado de tipos de letra que puedes garantizar que están disponibles en todos los sistemas comunes: las llamadas <a href="/es/docs/Learn/CSS/Styling_text/Fundamentals#Familia_de_tipos_de_letras">fuentes seguras para la web</a>. Puedes usar la lista de tipos de letra para especificar cuáles prefieres, seguido de alternativas seguras para la web y del tipo de letra predeterminado del sistema. El problema es que esto añade trabajo extra en términos de pruebas para asegurarte de que tus diseños se ven bien con cada tipo de letra, etc.</p> + +<h2 id="Tipografías_web">Tipografías web</h2> + +<p>Hay una alternativa, sin embargo, que funciona muy bien hasta con versiones posteriores a la versión 6 de Internet Explorer. Las tipografías web son una función del CSS que te permite especificar los archivos de tipo de letra que se van a descargar junto con tu sitio web a medida que el usuario acceda a ellos, lo que significa que cualquier navegador que admita tipografías web puede disponer de los tipos de letra que especificas. ¡Increíble! Observa a continuación la sintaxis que se necesita.</p> + +<p>En primer lugar, tienes un bloque {{cssxref ("@font-face")}} al comienzo del CSS, que especifica los archivos de los tipos de letra que quieres que se descarguen:</p> + +<pre class="brush: css notranslate">@font-face { + font-family: "myFont"; + src: url("myFont.woff"); +}</pre> + +<p>A continuación, puedes usar el nombre de la familia de tipos de letra especificado en <code>@font-face</code> para aplicar tu tipo de letra personalizado a cualquier elemento que desees:</p> + +<pre class="brush: css notranslate">html { + font-family: "myFont", "Bitstream Vera Serif", serif; +}</pre> + +<p>La sintaxis es un poco más compleja; más adelante la veremos más detalladamente.</p> + +<p>Hay dos cosas importantes a tener en cuenta acerca de las tipografías web:</p> + +<ol> + <li>Los navegadores admiten diferentes formatos de tipos de letra, por lo que necesitarás más de un formato de tipos de letra para conseguir una compatibilidad decente entre navegadores. Por ejemplo, la mayoría de los navegadores modernos admiten WOFF/WOFF2 (Web Open Font Format, versiones 1 y 2), el formato más eficiente disponible. Pero las versiones antiguas de Internet Explorer solo admiten tipos de letra con formato EOT (Embedded Open Type) y es posible que debas incluir una versión SVG del tipo de letra para soportar versiones antiguas de navegadores iPhone y Android. A continuación te mostraremos cómo generar el código necesario.</li> + <li>Generalmente las fuentes no son de uso gratuito. Debes pagar por ellas y/o respetar otras condiciones de licencia, como acreditar al creador del tipo de letra en el código (o en tu sitio web). Los tipos de letra no deben robarse, ni debes utilizarlos sin otorgar a su creador el crédito apropiado.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: ¡Los tipos de letra seguros para web como tecnología han sido compatibles con Internet Explorer desde su versión 4!</p> +</div> + +<h2 id="Aprendizaje_activo_Un_ejemplo_de_tipo_de_letra_seguro_para_web">Aprendizaje activo: Un ejemplo de tipo de letra seguro para web</h2> + +<p>Con esto en mente, vamos a construir un ejemplo básico de uso de un tipo de letra seguro para web a partir de los principios básicos. Es difícil hacer un ejemplo de demostración de este aspecto con un ejemplo en vivo incrustado, por lo tanto, nos gustaría que siguieses los pasos que se detallan en las secciones siguientes para que te hagas una idea de cómo funciona el proceso.</p> + +<p>Como punto de partida hay que utilizar los archivos <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/web-fonts/web-font-start.html">web-font-start.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/web-fonts/web-font-start.css">web-font-start.css</a> a los que añadir tu código (véase el <a href="http://mdn.github.io/learning-area/css/styling-text/web-fonts/web-font-start.html">ejemplo en vivo</a>). Haz una copia de estos archivos en un directorio nuevo de tu equipo. En el archivo <code>web-font-start.css</code>, encontrarás un poco de CSS para trabajar con el aspecto y los tipos de letra básicos del ejemplo.</p> + +<h3 id="Encontrar_tipos_de_letra">Encontrar tipos de letra</h3> + +<p>Para este ejemplo, utilizaremos dos tipografías web: una para los títulos de encabezado y otra para el texto base. Para empezar, hay que encontrar los archivos que contienen el tipo de letra. Los tipos de letra se crean en estudios de diseño y se guardan en diversos formatos de archivo. En general, hay tres tipos de sitios donde puedes obtener fuentes:</p> + +<ul> + <li>Un distribuidor gratuito de tipos de letra: Es un sitio web que pone a disposición tipos de letra para descargar de forma gratuita (aunque puede haber algunas condiciones de licencia, como la acreditación del creador del tipo de letra). Algunos ejemplos de sitios web donde puedes encontrar tipos de letra gratis son <a href="https://www.fontsquirrel.com/">Font Squirrel</a>, <a href="http://www.dafont.com/">dafont</a> y <a href="https://everythingfonts.com/">Everything Fonts</a>.</li> + <li>Un distribuidor de fuentes de pago: En este sitio web puedes encontrar tipos de letra a cambio de un precio, dos ejemplos son <a href="http://www.fonts.com/">fonts.com</a> o <a href="http://www.myfonts.com/">myfonts.com</a>. También puedes comprar tipos de letra directamente de estudios de diseño, por ejemplo, <a href="https://www.linotype.com/">Linotype</a>, <a href="http://www.monotype.com">Monotype</a>, o <a href="http://www.exljbris.com/">Exljbris</a>.</li> + <li>Un servicio de tipos de letra en línea: Es un sitio que guarda y te sirve los tipos de letra, lo que te facilita todo el proceso. Consulta la sección {{anch ("Los servicios de tipos de letra en línea")}} para obtener más información.</li> +</ul> + +<p>Vamos a ver algunos tipos de letra. Ve a <a href="https://www.fontsquirrel.com/">Font Squirrel</a> y elige dos tipos de letra: uno que te resulte agradable e interesante para los títulos (quizá una buena tipografía de tipo Display o Slab Serif), y otro un poco menos llamativo y más legible para los párrafos. Cuando encuentres los tipos de letra, pulsa el botón de descarga y guarda el archivo en el mismo directorio que los archivos HTML y CSS que guardaste anteriormente. No importa si son TTF (True Type Fonts) u OTF (Open Type Fonts).</p> + +<p>En cada caso, descomprime el paquete de tipos de letra (las tipografías web generalmente se distribuyen en archivos ZIP que contienen los archivos con el tipo de letra y la información de la licencia). En el paquete puede haber más de un archivo con tipos de letra: algunos tipos de letra se distribuyen por familias, con diferentes variantes disponibles, por ejemplo: <em>thin</em>, <em>medium</em>, <em>bold</em>, <em>italic</em>, <em>thin italic</em>, etc. Para este ejemplo, solo queremos que te quedes con un solo archivo de fuente para cada opción.</p> + +<div class="note"> +<p><strong>Nota</strong>: En la sección «Encontrar tipos de letra» en la columna de la derecha, puedes hacer clic en las diferentes etiquetas y clasificaciones para filtrar las opciones.</p> +</div> + +<h3 id="Generar_el_código">Generar el código</h3> + +<p>Ahora deberás generar el código que necesitas (y aplicar el estilo al tipo de letra). Para cada tipo de letra, sigue estos pasos:</p> + +<ol> + <li>Asegúrate de cumplir con todos los requisitos de la licencia, sobre todo si vas a usarlo en un proyecto comercial y/o en una web.</li> + <li>Ve a <a href="https://www.fontsquirrel.com/tools/webfont-generator">Webfont Generator </a>de Fontsquirrel.</li> + <li>Sube tus dos archivos de tipo de letra con el botón <em>Cargar Fuentes</em>.</li> + <li>Marca la casilla de verificación con el texto «Sí, las fuentes que elijo pueden utilizarse legalmente para una página web».</li> + <li>Haz clic en <em>Descarga tu paquete</em>.</li> +</ol> + +<p>Una vez que el generador haya finalizado el procesamiento, deberías obtener un archivo ZIP para descargar; guárdalo en el mismo directorio que tus archivos HTML y CSS.</p> + +<h3 id="El_código_de_tu_ejemplo_de_demostración">El código de tu ejemplo de demostración</h3> + +<p>En este punto, descomprime el paquete con los tipos de letra web que acabas de generar. En el directorio descomprimido verás tres elementos útiles:</p> + +<ul> + <li>Las distintas versiones de cada tipo de letra, por ejemplo: <code>.ttf</code>, <code>.woff</code>, <code>.woff2</code>, etc.; los tipos de letra exactos proporcionados se actualizarán con el tiempo a medida que cambien los requisitos técnicos del navegador. Como se ya hemos dicho, se necesita más de un tipo de letra para garantizar la compatibilidad entre navegadores: esta es la forma en que Fontsquirrel se asegura de que tengas todo lo que necesitas.</li> + <li>Un archivo HTML con un ejemplo de demostración para cada tipo de letra: cárgalos en tu navegador para ver cómo se ve la fuente en diferentes contextos de uso.</li> + <li>Un archivo <code>stylesheet.css</code>, que contiene el código @font-face que necesitas.</li> +</ul> + +<p>Para implementar estos tipos de letra en tu ejemplo de demostración, sigue estos pasos:</p> + +<ol> + <li>Cambia el nombre del directorio descomprimido a algo fácil y simple, como <code>fonts</code>.</li> + <li>Abre el archivo <code>stylesheet.css</code> y copia los dos bloques <code>@font-face</code> incluidos en tu archivo <code>web-font-start.css</code>. Debes ponerlos en la parte superior, antes de cualquier elemento CSS, ya que los tipos de letra deben importarse antes que los puedas utilizar en tu sitio web.</li> + <li>Cada una de las funciones <code>url()</code> apunta a un archivo de tipo de letra que tenemos que importar a nuestro CSS. Necesitamos asegurarnos de que las rutas a los archivos son correctas, así que añade <code>fonts/</code> al inicio de cada ruta (ajusta la ruta como sea necesario).</li> + <li>Ahora puedes usar estos tipos de letra en tu lista de tipos de letra, al igual que cualquier tipo de letra seguro o predeterminado del sistema. Por ejemplo: + <pre class="brush: css notranslate">font-family: 'zantrokeregular', serif;</pre> + </li> +</ol> + +<p>Con tu ejemplo de demostración, deberías obtener una página con unos agradables tipos de letra. Debido a que los tipos de letra se crean en diferentes tamaños, es posible que tengas que ajustar el tamaño, el espaciado, etc., para conseguir una apariencia más ordenada.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/12984/web-font-example.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Si tienes problemas para lograr que esto funcione, no dudes en comparar tu versión con nuestros archivos terminados, consulta <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/web-fonts/web-font-finished.html">web-font-finished.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/web-fonts/web-font-finished.css">web-font-finished.css</a> (<a href="http://mdn.github.io/learning-area/css/styling-text/web-fonts/web-font-finished.html">ejecuta el ejemplo terminado en vivo</a>).</p> +</div> + +<h2 id="Los_servicios_de_tipos_de_letra_en_línea">Los servicios de tipos de letra en línea</h2> + +<p>Los servicios de tipos de letra en línea en general guardan tipos de letra y los proporcionan a los usuarios, por lo que no tienes que preocuparte por escribir el código <code>@font-face</code>, solo necesitas insertar una o dos sencillas líneas de código en tu sitio web para que todo funcione. Los ejemplos incluyen <a href="https://fonts.adobe.com/">Adobe Fonts</a> y <a href="http://www.typography.com/cloud/welcome/">Cloud.typography</a>. La mayoría de estos servicios se basan en suscripciones de pago, con la excepción notable de <a href="https://www.google.com/fonts">Google Fonts</a>, un servicio gratuito y muy útil, sobre todo para trabajos de prueba rápida y escritura de ejemplos de demostración.</p> + +<p>La mayoría de estos servicios son fáciles de usar, por lo que no vamos a exponerlos en gran detalle. Vamos a echar un vistazo rápido a las fuentes de Google, para que te hagas una idea. De nuevo, usa copias de <code>web-font-start.html</code> y <code>web-font-start.css</code> como punto de partida.</p> + +<ol> + <li>Ve a <a href="https://www.google.com/fonts">Google Fonts</a>.</li> + <li>Usa los filtros del lado izquierdo para indicar los tipos de letra que deseas escoger y elige un par de tipos de letra que te gusten.</li> + <li>Para seleccionar una familia de tipos de letra, pulsa el botón ⊕ que encontrarás al lado.</li> + <li>Cuando hayas elegido las familias de tipos de letra, pulsa la barra <em>[número] familias seleccionadas</em> que encontrarás en la parte inferior de la página.</li> + <li>En la pantalla resultante, primero debes copiar la línea de código HTML que se muestra y pegarla en el encabezado de tu archivo HTML. Ponlo encima del elemento {{HTMLElement("link")}}, de modo que el tipo de letra se importe correctamente antes de intentar utilizarlo en tu CSS.</li> + <li>Luego, debes copiar las declaraciones CSS enumeradas en tu CSS según corresponda para aplicar los tipos de letra personalizados a tu HTML.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar una versión completa en <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/web-fonts/google-font.html">google-font.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/web-fonts/google-font.css">google-font.css</a>, si necesitas comparar tu trabajo con el nuestro (<a href="http://mdn.github.io/learning-area/css/styling-text/web-fonts/google-font.html">consúltalo en vivo</a>).</p> +</div> + +<h2 id="font-face_con_más_detalle">@font-face con más detalle</h2> + +<p>Vamos a explorar que la sintaxis correspondiente a <code>@font-face</code> que te ha generado Fontsquirrel. Uno de los bloques se verá así:</p> + +<pre class="brush: css notranslate">@font-face { + font-family: 'ciclefina'; + src: url('fonts/cicle_fina-webfont.eot'); + src: url('fonts/cicle_fina-webfont.eot?#iefix') format('embedded-opentype'), + url('fonts/cicle_fina-webfont.woff2') format('woff2'), + url('fonts/cicle_fina-webfont.woff') format('woff'), + url('fonts/cicle_fina-webfont.ttf') format('truetype'), + url('fonts/cicle_fina-webfont.svg#ciclefina') format('svg'); + font-weight: normal; + font-style: normal; +}</pre> + +<p>Esto se conoce como «sintaxis @font-face a prueba de balas» desde una publicación de Paul Irish, en los tiempos en que <code><code>@font-face</code></code> empezaba a popularizarse (<a href="http://www.paulirish.com/2009/bulletproof-font-face-implementation-syntax/">Bulletproof @font-face Syntax</a>). Vamos a ver qué hace:</p> + +<ul> + <li><code><code><code>font-family</code></code></code>: Esta línea especifica el nombre con el que vas a referirte a la fuente. Puedes poner el que quieras, siempre y cuando lo uses de manera coherente a lo largo de tu CSS.</li> + <li><code><code><code>src</code></code></code>: Estas líneas especifican las rutas de acceso a los archivos de tipos de letra para que puedas importarlos a tu CSS (la parte <code><code><code>URL</code></code></code>) y el formato de cada archivo de tipo de letra (la parte <code><code><code>format</code></code></code>). La última parte en cada caso es opcional, pero es útil declararla porque permite que los navegadores encuentren más rápido un tipo de letra que puedan usar. Se pueden enumerar varias declaraciones, separadas por comas: el navegador buscará por ellas y usará la primera que encuentre. Por lo tanto, es mejor poner formatos nuevos y mejores, como WOFF2 y formatos más antiguos, no tan buenos, como TTF. La única excepción son las fuentes EOT: se colocan primero para corregir un par de errores en versiones anteriores de Internet Explorer, por lo que intentará usar lo primero que encuentre, incluso si realmente no puede usar la fuente.</li> + <li>{{cssxref("font-weight")}}/{{cssxref("font-style")}}: Estas líneas especifican qué grueso tiene el tipo de letra y si se muestra en cursiva o no. Si vas a importar diversos grosores del mismo tipo de letra, puedes especificar cuál es su grueso/estilo y luego usar valores de {{cssxref("font-weight")}} / {{cssxref("font-style")}} diferentes para elegir entre ellos, en lugar de tener que llamar a todos los diferentes miembros de la familia de tipos de letra con nombres distintos. <a href="http://www.456bereastreet.com/archive/201012/font-face_tip_define_font-weight_and_font-style_to_keep_your_css_simple/">@tip-face tip: define font-weight and font-stile to keep your CSS simple</a> de Roger Johansson muestra qué hacer con más detalle.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: También puedes especificar los valores particulares {{cssxref ("font-variant")}} y {{cssxref ("font-stretch")}} para tus tipos de letra seguros para web. En los navegadores más nuevos también puedes especificar un valor {{cssxref ("unicode-range")}}, que es un rango de caracteres específicos que debes usar aparte del tipo de letra seguro para web en los navegadores que incluyan esta opción. Solo se descargaran los caracteres especificados y te ahorrarás descargas innecesarias. <a href="https://24ways.org/2011/creating-custom-font-stacks-with-unicode-range/">Creating Custom Font Stacks with Unicode-Range</a> de Drew McLellan proporciona algunas ideas útiles sobre cómo hacer uso de todo esto.</p> +</div> + +<h2 id="Tipos_de_letra_variables">Tipos de letra variables</h2> + +<p>Los navegadores disponen hoy de una tecnología de tipos de letra reciente llamada tipos de letra variables: se trata de tipos de letra que permiten incorporar muchas variaciones diferentes de un tipo de letra en un solo archivo, en lugar de tener un archivo separado para cada ancho, grosor o estilo. Es demasiado avanzado para nuestro curso para principiantes, pero si te apetece avanzar y echarles un vistazo, lee nuestra <a href="/en-US/docs/Web/CSS/CSS_Fonts/Variable_Fonts_Guide">guía de tipos de letra variables</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahora que has leído nuestros artículos sobre nociones de aplicación de estilo al texto, es hora de evaluar cuánto has retenido del módulo a partir de la creación de una composición tipográfica de una página de inicio de una escuela comunitaria.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Styling_text/Styling_links", "Learn/CSS/Styling_text/Typesetting_a_homepage", "Learn/CSS/Styling_text")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Fundamentals">Texto fundamental y estilo de fuente</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_lists">Dar estilo a las listas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_links">Dar estilo a los enlaces</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Las fuentes web</a></li> + <li><a href="/en-US/Learn/CSS/Styling_text/Typesetting_a_homepage">Composición tipográfica de una página de inicio de una escuela comunitaria</a></li> +</ul> diff --git a/files/es/learn/css/styling_text/fundamentals/index.html b/files/es/learn/css/styling_text/fundamentals/index.html new file mode 100644 index 0000000000..a1fa747e27 --- /dev/null +++ b/files/es/learn/css/styling_text/fundamentals/index.html @@ -0,0 +1,732 @@ +--- +title: Fundamentos de texto y fuentes tipográficas +slug: Learn/CSS/Styling_text/Fundamentals +translation_of: Learn/CSS/Styling_text/Fundamentals +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/CSS/Styling_text/Styling_lists", "Learn/CSS/Styling_text")}}</div> + +<p class="summary"><span class="seoSummary">En este artículo vas a iniciar tu viaje hacia el dominio la aplicación de estilos a textos con {{glossary("CSS")}}. </span> Aquí trataremos en detalle todos los fundamentos básicos del diseño del texto y las fuentes tipográficas, incluyendo la configuración de su grosor, la familia y el estilo de letra, las propiedades abreviadas para los tipos de letra, la alineación del texto, el espaciado entre líneas y letras, y otros efectos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, conceptos básicos de HTML (estudio de <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>), conceptos básicos de CSS (estudio de <a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender las propiedades y técnicas fundamentales necesarias para dar estilo al texto en las páginas web.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_implica_aplicar_estilo_a_texto_en_CSS">¿Qué implica aplicar estilo a texto en CSS?</h2> + +<p>Como ya habrás experimentado en tu trabajo con el HTML y el CSS, el texto incluido en un elemento se dispone dentro de la caja de contenido del elemento. Esta empieza en la parte superior izquierda del área de contenido (o en la esquina superior derecha, en el caso del contenido de los lenguajes RTL, o right-to-left, que se escriben de derecha a izquierda) y fluye hacia el final de la línea. Una vez que llega al final, baja a la línea siguiente y sigue, y luego continúa a la línea siguiente, hasta que todo el contenido se ha ubicado en la caja. El contenido de texto se comporta efectivamente como una serie de elementos en línea, distribuidos en líneas adyacentes entre sí, y sin crear saltos de línea hasta que se llega al final de la línea, a menos que se fuerce un salto de línea manual con el elemento {{htmlelement("br")}}.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si el párrafo anterior te parece confuso, no te preocupes: vuelve atrás y revisa el artículo sobre el <a href="/es/docs/Learn/CSS/Building_blocks/El_modelo_de_caja">modelo de caja</a> antes de continuar.</p> +</div> + +<p>Las propiedades CSS que se usan para aplicar estilo al texto pueden clasificarse generalmente en dos categorías, que veremos por separado en este artículo:</p> + +<ul> + <li><strong>Estilos del tipo de letra</strong>: Propiedades que afectan al texto (qué tipo de letra se usa, su tamaño, si es negrita, itálica, etc.).</li> + <li><strong>Estilos de disposición del texto</strong>: Propiedades que afectan al espaciado y otras características relativas a la disposición del texto, lo que permite la elección de, por ejemplo, el espacio entre líneas y letras, y el modo como el texto se alinea dentro de la caja contenedora.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Ten en cuenta que el efecto se aplica sobre todo el texto que hay dentro de un elemento como si fuera una única entidad. No puedes seleccionar y dar estilo a subsecciones de texto, a menos que las delimites con algún elemento apropiado (como {{htmlelement("span")}} o {{htmlelement("strong")}}), o con un pseudoelemento específico para el texto como <a href="/es/docs/Web/CSS/::first-letter">::first-letter</a> (selecciona la primera letra del texto de un elemento), <a href="/es/docs/Web/CSS/::first-line">::first-line</a> (selecciona la primera línea del texto de un elemento), o <a href="/es/docs/Web/CSS/::selection">::selection</a> (selecciona el texto que está resaltado por el cursor).</p> +</div> + +<h2 id="Tipos_de_letra">Tipos de letra</h2> + +<p>Veamos las propiedades que permiten definir el estilo del tipo de letra. En este ejemplo aplicaremos algunas propiedades CSS diferentes al mismo ejemplo HTML, que presentamos a continuación:</p> + +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember it as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p></pre> + +<p>Puedes ver el <a href="http://mdn.github.io/learning-area/css/styling-text/fundamentals/">ejemplo completo en Github</a> (consulta también <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/fundamentals/index.html">el código fuente</a>.)</p> + +<h3 id="Color">Color</h3> + +<p>La propiedad {{cssxref("color")}} establece el color del contenido de los elementos seleccionados (que normalmente es texto, pero también puede incluir un par cosas más, como un subrayado o una línea superpuesta al texto con la propiedad {{cssxref("text-decoration")}} ).</p> + +<p>La propiedad <code>color</code> puede admitir cualquier <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS">unidad de color CSS</a>, por ejemplo:</p> + +<pre class="brush: css notranslate">p { + color: red; +}</pre> + +<p>Esto mostrará el contenido de los párrafos en color rojo, en lugar del negro que es el estándar por defecto del navegador:</p> + +<div class="hidden"> +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember it as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p></pre> +</div> + +<p>{{ EmbedLiveSample('Color', '100%', 220) }}</p> + +<h3 id="Familia_de_tipos_de_letras">Familia de tipos de letras</h3> + +<p>Usamos la propiedad {{cssxref("font-family")}} para definir un tipo de letra diferente para nuestro texto. Esta propiedad indica al navegador el tipo de letra (o una lista de tipos de letra) que debe aplicar a los elementos seleccionados. El navegador solo aplica el tipo de letra si la máquina que accede al sitio web dispone de ella; en caso contrario, simplemente usa el tipo de letra que tiene definido por defecto ({{anch("Default fonts", "default font")}}). Aquí tienes un ejemplo sencillo:</p> + +<pre class="brush: css notranslate">p { + font-family: arial; +}</pre> + +<p>Con esto, todos los párrafos de una página adoptan el tipo de letra Arial, que se encuentra en cualquier ordenador.</p> + +<h4 id="Tipos_de_letra_seguros_para_la_web">Tipos de letra seguros para la web</h4> + +<p>Solo hay un cierto número de tipos de letra que están disponibles en todos los sistemas en general, y que en consecuencia pueden utilizarse sin demasiadas preocupaciones. Son los llamados <em>tipos de letra seguros para la web</em>, o <em><strong>web safe fonts</strong></em>.</p> + +<p>La mayor parte del tiempo, como desarrolladores web deseamos tener un control específico mayor sobre los tipos de letra con que se va a mostrar para mostrar nuestro contenido de texto. El problema está en encontrar una manera de saber de qué tipo de letra dispone el ordenador que se utiliza para acceder a nuestras páginas. No hay manera de saber esto en todos los casos, pero al menos contamos con que los tipos de letra seguros para la web están disponibles en casi todos los sistemas operativos más utilizados (las distribuciones Linux más comunes, Windows, Mac, Android, e iOS).</p> + +<p>La lista de los tipos de letra seguros para la web cambia al ir evolucionando los sistemas operativos, pero es correcto considerar los tipos de letra siguientes como seguros para la web, al menos por ahora (muchos de ellos se han popularizado gracias a la iniciativa <em><a href="https://es.wikipedia.org/wiki/Core_fonts_for_the_Web">Core fonts for the web</a></em> de Microsoft, de finales de la década de 1990 y principios de la del 2000):</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Nombre</th> + <th scope="col" style="white-space: nowrap;">Tipo de letra genérico</th> + <th scope="col">Observaciones</th> + </tr> + </thead> + <tbody> + <tr> + <td>Arial</td> + <td>sans-serif</td> + <td>A menudo se considera una buena práctica añadir también <em>Helvética</em> como opción preferida a <em>Arial</em> porque, aunque tienen casi el mismo aspecto y <em>Arial</em> está más ampliamente disponible, se considera que <em>Helvética</em> tiene una forma más agradable.</td> + </tr> + <tr> + <td>Courier New</td> + <td>monospace</td> + <td>Algunos sistemas operativos cuentan con una versión alternativa (posiblemente más antigua) del tipo de letra <em>Courier New</em> llamado <em>Courier</em>. Se considera una buena práctica usar ambos, con <em>Courier New</em> como la opción preferida.</td> + </tr> + <tr> + <td style="white-space: nowrap;">Georgia</td> + <td>serif</td> + <td></td> + </tr> + <tr> + <td style="white-space: nowrap;">Times New Roman</td> + <td>serif</td> + <td>Algunos sistemas operativos cuentan con una versión alternativa (posiblemente más antigua) del tipo de letra <em>Times New Roman</em> llamado <em>Times</em>. Se considera una buena práctica usar ambos, con <em>Times New Roman</em> como la opción preferida.</td> + </tr> + <tr> + <td>Trebuchet MS</td> + <td>sans-serif</td> + <td>Hay que tener cuidado al usar este tipo de letra porque no está ampliamente disponible en los sistemas operativos móviles.</td> + </tr> + <tr> + <td>Verdana</td> + <td>sans-serif</td> + <td></td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Nota</strong>: Entre otros recursos, el sitio <a href="http://www.cssfontstack.com/">cssfontstack.com</a> mantiene una lista de tipos de letra seguros disponibles en los sistemas operativos para Windows y Mac, que puede ayudarte en la toma de decisiones acerca de lo que consideras seguro para tus propósitos.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Hay una manera de descargar un tipo de letra personalizado junto con la página web, que te permite personalizar el uso de los tipos de letra de la manera que desees: <strong>web fonts</strong>. Esto es un poco más complejo, y lo vamos a exponer más adelante en un <a href="/es/docs/Learn/CSS/Styling_text/Fuentes_web">artículo independiente</a> del módulo.</p> +</div> + +<h4 id="Fuentes_predeterminadas">Fuentes predeterminadas</h4> + +<p>CSS define cinco nombres genéricos para los tipos de letra <code>serif</code><font face="Open Sans, Arial, sans-serif">, </font><code>sans-serif</code>,<font face="Open Sans, Arial, sans-serif"> </font><code>monospace</code>, <code>cursive</code> y <code>fantasy</code>. Son muy genéricos y el tipo de letra exacto que se va a utilizar cuando se especifiquen dichos nombres dependerá de cada navegador y puede variar dependiendo del sistema operativo. Representa el <em>peor escenario posible</em>, en el que el navegador tratará de proporcionar al menos una fuente que parezca apropiada. <code>serif</code>, <code>sans-serif</code> y <code>monospace</code> son bastante predecibles y el navegador debería proporcionar algo razonable. Por otra parte, <code>cursive</code> y <code>fantasy</code> son menos predecibles y te recomendamos que las uses con cautela, y vayas probando a medida que avanzas.</p> + +<p>Los cinco nombres se definen de la manera siguiente:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Nombre</th> + <th scope="col">Definición</th> + <th scope="col">Ejemplo</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>serif</code></td> + <td>Tipos de letra que tienen <em><a href="https://es.wikipedia.org/wiki/Gracia_(tipograf%C3%ADa)">serifas</a></em> (pequeños adornos, en general en los extremos de los trazos de los caracteres tipográficos)</td> + <td><span style="font-family: serif;">Mi gran elefante rojo</span></td> + </tr> + <tr> + <td><code>sans-serif</code></td> + <td>Tipos de letra que carecen de <em>serifas</em>.</td> + <td><span style="font-family: sans-serif;">Mi gran elefante rojo</span></td> + </tr> + <tr> + <td><code>monospace</code></td> + <td>Tipos de letra en que cada carácter tiene el mismo ancho; se usan con frecuencia en las listas de sentencias de los códigos de programación.</td> + <td><span style="font-family: monospace;">Mi gran elefante rojo</span></td> + </tr> + <tr> + <td><code>cursive</code></td> + <td>Tipos de letra que intentan emular la letra manuscrita, con trazos fluidos y conectados.</td> + <td><span style="font-family: cursive;">Mi gran elefante rojo</span></td> + </tr> + <tr> + <td><code>fantasy</code></td> + <td>Tipos de letra que pensados para ser decorativos.</td> + <td><span style="font-family: fantasy;">Mi gran elefante rojo</span></td> + </tr> + </tbody> +</table> + +<h4 id="Listas_de_tipos_de_letra">Listas de tipos de letra</h4> + +<p>Ya que no puedes garantizar la disponibilidad de los tipos de letra que deseas utilizar (incluso un tipo de letra seguro para la web podría fallar por alguna razón), puedes proporcionar un <strong>lista de tipos de letra</strong> para que el navegador tenga diversos tipos de letra entre los que elegir. Consiste simplemente en introducirlo como el valor de <code>font-family</code>, que consistirá en una lista de diversos nombres de tipos de letra separados por comas, por ejemplo.</p> + +<pre class="brush: css notranslate">p { + font-family: "Trebuchet MS", Verdana, sans-serif; +}</pre> + +<p>En tal caso, el navegador comienza al principio de la lista y busca si el primer tipo de letra está disponible en la máquina. Si es así, aplica ese tipo de letra a los elementos seleccionados, y si no, lo intenta con el nombre siguiente de la lista; y así sucesivamente.</p> + +<p>Es una buena idea proporcionar un nombre de tipo de letra genérico al final de la lista para que el navegador pueda al menos proporcionar algo aproximadamente adecuado en el caso de que ninguno de los tipos de letra que deseas esté disponible. Para ilustrar este punto: los navegadores asignan a los párrafos el tipo de letra <em>serif</em> por defecto, que normalmente es Times New Roman, si no hay ninguna otra opción disponible, pero esto no resulta conveniente cuando se espera un tipo de letra <em>sans-serif</em>!</p> + +<div class="note"> +<p><strong>Nota</strong>: Los nombres de los tipos de letra que están constituidos por más de una palabra (como <code>Trebuchet MS</code> ) han de ponerse entre comillas, por ejemplo <code>"Trebuchet MS"</code>.</p> +</div> + +<h4 id="Un_ejemplo_con_font-family">Un ejemplo con font-family</h4> + +<p>Vamos a introducir en nuestro ejemplo anterior una fuente de tipo sans-serif para los párrafos:</p> + +<pre class="brush: css notranslate">p { + color: red; + font-family: Helvetica, Arial, sans-serif; +}</pre> + +<p>Esto nos da el resultado siguiente:</p> + +<div class="hidden"> +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember it as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p></pre> +</div> + +<p>{{ EmbedLiveSample('Un_ejemplo_con_font-family', '100%', 220) }}</p> + +<h3 id="Tamaño_de_la_letra">Tamaño de la letra</h3> + +<p>En el artículo sobre <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS">Unidades y valores de CSS</a> de nuestro módulo anterior, revisamos las unidades de longitud y tamaño. El tamaño del tipo de letra (establecido con la propiedad {{cssxref("font-size")}}) puede tomar valores medidos en la mayoría de estas unidades (y en otras, como <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS#Porcentajes">porcentajes</a>). Sin embargo, las unidades más comunes que vas a usar para ajustar el tamaño del texto son:</p> + +<ul> + <li>Unidades <code>px</code> (píxeles): El número de píxeles de altura que deseas que tenga el texto. Esta es una unidad absoluta, da como resultado el mismo valor calculado final para el tipo de letra en la página en casi cualquier situación.</li> + <li>Unidades <code>em</code>: 1em equivale al tamaño de tipo de letra que se haya establecido en el elemento padre del elemento activo al que aplicamos estilo (más específicamente, el ancho de una letra M mayúscula contenida dentro del elemento padre). Este puede ser complejo de resolver si hay muchos elementos anidados con diferentes tamaños de tipo de letra establecidos, pero es factible, como verás a continuación. Pero, ¿para qué molestarse en ello? Porque resulta bastante natural una vez que te acostumbras a ello, y puedes usar unidades <code>em</code> para establecer el tamaño de todo, no solo del texto. Puedes tener un sitio web completo dimensionado con unidades <code>em</code>, lo que facilita su mantenimiento.</li> + <li>Unidades <code>rem</code>: Funcionan igual que las unidades <code>em</code>, excepto que 1<code>rem</code> equivale al tamaño del tipo de letra establecido en el elemento raíz del documento (es decir, en {{htmlelement("html")}}), no en el elemento padre. Esto facilita mucho los cálculos de los tamaños del tipo de letra, aunque te puede dar mucha guerra si quieres incluir navegadores que ya son muy antiguos porque las versiones de Internet Explorer 8 y anteriores no admiten la unidad <code>rem</code>.</li> +</ul> + +<p>La propiedad <code>font-size</code> de un elemento se hereda del elemento padre. Todo comienza con el elemento raíz de todo el documento ({{htmlelement("html")}}) cuya propiedad <code>font-size</code> se establece a en 16px como estándar en todos los navegadores. Cualquier párrafo (o cualquier otro elemento que no tenga un tamaño diferente establecido por el navegador) dentro del elemento raíz tendrá un tamaño final de 16px. Otros elementos pueden tener diferentes tamaños predeterminados, por ejemplo un elemento {{htmlelement("h1")}} tiene de manera predeterminada un tamaño establecido de 2em, por lo que tendrá un tamaño final de 32px.</p> + +<p>Las cosas se vuelven más complicadas cuando se empieza a alterar el tamaño del tipo de letra de los elementos anidados. Por ejemplo, si tu página incluye un elemento {{htmlelement("article")}} y estableces un tamaño de fuente de <code>1.5em</code> (que resultará en un tamaño final de 24px), y luego quieres que los párrafos dentro del elemento <code><article></code> tengan un tamaño de letra calculado de 20px, ¿qué valor de unidad <code>em</code> deberías usar?</p> + +<pre class="brush: html notranslate"><!-- El tamaño de letra base del documento es 16px --> +<article> <!-- Si mi tamaño de letra es 1.5em --> + <p>Mi párrafo</p> <!-- ¿Cómo calculo el tamaño del tipo de letra para que de 20px? --> +</article></pre> + +<p>Necesitarías establecer el valor en unidades <code>em</code> de 20/24, es decir, <code>0.83333333 em</code>. El cálculo puede ser complicado, por lo que hay que pensarlo bien a la hora de aplicar estilo a las cosas. Lo mejor es usar unidades <code>rem</code> donde se pueda, porque simplifican las cosas, y evitar establecer un tamaño de letra concreto para los elementos del contenedor, siempre que sea posible.</p> + +<h4 id="Un_ejemplo_sencillo_de_definición_de_tamaños">Un ejemplo sencillo de definición de tamaños</h4> + +<p>Al dimensionar el texto, en general es una buena idea establecer el tamaño básico del tipo de letra del documento (<code>font-size</code>) en 10 px, de modo que los cálculos son mucho más fáciles de resolver, puesto que entonces los valores (r)em que necesites son el tamaño del tipo de letra en píxeles dividido por 10, no por 16. Luego de hacer eso, puedes establecer con facilidad los diferentes tamaños de los tipos de letra de tu documento como desees. Es una buena idea hacer una lista de todos los conjuntos de reglas de tamaño de fuente (<code>font-size</code>) en una zona concreta de tu hoja de estilo para que resulten fáciles de encontrar.</p> + +<p>Nuestro nuevo resultado es:</p> + +<div class="hidden"> +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember it as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p> +</pre> +</div> + +<pre class="brush: css notranslate">html { + font-size: 10px; +} + +h1 { + font-size: 2.6rem; +} + +p { + font-size: 1.4rem; + color: red; + font-family: Helvetica, Arial, sans-serif; +}</pre> + +<p>{{ EmbedLiveSample('Un_ejemplo_sencillo_de_definición_de_tamaños', '100%', 220) }}</p> + +<h3 id="Estilo_y_cuerpo_del_tipo_de_letra_efectos_y_decoración_del_texto">Estilo y cuerpo del tipo de letra, efectos y decoración del texto</h3> + +<p>El CSS proporciona cuatro propiedades comunes para alterar el efecto visual / énfasis del texto:</p> + +<ul> + <li>{{cssxref("font-style")}}: Se usa para activar y desactivar el texto en cursiva. Los valores posibles son los siguientes (raramente usarás esto, a menos que desees desactivar algún estilo de cursiva por alguna razón): + <ul> + <li><code>normal</code>: Pone el texto en tipo de letra normal (desactiva la cursiva).</li> + <li><code>italic</code>: Pone el texto en la versión cursiva del tipo de letra, si está disponible; si no está disponible, simulará cursiva con el modo <code>oblique</code> en su lugar.</li> + <li><code>oblique</code>: Pone el texto en una versión de tipo de letra cursiva simulada, que se genera inclinando la versión normal.</li> + </ul> + </li> + <li>{{cssxref("font-weight")}}: Establece el grueso o peso del texto. Puede haber muchos valores si dispones de muchas variantes de fuente (como <em>-light</em>, <em>-normal</em>, <em>-bold</em>, <em>-extrabold</em>, <em>-black</em>, etc.), pero en realidad raramente usarás alguna de ellas, más allá de los estilos <code>normal</code> y <code>bold</code>: + <ul> + <li><code>normal</code>, <code>bold</code>: Grueso del tipo de letra normal y <strong style="font-weight: bold;">negrita</strong></li> + <li><code>lighter</code>, <code>bolder</code>: Establece el grueso de la negrita del elemento activo un nivel por debajo o por encima del grueso de su elemento padre.</li> + <li><code>100</code>–<code>900</code>: Valores numéricos de negrita, que proporcionan un control más detallado que las palabras clave anteriores, si es necesario.</li> + </ul> + </li> + <li>{{cssxref("text-transform")}}: Te permite practicar algunas transformaciones sobre tu tipo de letra. Los valores incluyen: + <ul> + <li><code>none</code>: Impide cualquier transformación.</li> + <li><code>uppercase</code>: Transforma TODO EL TEXTO A MAYÚSCULAS.</li> + <li><code>lowercase</code>: Transforma todo el texto a minúsculas.</li> + <li><code>capitalize</code>: Transforma <span style="text-transform: capitalize;">Las Letras Iniciales De Cada Palabra A Mayúscula</span>.</li> + <li><code>full-width</code>: Transforma todos los caracteres para cada uno quede <span style="text-transform: full-width;">dentro de una caja de ancho fijo</span>, similar a una fuente monoespaciada, lo que permite, por ejemplo, la alineación de caracteres latinos junto con caracteres asiáticos (chino, japonés, coreano.)</li> + </ul> + </li> + <li>{{cssxref("text-decoration")}}: Activa/desactiva decoraciones en los tipos de letra (usarás esto principalmente para desactivar el subrayado por defecto de los enlaces al aplicarles estilo). Los valores disponibles son: + <ul> + <li><code>none</code>: Desactiva cualquier decoración de texto que presente.</li> + <li><code>underline</code>: <u>Subraya el texto</u>.</li> + <li><code>overline</code>: <span style="text-decoration: overline;">Proporciona al texto una línea superpuesta</span>.</li> + <li><code>line-through</code>: Coloca un <s style="text-decoration: line-through;">tachado sobre el texto</s>.</li> + </ul> + Observa que {{cssxref("text-decoration")}} puede aceptar diversos valores a la vez, de modo que puedes incluir diversas decoraciones simultáneas, por ejemplo <span style="text-decoration: underline overline;"><code>text-decoration: underline overline</code></span>. Ten encuenta también que {{cssxref("text-decoration")}} es una propiedad abreviada de {{cssxref("text-decoration-line")}}, {{cssxref("text-decoration-style")}} y {{cssxref("text-decoration-color")}}. Puedes utilizar combinaciones de los valores de esta propiedad para crear efectos interesantes, por ejemplo <span style="text-decoration: line-through red wavy;"><code>text-decoration: line-through red wavy</code>.</span></li> +</ul> + +<p>Añadamos un par de estas propiedades a nuestro ejemplo. Nuestro nuevo resultado quedaría como este:</p> + +<div class="hidden"> +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember it as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p> +</pre> +</div> + +<pre class="brush: css notranslate">html { + font-size: 10px; +} + +h1 { + font-size: 2.6rem; + text-transform: capitalize; +} + +h1 + p { + font-weight: bold; +} + +p { + font-size: 1.4rem; + color: red; + font-family: Helvetica, Arial, sans-serif; +}</pre> + +<p>{{ EmbedLiveSample('Estilo_y_cuerpo_del_tipo_de_letra_efectos_y_decoración_del_texto', '100%', 220) }}</p> + +<h3 id="Textos_sombreados">Textos sombreados</h3> + +<p>Puedes aplicar sombras a tus textos con la propiedad {{cssxref("text-shadow")}}. Esta propiedad puede tomar hasta cuatro valores, como se muestra en ejemplo siguiente:</p> + +<pre class="brush: css notranslate">text-shadow: 1px 1px 1px red;</pre> + +<p>Las cuatro propiedades son las siguientes:</p> + +<ol> + <li>El desplazamiento horizontal de la sombra desde el texto original; admite la mayoría de las <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS">unidades y magnitudes</a> de que dispone CSS, pero lo más habitual es usar <code>px</code>. Es un valor obligatorio.</li> + <li>El desplazamiento vertical de la sombra desde el texto original; se comporta básicamente igual que el desplazamiento horizontal, excepto porque mueve la sombra arriba/abajo, y no hacia derecha/izquierda. Es un valor obligatorio.</li> + <li>El radio de desenfoque; cuanto más alto es este valor, mayor es la dispersión de la sombra. Si no se incluye este valor, el valor por defecto es 0, y no hay desenfoque. Esta propiedad admite la mayoría de las <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS">unidades y magnitudes</a> de que dispone el CSS.</li> + <li>El color de base de la sombra, que admite cualquier <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS">unidad de color de que dispone CSS</a>. Si no se incluye este valor, el valor predeterminado es <code>negro</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Los valores con desplazamiento positivo mueven la sombra hacia la derecha o hacia abajo, mientras que los valores con desplazamiento negativo, por ejemplo <code>-1px -1px</code>, mueven la sombrea hacia la izquierda o hacia arriba.</p> +</div> + +<h4 id="Sombras_múltiples">Sombras múltiples</h4> + +<p>Puedes aplicar diversas sombras al mismo texto incluyendo múltiples valores de sombra separados por comas, por ejemplo:</p> + +<pre class="brush: css notranslate"><code class="language-css"><span class="property token">text-shadow</span><span class="punctuation token">:</span> -<span class="number token">1</span>px -<span class="number token">1</span>px <span class="number token">1</span>px <span class="hexcode token">#aaa</span>, + <span class="number token">0</span>px <span class="number token">4</span>px <span class="number token">1</span>px <span class="function token">rgba</span><span class="punctuation token">(</span><span class="number token">0</span>,<span class="number token">0</span>,<span class="number token">0</span>,<span class="number token">0.5</span><span class="punctuation token">)</span>, + <span class="number token">4</span>px <span class="number token">4</span>px <span class="number token">5</span>px <span class="function token">rgba</span><span class="punctuation token">(</span><span class="number token">0</span>,<span class="number token">0</span>,<span class="number token">0</span>,<span class="number token">0.7</span><span class="punctuation token">)</span>, + <span class="number token">0</span>px <span class="number token">0</span>px <span class="number token">7</span>px <span class="function token">rgba</span><span class="punctuation token">(</span><span class="number token">0</span>,<span class="number token">0</span>,<span class="number token">0</span>,<span class="number token">0.4</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> + +<p>Si aplicamos esto al elemento {{htmlelement("h1")}} de nuestro ejemplo <em>Tommy The Cat</em>, obtenemos esto:</p> + +<div class="hidden"> +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember it as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p> +</pre> + +<pre class="brush: css notranslate">html { + font-size: 10px; +} + +h1 { + font-size: 26px; + text-transform: capitalize; + text-shadow: -1px -1px 1px #aaa, + 0px 2px 1px rgba(0,0,0,0.5), + 2px 2px 2px rgba(0,0,0,0.7), + 0px 0px 3px rgba(0,0,0,0.4); +} + +h1 + p { + font-weight: bold; +} + +p { + font-size: 14px; + color: red; + font-family: Helvetica, Arial, sans-serif; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Sombras_múltiples', '100%', 220) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes ver más ejemplos interesantes del uso de <code>text-shadow</code> en el artículo de <em>Sitepoint</em> <a href="http://www.sitepoint.com/moonlighting-css-text-shadow/">Moonlighting with CSS text-shadow</a>.</p> +</div> + +<h2 id="Diseño_del_texto">Diseño del texto</h2> + +<p>Una vez tratadas las propiedades básicas para los tipos de letra, echemos un vistazo a las propiedades que podemos usar para la disposición del texto.</p> + +<h3 id="Alineación_del_texto">Alineación del texto</h3> + +<p>La propiedad {{cssxref("text-align")}} se usa para controlar la forma en que el texto se alinea dentro de la caja que lo contiene. Los valores disponibles para esta propiedad son los siguientes, y funcionan de la misma forma que en una aplicación de procesamiento de texto:</p> + +<ul> + <li><code>left</code>: Alinea el texto por la izquierda.</li> + <li><code>right</code>: Alinea el texto por la derecha.</li> + <li><code>center</code>: Centra el texto.</li> + <li><code>justify</code>: Varía los espacios entre las palabras para que todas las líneas de texto tengan el mismo ancho. Debes usar este valor con prudencia porque puede quedar terrible, especialmente si el párrafo al que se aplica contiene muchas palabras largas. Si tienes intención de utilizar esta propiedad, también deberías pensar en alguna otra, como {{cssxref("hyphens")}}, para dividir las palabras largas entre las líneas.</li> +</ul> + +<p>Si aplicamos <code>text-align: center;</code> al elemento {{htmlelement("h1")}} de nuestro ejemplo, obtendremos esto:</p> + +<div class="hidden"> +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p> +</pre> + +<pre class="brush: css notranslate">html { + font-size: 10px; +} + +h1 { + font-size: 2.6rem; + text-transform: capitalize; + text-shadow: -1px -1px 1px #aaa, + 0px 2px 1px rgba(0,0,0,0.5), + 2px 2px 2px rgba(0,0,0,0.7), + 0px 0px 3px rgba(0,0,0,0.4); + text-align: center; +} + +h1 + p { + font-weight: bold; +} + +p { + font-size: 1.4rem; + color: red; + font-family: Helvetica, Arial, sans-serif; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Alineación_del_texto', '100%', 220) }}</p> + +<h3 id="Interlineado">Interlineado</h3> + +<p>La propiedad {{cssxref("line-height")}} establece la altura entre cada línea de texto; esta propiedad admite la mayoría de las <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS">unidades y magnitudes</a>, pero también puede tomar un valor sin unidades, que actúa como un multiplicador y generalmente se considera la mejor opción porque se multiplica la propiedad {{cssxref("font-size")}} para obtener la altura de la línea (<code>line-height</code>). El texto del cuerpo (<code>body</code>) generalmente se ve mejor y es más fácil de leer si hay más separación entre las líneas; la altura recomendada de la línea es entre 1.5-2 (a doble espacio). Por lo tanto, para configurar nuestras líneas de texto a 1.5 veces la altura de la fuente, deberías usar esto:</p> + +<pre class="brush: css notranslate">line-height: 1.5;</pre> + +<p>Aplicando esto a los elementos {{htmlelement("p")}} en nuestro ejemplo nos daría este resultado:</p> + +<div class="hidden"> +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember it as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p> +</pre> + +<pre class="brush: css notranslate">html { + font-size: 10px; +} + +h1 { + font-size: 2.6rem; + text-transform: capitalize; + text-shadow: -1px -1px 1px #aaa, + 0px 2px 1px rgba(0,0,0,0.5), + 2px 2px 2px rgba(0,0,0,0.7), + 0px 0px 3px rgba(0,0,0,0.4); + text-align: center; +} + +h1 + p { + font-weight: bold; +} + +p { + font-size: 1.4rem; + color: red; + font-family: Helvetica, Arial, sans-serif; + line-height: 1.5; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Interlineado', '100%', 250) }}</p> + +<h3 id="Espacio_entre_letras_y_espacio_entre_palabras">Espacio entre letras y espacio entre palabras</h3> + +<p>Las propiedades {{cssxref("letter-spacing")}} y {{cssxref("word-spacing")}} te permiten establecer el espacio entre las letras y entre las palabras del texto. No los usarás a menudo, pero podría ser útil para obtener una apariencia determinada o para mejorar la legibilidad de un tipo de letra particularmente denso. Estas propiedades admiten la mayoría de las <a href="/es/docs/Learn/CSS/Building_blocks/Valores_y_unidades_CSS">unidades y magnitudes</a>.</p> + +<p>Así, como ejemplo, podemos aplicar a la primera línea de los elementos {{htmlelement("p")}} de nuestro ejemplo lo siguiente:</p> + +<pre class="brush: css notranslate">p::first-line { + letter-spacing: 2px; + word-spacing: 4px; +}</pre> + +<p>y obtendremos:</p> + +<div class="hidden"> +<pre class="brush: html notranslate"><h1>Tommy the cat</h1> + +<p>Well I remember it as though it were a meal ago...</p> + +<p>Said Tommy the Cat as he reeled back to clear whatever foreign matter + may have nestled its way into his mighty throat. Many a fat alley rat +had met its demise while staring point blank down the cavernous barrel of + this awesome prowling machine. Truly a wonder of nature this urban +predator — Tommy the cat had many a story to tell. But it was a rare +occasion such as this that he did.</p> +</pre> + +<pre class="brush: css notranslate">html { + font-size: 10px; +} + +h1 { + font-size: 2.6rem; + text-transform: capitalize; + text-shadow: -1px -1px 1px #aaa, + 0px 2px 1px rgba(0,0,0,0.5), + 2px 2px 2px rgba(0,0,0,0.7), + 0px 0px 3px rgba(0,0,0,0.4); + text-align: center; +} + +h1 + p { + font-weight: bold; +} + +p::first-line { + letter-spacing: 2px; + word-spacing: 4px; +} + +p { + font-size: 1.4rem; + color: red; + font-family: Helvetica, Arial, sans-serif; + line-height: 1.5; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Espacio_entre_letras_y_espacio_entre_palabras', '100%', 250) }}</p> + +<h3 id="Otras_propiedades_interesantes">Otras propiedades interesantes</h3> + +<p>Las propiedades anteriores nos dan una idea de cómo empezar a aplicar texto a una página web, pero hay muchas más propiedades que puedes usar. Nuestro objetivo aquí es solo exponer las más importantes. Cuando te hayas acostumbrado a usar las propiedades anteriores, también deberías explorar las siguientes:</p> + +<p>Aplicación de estilos a tipos de letra:</p> + +<ul> + <li>{{cssxref("font-variant")}}: Cambia entre las opciones de versalita y normal del tipo de letra.</li> + <li>{{cssxref("font-kerning")}}: Activa/Desactiva las opciones de interletraje del tipo de letra.</li> + <li>{{cssxref("font-feature-settings")}}: Activa/Desactiva diversas características de los tipos de letra <a href="https://en.wikipedia.org/wiki/OpenType">OpenType</a>.</li> + <li>{{cssxref("font-variant-alternates")}}: Controla el uso de los caracteres alternativos para un tipo de letra dado.</li> + <li>{{cssxref("font-variant-caps")}}: Controla el uso de los caracteres alternativos de las mayúsculas.</li> + <li>{{cssxref("font-variant-east-asian")}}: Controla el uso de los caracteres alternativos en textos en idiomas del Asia Oriental, como el japonés y el chino.</li> + <li>{{cssxref("font-variant-ligatures")}}: Controla qué ligaduras y formas contextuales se usarán en el texto.</li> + <li>{{cssxref("font-variant-numeric")}}: Controla el uso de los caracteres alternativos para números, fracciones y marcadores de ordinales.</li> + <li>{{cssxref("font-variant-position")}}: Controla el uso de los caracteres alternativos de tamaños más pequeños posicionados como subíndice y superíndice.</li> + <li>{{cssxref("font-size-adjust")}}: Ajusta el tamaño visual del texto independientemente del tamaño real del tipo de letra.</li> + <li>{{cssxref("font-stretch")}}: Cambia entre posibles versiones ampliadas de un tipo de letra determinado.</li> + <li>{{cssxref("text-underline-position")}}: Especifica la posición de los subrayados con el valor <code>underline</code> de la propiedad <code>text-decoration-line</code>.</li> + <li>{{cssxref("text-rendering")}}: Intenta optimizar la representación del texto.</li> +</ul> + +<p>Estilos de disposición de los textos</p> + +<ul> + <li>{{cssxref("text-indent")}}: Especifica el espacio horizontal que debe dejarse antes del comienzo de la primera línea del contenido de texto.</li> + <li>{{cssxref("text-overflow")}}: Define cómo se señala el contenido que los usuarios no ven porque desborda.</li> + <li>{{cssxref("white-space")}}: Define cómo se usan los espacios en blanco y los saltos de línea asociados dentro del elemento.</li> + <li>{{cssxref("word-break")}}: Especifica si se deben dividir las palabras a final de línea.</li> + <li>{{cssxref("direction")}}: Define la dirección del texto (esto depende del idioma, y por lo general es mejor dejar que HTML maneje esa parte, porque está vinculada al contenido del texto).</li> + <li>{{cssxref("hyphens")}}: Activa/Desactiva la separación de palabras en los idiomas admitidos.</li> + <li>{{cssxref("line-break")}}: Relaja o refuerza el salto de línea en los idiomas asiáticos.</li> + <li>{{cssxref("text-align-last")}}: Define cómo es la alineación de la última línea de un bloque o línea justo antes de un salto de línea forzado.</li> + <li>{{cssxref("text-orientation")}}: Define la orientación del texto en una línea.</li> + <li>{{cssxref("word-wrap")}}: Especifica si el navegador puede dividir palabras a final de línea para evitar desbordamientos del contenido.</li> + <li>{{cssxref("writing-mode")}}: Define si las líneas de texto se disponen en horizontal o en vertical y la dirección en la que fluyen las líneas subsiguientes.</li> +</ul> + +<h2 id="Propiedades_abreviadas_para_los_tipos_de_letra">Propiedades abreviadas para los tipos de letra</h2> + +<p>Muchas propiedades relativas a los tipos de letra también pueden establecerse de forma abreviada con la propiedad {{cssxref("font")}}. Se escriben en el orden siguiente: {{cssxref("font-style")}}, {{cssxref("font-variant")}}, {{cssxref("font-weight")}}, {{cssxref("font-stretch")}}, {{cssxref("font-size")}}, {{cssxref("line-height")}}, and {{cssxref("font-family")}}.</p> + +<p>De entre todas estas propiedades, solo <code>font-size</code> y <code>font-family</code> son obligatorias al usar la propiedad abreviada de <code>font</code>.</p> + +<p>Se debe colocar una barra inclinada (<em>slash</em>) entre las propiedades {{cssxref("font-size")}} y {{cssxref("line-height")}}.</p> + +<p>Un ejemplo completo se vería así:</p> + +<pre class="brush: css notranslate">font: italic normal bold normal 3em/1.5 Helvetica, Arial, sans-serif;</pre> + +<h2 id="Aprendizaje_activo_Jugar_a_aplicar_estilos">Aprendizaje activo: Jugar a aplicar estilos</h2> + +<p>En esta sección de aprendizaje activo no proponemos ningún ejercicio específico: Simplemente nos gustaría que juegues con algunas propiedades de diseño de tipo de letra / texto, ¡y a ver qué consigues! Puedes hacer esto con archivos HTML/CSS sin conexión, o puedes introducir tu código en el ejemplo editable en vivo a continuación.</p> + +<p>Si te equivocas, puedes volver a empezar con el botón <em>Reinicio</em>.</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><div class="body-wrapper" style="font-family: 'Open Sans Light',Helvetica,Arial,sans-serif;"> + <h2>HTML Input</h2> + <textarea id="code" class="html-input" style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;"> + <p>Some sample text for your delight</p></textarea> + + <h2>CSS Input</h2> + <textarea id="code" class="css-input" style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;">p { + + }</textarea> + + <h2>Output</h2> + <div class="output" style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;"></div> + <div class="controls"> + <input id="reset" type="button" value="Reset" style="margin: 10px 10px 0 0;"> + </div> +</div> +</pre> + +<pre class="brush: js notranslate">var htmlInput = document.querySelector(".html-input"); +const cssInput = document.querySelector(".css-input"); +const reset = document.getElementById("reset"); +let htmlCode = htmlInput.value; +let cssCode = cssInput.value; +const output = document.querySelector(".output"); + +const styleElem = document.createElement('style'); +const headElem = document.querySelector('head'); +headElem.appendChild(styleElem); + +function drawOutput() { + output.innerHTML = htmlInput.value; + styleElem.textContent = cssInput.value; +} + +reset.addEventListener("click", function() { + htmlInput.value = htmlCode; + cssInput.value = cssCode; + drawOutput(); +}); + +htmlInput.addEventListener("input", drawOutput); +cssInput.addEventListener("input", drawOutput); +window.addEventListener("load", drawOutput); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 800) }}</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Esperamos que hayas disfrutado jugando con el texto en este artículo. El próximo artículo te enseñará todo lo que necesitas saber sobre la aplicación de estilos de lista en HTML.</p> + +<p>{{NextMenu("Learn/CSS/Styling_text/Styling_lists", "Learn/CSS/Styling_text")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Fundamentals">Aplicar estilo al texto base y tipos de letra</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_lists">Aplicación de estilo a listas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_links">Aplicación de estilo a enlaces</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Tipos de letra para web</a></li> + <li><a href="/en-US/Learn/CSS/Styling_text/Typesetting_a_homepage">Escribir una página de inicio para la comunidad escolar</a></li> +</ul> diff --git a/files/es/learn/css/styling_text/index.html b/files/es/learn/css/styling_text/index.html new file mode 100644 index 0000000000..a87012ec5c --- /dev/null +++ b/files/es/learn/css/styling_text/index.html @@ -0,0 +1,57 @@ +--- +title: Estilo de texto +slug: Learn/CSS/Styling_text +tags: + - Beginner + - CSS + - CodingScripting + - Fonts + - Landing + - Links + - Module + - NeedsTranslation + - Text + - TopicStub + - font + - letter + - line + - lists + - shadow + - web fonts +translation_of: Learn/CSS/Styling_text +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Con los conceptos básicos del lenguaje CSS cubiertos, el siguiente tema de CSS para concentrarse es estilizar texto — una de las cosas más comunes que hará con CSS. Aquí observamos los fundamentos para estilizar texto, incluyendo la configuración de fuente, negrita, cursiva, linea y espacios entre letras, sombras paralelas y otras funciones de texto. Completamos el módulo observando la aplicación de fuentes personalizadas en su página, y el diseño de listas y enlaces.</p> + +<h2 id="Requisitos_previos">Requisitos previos</h2> + +<p>Antes de iniciar este módulo, ya debe estár familizarizado con HTML, como se explica en el módulo <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">Introducción a HTML</a>, y sentirse cómodo con los fundamentos de CSS, como se explica en <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">Introducción a CSS</a>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si está trabajando en una computadora/tableta/u otro dispositivo donde no tenga la capacidad de crear sus propios archivos, puede probar (la mayoría) de los ejemplos de código en un programa de codificación en línea como <a href="http://jsbin.com/">JSBin</a>,<a href="https://codepen.io/"> CodePen</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<p>Este módulo contiene los siguientes artículos, los cuales le enseñarán todos los elementos esenciales detras del diseño de contenido de texto HTML.</p> + +<dl> + <dt><a href="/en-US/docs/Learn/CSS/Styling_text/Fundamentals">Texto fundamental y estilo de fuente</a></dt> + <dd>En este artículo iremos a través de todos los aspectos básicos del estilo de texto/fuente en detalle, incluyendo configuraciones del peso de la fuente, la familia y el estilo, taquigrafía de fuente, alineación de texto y otros efectos, línea y espaciado de letras.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_lists">Estilos de listas</a></dt> + <dd>Las listas, en su mayor parte, se comportan como cualquier otro texto, pero hay algunas propiedades de CSS específicas para las listas que debe conocer, y algunas de las mejores prácticas para tener en cuenta. Este artículo explica todo.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_links">Estilos de enlaces</a></dt> + <dd>Al diseñar enlaces, es importante comprender cómo hacer uso de pseudo-clases para diseñar estados de enlaces de manera efectiva, y cómo diseñar enlaces para su uso en características de interfaces variadas comunes tales como menús de navegación y pestañas. Veremos todos estos temas en este artículo.</dd> + <dt><a href="/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Fuentes web</a></dt> + <dd>Aquí exploraremos las fuentes web en detalle — estas permiten descargar fuentes personalizadas junto con su página web, para permitir un estilo de texto más variado y personalizado.</dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<p>Las siguientes evaluaciones pondrán a prueba su comprensión de las técnicas del diseño de texto cubiertas en las guías anteriores.</p> + +<dl> + <dt><a href="/en-US/Learn/CSS/Styling_text/Typesetting_a_homepage">Escribiendo una página de inicio para la comunidad de la escuela</a></dt> + <dd>En esta evaluación, pondremos a prueba su comprensión del estilo del texto haciendo que redacte el texto de la página principal de la escuela comunitaria.</dd> +</dl> diff --git a/files/es/learn/css/styling_text/styling_links/index.html b/files/es/learn/css/styling_text/styling_links/index.html new file mode 100644 index 0000000000..b5180d51df --- /dev/null +++ b/files/es/learn/css/styling_text/styling_links/index.html @@ -0,0 +1,434 @@ +--- +title: Dar estilo a los enlaces +slug: Learn/CSS/Styling_text/Styling_links +translation_of: Learn/CSS/Styling_text/Styling_links +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/Styling_text/Styling_lists", "Learn/CSS/Styling_text/Web_fonts", "Learn/CSS/Styling_text")}}</div> + +<p class="summary">A la hora de dar estilo a los <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/Creating_hyperlinks">enlaces</a>, es importante comprender cómo utilizar las pseudoclases para diseñar los estados de un enlace de manera efectiva y cómo diseñar enlaces para su uso en diversas funciones de interfaz comunes, como menús y pestañas de navegación. Veremos todos estos temas en este artículo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, conceptos básicos de HTML (véase <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>), conocimientos básicos de CSS (véase <a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a>), <a href="/es/docs/Learn/CSS/Styling_text/Fundamentals">nociones de aplicación de estilo con CSS a textos y tipos de letra</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a dar formato a los estados de un enlace y a usarlos de manera efectiva en algunas funciones de interfaz de usuario comunes, como los menús de navegación.</td> + </tr> + </tbody> +</table> + +<h2 id="Echemos_un_vistazo_a_algunos_enlaces">Echemos un vistazo a algunos enlaces</h2> + +<p>Analizamos cómo se implementan los enlaces en tu HTML de acuerdo con las buenas prácticas de <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/Creating_hyperlinks">Creación de hipervínculos</a>. En este artículo desarrollaremos estos conocimientos y te mostraremos las buenas prácticas del diseño de enlaces.</p> + +<h3 id="Los_estados_de_un_enlace">Los estados de un enlace</h3> + +<p>Lo primero que hay que entender es el concepto de estados de un enlace (diferentes estados en los que pueden estar los enlaces, que pueden diseñarse usando diferentes <a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS">pseudoclases</a>):</p> + +<ul> + <li><strong>Link (no visitado)</strong>: El estado predeterminado que presenta un enlace cuando no está en ningún otro estado. Se puede especificar usando la pseudoclase {{cssxref(":link")}}.</li> + <li><strong>Visited</strong>: Un enlace cuando ya se ha visitado (está grabado en el historial del navegador); se le aplica otro formato con la pseudoclase {{cssxref(":visited")}}.</li> + <li><strong>Hover</strong>: Un enlace cuando se le pasa el cursor por encima; se le aplica otro formato con la pseudoclase {{cssxref(":hover")}}.</li> + <li><strong>Focus</strong>: Un enlace cuando tiene el foco (por ejemplo, se salta a este con la tecla <kbd>Tab</kbd> del teclado o se le da el foco mediante programación usando {{domxref("HTMLElement.focus()")}}); se le aplica un formato diferente con la pseudoclase {{cssxref(":focus")}}.</li> + <li><strong>Active</strong>: Un enlace cuando se activa (por ejemplo, se hace clic encima); se le aplica un formato diferente con la pseudoclase {{cssxref(":active")}}.</li> +</ul> + +<h3 id="Estilos_predeterminados">Estilos predeterminados</h3> + +<p>El ejemplo siguiente ilustra cómo se comportará un enlace por defecto (el CSS simplemente amplía y centra el texto para que destaque más).</p> + +<pre class="brush: html notranslate"><p><a href="#">Un enlace simple</a></p> +</pre> + +<pre class="brush: css notranslate">p { + font-size: 2rem; + text-align: center; +}</pre> + +<p>{{ EmbedLiveSample('Estilos_predeterminados', '100%', 120) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Todos los enlaces que hay en los ejemplos de esta página son simulados, encontrarás un símbolo <code>#</code> (almohadilla) en el lugar de una URL real. Esto es porque si incluyéramos enlaces reales, los ejemplos quedarían interrumpidos al hacer clic (daría error, o se cargaría una página en el ejemplo incrustado de la que no podrías volver atrás). <code>#</code> solo establece enlaces dentro de la misma página.</p> +</div> + +<p>A medida que explores los estilos predeterminados, observarás algunas cosas:</p> + +<ul> + <li>Los enlaces están subrayados.</li> + <li>Los enlaces no visitados se ven de color azul.</li> + <li>Los enlaces visitados se ven de color morado.</li> + <li>Al pasar el puntero del ratón sobre un enlace, cambia a un pequeño icono en forma de mano.</li> + <li>Los enlaces que tienen el foco presentan un contorno alrededor: deberías poder saltar por los enlaces de esta página con el teclado pulsando la tecla de tabulación (en Mac, es posible que necesites habilitar la opción <em>Acceso total por teclado: Todos los controles</em> presionando <kbd>Ctrl</kbd> + <kbd>F7</kbd> para que funcione).</li> + <li>Los enlaces activos se muestran de color rojo (intenta mantener el cursor sobre el enlace mientras haces clic).</li> +</ul> + +<p>Curiosamente, estos estilos predeterminados son casi los mismos que se utilizaban al inicio de los navegadores en la década de 1990. Esto se debe a que los usuarios conocen y esperan que sea de esta forma. Podría confundir a mucha gente que los enlaces se mostrasen de manera diferente. Esto no quiere decir que no puedas cambiar el formato de los enlaces, solo que no deberías alejarte mucho de la conducta esperada. Al menos deberías:</p> + +<ul> + <li>Subrayar los enlaces, pero no otros elementos. Si no quieres hacerlo, al menos destacarlos de alguna otra forma.</li> + <li>Hacer que reaccionen de alguna manera cuando se les pasa el cursor por encima, y de una manera algo diferente cuando se activan.</li> +</ul> + +<p>Los estilos por defecto se pueden desactivar/cambiar usando las propiedades CSS siguientes:</p> + +<ul> + <li>{{cssxref("color")}} para el color del texto.</li> + <li>{{cssxref("cursor")}} para el estilo del cursor (no debes deshabilitar esta opción a menos que tengas una muy buena razón para hacerlo).</li> + <li>{{cssxref("outline")}} para el contorno del texto (un contorno es similar a un borde, la única diferencia es que el borde ocupa un espacio en la caja y el contorno solo se solapa sobre el fondo). El contorno es una ayuda de accesibilidad útil, así que piénsatelo bien antes de desactivar esta opción; al menos deberías plantear dos estilos para los estados de pasar el puntero por encima y de tener el foco.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: No estás limitado a las propiedades anteriores para diseñar tus enlaces; tienes libertad para usar cualquier propiedad que te guste. ¡Solo trata de que no resulte descabellado!</p> +</div> + +<h3 id="Dar_formato_a_algunos_enlaces">Dar formato a algunos enlaces</h3> + +<p>Ahora que hemos visto los estados predeterminados, veamos un conjunto típico de estilos de enlace.</p> + +<p>Para empezar, escribiremos nuestro conjunto de reglas vacío:</p> + +<pre class="brush: css notranslate">a { + +} + + +a:link { + +} + +a:visited { + +} + +a:focus { + +} + +a:hover { + +} + +a:active { + +}</pre> + +<p>Este orden es importante porque los estilos de enlace se construyen sobre los anteriores. Por ejemplo, los estilos de la primera regla se aplicarán a todas las reglas siguientes, y cuando activas un enlace también pasas con el cursor por encima. Si los pones en un orden incorrecto, no funcionarán adecuadamente. Para recordar este orden, puedes intentar utilizar una fórmula nemotécnica como <strong>L</strong>o<strong>V</strong>e <strong>F</strong>ears <strong>HA</strong>te.</p> + +<p>Ahora vamos a añadir algo más de información para darles formato:</p> + +<pre class="brush: css notranslate">body { + width: 300px; + margin: 0 auto; + font-size: 1.2rem; + font-family: sans-serif; +} + +p { + line-height: 1.4; +} + +a { + outline: none; + text-decoration: none; + padding: 2px 1px 0; +} + +a:link { + color: #265301; +} + +a:visited { + color: #437A16; +} + +a:focus { + border-bottom: 1px solid; + background: #BAE498; +} + +a:hover { + border-bottom: 1px solid; + background: #CDFEAA; +} + +a:active { + background: #265301; + color: #CDFEAA; +}</pre> + +<p>También proporcionaremos algún ejemplo de HTML al que aplicar CSS:</p> + +<pre class="brush: html notranslate"><p>Dispones de varios navegadores, como <a href="#">Mozilla +Firefox</a>, <a href="#">Google Chrome</a> y +<a href="#">Microsoft Edge</a>.</p></pre> + +<p>Poner los dos juntos nos da este resultado:</p> + +<p>{{ EmbedLiveSample('Dar_formato_a_algunos_enlaces', '100%', 150) }}</p> + +<p>¿Qué hemos hecho aquí? Sin duda tiene un aspecto diferente al estilo predeterminado, pero todavía ofrece una experiencia lo suficientemente familiar como para que los usuarios sepan de qué se trata:</p> + +<ul> + <li>Las dos primeras reglas no presentan gran interés en esta explicación.</li> + <li>La tercera regla usa el selector <code>a</code> para eliminar el subrayado de texto predeterminado y el contorno en el estado de foco (que de todos modos varía dependiendo del navegador), y añade una pequeña cantidad de área de relleno a cada enlace (todo esto se aclarará más adelante).</li> + <li>A continuación, utilizamos los selectores <code>a:link</code> y <code>a:visited</code> para establecer un par de variaciones de color en los enlaces no visitados y visitados, para que se distingan.</li> + <li>Las dos reglas siguientes usan <code>a:focus</code> y <code>a:hover</code> para establecer colores de fondo diferentes para los enlaces con el foco y los enlaces activados con el paso del cursor, y además un subrayado para que el enlace destaque aún más. Aquí destacamos dos aspectos: + <ul> + <li>El subrayado se ha creado usando {{cssxref("border-bottom")}} y no {{cssxref("text-decoration")}}, y es que algunas personas lo prefieren porque el primero tiene mejores opciones en cuanto a estilo, y se dibuja un poco más abajo, por lo que no pisa los trazos descendentes de la palabra que se subraya (por ejemplo, los trazos de la g o la y).</li> + <li>El valor {{cssxref ("border-bottom")}} se ha establecido en <code>1px solid</code> sin especificar ningún color. Así, el borde adopta el mismo color que el texto del elemento, lo que es útil en casos en los que el texto es de un color diferente en cada caso.</li> + </ul> + </li> + <li>Finalmente, <code>a:active</code> se usa para dar a los enlaces un esquema de color inverso mientras se activan, ¡para dejar claro que algo importante sucede!</li> +</ul> + +<h3 id="Aprendizaje_activo_proporciona_estilo_a_tus_enlaces">Aprendizaje activo: proporciona estilo a tus enlaces</h3> + +<p>En esta sesión de aprendizaje activo, queremos que tomes nuestro conjunto de reglas vacías y añadas tus propias declaraciones para lograr unos enlaces geniales. Da rienda suelta a tu imaginación. Estamos seguros de que puedes crear algo genial y tan funcional como nuestro ejemplo anterior.</p> + +<p>Si te equivocas, puedes volver a empezar pulsando el botón <em>Reinicio</em>. Si te quedas encallado, pulsa el botón <em>Mostrar la solución</em> para recuperar el ejemplo anterior.</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><div class="body-wrapper" style="font-family: 'Open Sans Light',Helvetica,Arial,sans-serif;"> + <h2>Entrada de HTML</h2> + <textarea id="code" class="html-input" style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;"><p> Hay varios navegadores disponibles, tales como <a href="#">Mozilla + Firefox</a>, <a href="#">Google Chrome</a> y +<a href="#">Microsoft Edge</a>.</p></textarea> + + <h2>Entrada CSS</h2> + <textarea id="code" class="css-input" style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;">a { + +} + +a:link { + +} + +a:visited { + +} + +a:focus { + +} + +a:hover { + +} + +a:active { + +}</textarea> + + <h2>Salida</h2> + <div class="output" style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;"></div> + <div class="controls"> + <input id="reset" type="button" value="Reinicio" style="margin: 10px 10px 0 0;"> + <input id="solution" type="button" value="Mostrar la solución" style="margin: 10px 0 0 10px;"> + </div> +</div> +</pre> + +<pre class="brush: js notranslate">var htmlInput = document.querySelector(".html-input"); +var cssInput = document.querySelector(".css-input"); +var reset = document.getElementById("reset"); +var htmlCode = htmlInput.value; +var cssCode = cssInput.value; +var output = document.querySelector(".output"); +var solution = document.getElementById("solution"); + +var styleElem = document.createElement('style'); +var headElem = document.querySelector('head'); +headElem.appendChild(styleElem); + +function drawOutput() { + output.innerHTML = htmlInput.value; + styleElem.textContent = cssInput.value; +} + +reset.addEventListener("click", function() { + htmlInput.value = htmlCode; + cssInput.value = cssCode; + drawOutput(); +}); + +solution.addEventListener("click", function() { + htmlInput.value = htmlCode; + cssInput.value = 'p {\n font-size: 1.2rem;\n font-family: sans-serif;\n line-height: 1.4;\n}\n\na {\n outline: none;\n text-decoration: none;\n padding: 2px 1px 0;\n}\n\na:link {\n color: #265301;\n}\n\na:visited {\n color: #437A16;\n}\n\na:focus {\n border-bottom: 1px solid;\n background: #BAE498;\n}\n\na:hover {\n border-bottom: 1px solid;\n background: #CDFEAA;\n}\n\na:active {\n background: #265301;\n color: #CDFEAA;\n}'; + drawOutput(); +}); + +htmlInput.addEventListener("input", drawOutput); +cssInput.addEventListener("input", drawOutput); +window.addEventListener("load", drawOutput); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 800) }}</p> + +<h2 id="Incluir_iconos_en_los_enlaces">Incluir iconos en los enlaces</h2> + +<p>Una práctica común es incluir iconos en los enlaces para proporcionar más de un indicador en cuanto a qué tipo de contenido apunta. Echemos un vistazo a un ejemplo muy simple que añade un icono a enlaces externos (enlaces que conducen a otros sitios web). Este icono suele parecerse a una pequeña flecha que sale de un cuadro; para este ejemplo, usaremos <a href="https://icons8.com/web-app/741/external-link">este fantástico ejemplo de icons8.com</a>.</p> + +<p>Echemos un vistazo a algunos elementos HTML y CSS que nos van a proporcionar el efecto que queremos. En primer lugar, algunos elementos HTML sencillos para dar estilo:</p> + +<pre class="brush: html notranslate"><p>Para obtener más información sobre el tiempo, visite nuestra <a href="http://#">página del tiempo</a>, +mire la <a href="http://#">Wikipedia</a>, o cheque +<a href="http://#">Extreme Science</a>.</p></pre> + +<p>A continuación, el CSS:</p> + +<pre class="brush: css notranslate">body { + width: 300px; + margin: 0 auto; + font-family: sans-serif; +} + +p { + line-height: 1.4; +} + +a { + outline: none; + text-decoration: none; + padding: 2px 1px 0; +} + +a:link { + color: blue; +} + +a:visited { + color: purple; +} + +a:focus, a:hover { + border-bottom: 1px solid; +} + +a:active { + color: red; +} + +a[href*="http"] { + background: url('https://mdn.mozillademos.org/files/12982/external-link-52.png') no-repeat 100% 0; + background-size: 16px 16px; + padding-right: 19px; +}</pre> + +<p>{{ EmbedLiveSample('Incluir_iconos_en_los_enlaces', '100%', 150) }}</p> + +<p>¿Qué pasa aquí? Omitiremos la mayor parte del CSS, ya que es la misma información que has visto antes. Sin embargo, la última regla es interesante: insertamos una imagen de fondo personalizada en enlaces externos de una manera similar a como manejamos <a href="/es/docs/Learn/CSS/Styling_text/Styling_lists#Uso_de_una_imagen_personalizada_como_vi%C3%B1eta">viñetas personalizadas en los elementos de lista</a> en el último artículo. Esta vez, sin embargo, utilizamos la propiedad abreviada {{cssxref("background")}} en lugar de las propiedades individuales. Establecemos la ruta a la imagen que queremos insertar, especificamos el valor <code>no-repeat</code> para que solo se inserte una copia, y luego especificamos la posición como al 100% a la derecha del contenido de texto y a 0 píxeles del extremo superior.</p> + +<p>También usamos {{cssxref("background-size")}} para especificar el tamaño de la imagen de fondo (es útil tener un icono más grande y luego cambiar su tamaño de esta manera, según sea necesario para fines de diseño web adaptativo). Sin embargo, esto solo funciona con Internet Explorer 9 y versiones posteriores, por lo que si trabajas con navegadores antiguos, tendrás que cambiar el tamaño de la imagen e insertarla tal como es.</p> + +<p>Finalmente, establecemos un área de relleno a la derecha ({{cssxref ("padding-right")}}) para los enlaces, para crear un espacio en que aparezca la imagen de fondo, de modo que no se superponga con el texto.</p> + +<p>Un último apunte: ¿cómo seleccionamos solo los enlaces externos? Bueno, si escribes tus enlaces <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/Creating_hyperlinks">HTML</a> de forma adecuada, solo deberías usar URL absolutos para los enlaces externos. Para enlazar con otras partes del mismo sitio web, resulta más eficiente usar enlaces relativos. Por lo tanto, el texto «http» solo debe aparecer en los enlaces externos y es posible seleccionarlos con un <a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS#Selectores_de_atributo">selector de atributos</a>: <code>a[href*="http"]</code> selecciona los elementos {{HTMLElement ( "a")}}, pero solo si tienen un atributo {{htmlattrxref("href","a")}} con un valor que contiene «http» en algún lugar de su contenido textual.</p> + +<p>Eso es todo. Vuelve a la sección de aprendizaje activo anterior ¡y prueba esta nueva técnica!</p> + +<div class="note"> +<p><strong>Nota</strong>: No te preocupes si aún no estás familiarizado con los <a href="/es/docs/Learn/CSS/Building_blocks">fondos</a> y el <a href="/en-US/docs/Web/Apps/Progressive/Responsive/responsive_design_building_blocks">diseño web adaptativo</a>, lo explicaremos en otros artículos.</p> +</div> + +<h2 id="Dar_aspecto_de_botón_a_un_enlace">Dar aspecto de botón a un enlace</h2> + +<p>Las herramientas que has explorado hasta ahora en este artículo también se pueden usar de otras maneras. Por ejemplo, los estados como <code>hover</code> se pueden usar para diseñar muchos elementos diferentes, no solo enlaces. Es posible que desees diseñar un estado que señale el paso del cursor por encima de párrafos, elementos de lista u otras cosas.</p> + +<p>Además, suele ser bastante común dar a los enlaces un aspecto y un comportamiento de botón en ciertas circunstancias: el menú de navegación de un sitio web generalmente está marcado como una lista que contiene enlaces, y es posible aplicarle estilo fácilmente para que se parezca a un conjunto de botones de control o pestañas que proporcionan al usuario acceso a otras partes del sitio web. Vamos a ver cómo.</p> + +<p>En primer lugar, un poco de HTML:</p> + +<pre class="brush: html notranslate"><ul> + <li><a href="#">Inicio</a></li> <li><a href="#">Pizza</a></li> <li><a href = "#">Música</a> </li> <li><a href="#">Wombats</a></li> <li><a href="#">Finlandia</a></li> +</ul></pre> + +<p>Y ahora nuestro CSS:</p> + +<pre class="brush: css notranslate">body,html { + margin: 0; + font-family: sans-serif; +} + +ul { + padding: 0; + width: 100%; +} + +li { + display: inline; +} + +a { + outline: none; + text-decoration: none; + display: inline-block; + width: 19.5%; + margin-right: 0.625%; + text-align: center; + line-height: 3; + color: black; +} + +li:last-child a { + margin-right: 0; +} + +a:link, a:visited, a:focus { + background: yellow; +} + +a:hover { + background: orange; +} + +a:active { + background: red; + color: white; +}</pre> + +<p>Esto nos da el resultado siguiente:</p> + +<p>{{ EmbedLiveSample('Dar_aspecto_de_botón_a_un_enlace', '100%', 100) }}</p> + +<p>Vamos a explicar qué pasa aquí, y nos vamos a centrar en los aspectos más interesantes:</p> + +<ul> + <li>Nuestra segunda regla elimina el área de relleno ({{cssxref ("padding")}}) predeterminada del elemento {{htmlelement ("ul")}} y establece un ancho para abarcar el 100% del contenedor externo (el {{htmlelement ("body")}}, en este caso).</li> + <li>Los elementos {{htmlelement ("li")}} por defecto suelen ser elementos de bloque (repasa los <a href="/es/docs/Learn/CSS/Building_blocks/El_modelo_de_caja">tipos de cajas CSS</a>), lo que significa que ocupan sus propias líneas. En este caso, creamos una lista de enlaces horizontal, para lo que en la tercera regla establecemos la propiedad {{cssxref ("display")}} en el valor <code>inline</code>, que ubica todos los elementos de la lista sobre la misma línea porque ahora se comportan como elementos de línea.</li> + <li>La cuarta regla (que da formato al elemento {{htmlelement("a")}}) es la más complicada. Vamos a verla paso a paso: + <ul> + <li>Como en los ejemplos anteriores, comenzamos por desactivar las propiedades predeterminadas {{cssxref ("text-decoration")}} y {{cssxref ("outline")}}, ya que no queremos que estropeen nuestro aspecto.</li> + <li>A continuación, configuramos la propiedad {{cssxref ("display")}} en el valor <code>inline-block</code>: los elementos {{htmlelement ("a")}} se muestran en línea de forma predeterminada y, aunque no queremos que ocupe más de una línea, como haría un valor de <code>block</code>, queremos poderlos dimensionar: <code>inline-block</code> nos permite hacerlo.</li> + <li>Ahora nos centramos en el tamaño. Queremos llenar todo el ancho del elemento de lista {{htmlelement ("ul")}} y dejar un pequeño margen entre cada botón (pero ningún hueco en el borde derecho), y queremos los 5 botones del mismo tamaño. Para hacer esto, establecemos el atributo {{cssxref ("width")}} en 19,5%, y el atributo {{cssxref ("margin-right")}} en 0,625%. Observa que el ancho completo suma 100,625%, lo que haría caer el último botón <code><ul></code> a la siguiente línea por desbordamiento. Sin embargo, lo restituimos al 100% con la siguiente regla, que selecciona solo el último elemento <code><a></code> de la lista y elimina de él el margen. ¡Hecho!</li> + <li>Las tres últimas declaraciones son bastante sencillas y tienen principalmente finalidades estéticas. Centramos el texto dentro de cada enlace, establecemos {{cssxref ("line-height")}} en 3 para dar algo de altura a los botones (lo que también presenta la ventaja de centrar verticalmente el texto), y establecemos el color del texto a negro.</li> + </ul> + </li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Es posible que hayas observado que en el HTML se han colocado todos los elementos de lista en una misma línea; esto es porque los espacios/saltos de línea que se colocan entre elementos de bloque crean espacios en la página, igual como lo hacen los espacios entre las palabras, y estos espacios romperían nuestro diseño de menú de navegación horizontal. Así que hemos eliminado esos espacios. Puede encontrar más información sobre este problema (y sus soluciones) en <a href="https://css-tricks.com/fighting-the-space-between-inline-block-elements/">Combatir los espacios entre elementos de bloque colocados en línea</a>.</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p>Esperamos que este artículo te haya proporcionado todo lo que necesitas saber acerca de los enlaces... ¡por ahora! En el artículo final de nuestro módulo de aplicar estilo al texto detallaremos cómo usar tipos de letra personalizados para sitios web (o tipos de letra para web, como se les conoce comúnmente).</p> + +<p>{{PreviousMenuNext("Learn/CSS/Styling_text/Styling_lists", "Learn/CSS/Styling_text/Web_fonts", "Learn/CSS/Styling_text")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Fundamentals">Nociones de aplicación de estilo con CSS a textos y tipos de letra</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_lists">Aplicar estilo a listas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_links">Aplicar estilo a enlaces</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Tipos de letra para web</a></li> + <li><a href="/en-US/Learn/CSS/Styling_text/Typesetting_a_homepage">Composición tipográfica de una página de inicio de una escuela comunitaria</a></li> +</ul> diff --git a/files/es/learn/css/styling_text/styling_lists/index.html b/files/es/learn/css/styling_text/styling_lists/index.html new file mode 100644 index 0000000000..eeb395313b --- /dev/null +++ b/files/es/learn/css/styling_text/styling_lists/index.html @@ -0,0 +1,392 @@ +--- +title: Aplicación de estilo a listas +slug: Learn/CSS/Styling_text/Styling_lists +translation_of: Learn/CSS/Styling_text/Styling_lists +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/CSS/Styling_text/Fundamentals", "Learn/CSS/Styling_text/Styling_links", "Learn/CSS/Styling_text")}}</div> + +<p class="summary">Las <a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Lists">listas</a> se comportan como cualquier otro texto en su mayor parte, pero hay algunas propiedades CSS específicas de las listas que debes conocer y algunas prácticas recomendadas a tener en cuenta. Este artículo te lo explica.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, conocimientos básicos de HTML (estudio <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">introducción a HTML</a>), nociones de cómo trabaja con CSS (estudio <a href="/es/docs/Learn/CSS/First_steps">introducción a CSS</a>), <a href="/es/docs/Learn/CSS/Styling_text/Fundamentals">Conocimientos básicos de CSS para texto y tipos de letra</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarse con las buenas prácticas y propiedades relacionadas con la aplicación de estilo a listas.</td> + </tr> + </tbody> +</table> + +<h2 id="Un_ejemplo_sencillo_de_lista">Un ejemplo sencillo de lista</h2> + +<p>Para empezar, veamos un ejemplo sencillo de una lista. A lo largo de este artículo veremos listas no ordenadas, listas ordenadas y listas de descripciones; todas tienen características de estilo similares, algunas que son particulares del tipo de lista. El ejemplo sin ningún estilo aplicado está <a href="http://mdn.github.io/learning-area/css/styling-text/styling-lists/unstyled-list.html">disponible en Github</a> (consulta también el <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/styling-lists/unstyled-list.html">código fuente</a>.)</p> + +<p>El HTML para nuestro ejemplo de lista se ve así:</p> + +<pre class="brush: html notranslate"><h2>Shopping (unordered) list</h2> + +<p>Paragraph for reference, paragraph for reference, paragraph for reference, +paragraph for reference, paragraph for reference, paragraph for reference.</p> + +<ul> + <li>Humous</li> + <li>Pitta</li> + <li>Green salad</li> + <li>Halloumi</li> +</ul> + +<h2>Recipe (ordered) list</h2> + +<p>Paragraph for reference, paragraph for reference, paragraph for reference, +paragraph for reference, paragraph for reference, paragraph for reference.</p> + +<ol> + <li>Toast pitta, leave to cool, then slice down the edge.</li> + <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li> + <li>Wash and chop the salad.</li> + <li>Fill pitta with salad, humous, and fried halloumi.</li> +</ol> + +<h2>Ingredient description list</h2> + +<p>Paragraph for reference, paragraph for reference, paragraph for reference, +paragraph for reference, paragraph for reference, paragraph for reference.</p> + +<dl> + <dt>Humous</dt> + <dd>A thick dip/sauce generally made from chick peas blended with tahini, lemon juice, salt, garlic, and other ingredients.</dd> + <dt>Pitta</dt> + <dd>A soft, slightly leavened flatbread.</dd> + <dt>Halloumi</dt> + <dd>A semi-hard, unripened, brined cheese with a higher-than-usual melting point, usually made from goat/sheep milk.</dd> + <dt>Green salad</dt> + <dd>That green healthy stuff that many of us just use to garnish kebabs.</dd> +</dl></pre> + +<p>Si accedes al ejemplo en vivo e investigas los elementos de la lista usando las <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">herramientas de desarrollador del navegador</a>, observarás un par de valores de estilo predeterminados:</p> + +<ul> + <li>Los elementos {{htmlelement("ul")}} y {{htmlelement("ol")}} tienen un {{cssxref("margin")}} superior e inferior de <code>16px</code> (<code>1em</code>) y un {{cssxref("padding-left")}} de <code>40px</code> (<code>2.5em</code>.)</li> + <li>Los elementos de lista {{htmlelement("li")}} no tienen valores de espacio predeterminados.</li> + <li>El elemento {{htmlelement("dl")}} tiene un {{cssxref("margin")}} superior e inferior de <code>16px</code> (<code>1em</code>), pero no tiene ningún {{cssxref("padding")}} establecido.</li> + <li>Los elementos {{htmlelement("dd")}} tienen un {{cssxref("margin-left")}} de <code>40px</code> (<code>2.5em</code>).</li> + <li>Los elementos de referencia {{htmlelement("p")}} que hemos incluido tienen un {{cssxref("margin")}} superior e inferior de <code>16px</code> (<code>1em</code>), al igual que los diferentes tipos de lista.</li> +</ul> + +<h2 id="Manejar_el_espaciado_de_la_lista">Manejar el espaciado de la lista</h2> + +<p>Al diseñar listas, es necesario ajustar el diseño para que mantengan los mismos espaciados verticales (a veces denominados ritmos verticales) que el resto de elementos circundantes, como párrafos e imágenes; y el mismo espaciado horizontal entre uno y otro (en Github puedes ver el <a href="http://mdn.github.io/learning-area/css/styling-text/styling-lists/">ejemplo de diseño terminado</a>, y también <a href="https://github.com/mdn/learning-area/blob/master/css/styling-text/styling-lists/index.html">encontrar el código fuente</a>.)</p> + +<p>El CSS que se utiliza para aplicar estilo al texto y al espaciado de texto es el siguiente:</p> + +<pre class="brush: css notranslate">/* Estilos generales */ + +html { + font-family: Helvetica, Arial, sans-serif; + font-size: 10px; +} + +h2 { + font-size: 2rem; +} + +ul,ol,dl,p { + font-size: 1.5rem; +} + +li, p { + line-height: 1.5; +} + +/* Estilos para las listas de descripciones */ + + +dd, dt { + line-height: 1.5; +} + +dt { + font-weight: bold; +} + +dd { + margin-bottom: 1.5rem; +}</pre> + +<ul> + <li>La primera regla establece un tipo de letra para todo el sitio y un tamaño de letra base de 10px. Estos valores se heredan para toda la página.</li> + <li>Las reglas 2 y 3 establecen tamaños de letra relativos para los títulos, diferentes tipos de listas (que heredan los hijos de los elementos de listas), y párrafos. Esto significa que todos los párrafos y todas las listas tendrán el mismo tamaño de letra y el mismo espaciado superior e inferior, lo que ayudará a mantener el ritmo vertical constante.</li> + <li>La regla 4 establece el mismo interlineado ({{cssxref("line-height")}}) en los párrafos y los elementos de las listas, de modo que todos los párrafos y todos los elementos individuales de las listas tendrán el mismo espaciado entre las líneas. Esto también ayudará a mantener el ritmo vertical consistente.</li> + <li>Las reglas 5 y 6 se aplican a las listas de descripciones; establecemos la misma altura de interlineado (<code>line-height</code>) en los términos y las descripciones de la lista de descripciones, así como hicimos con los párrafos y los elementos de la lista. De nuevo, ¡la coherencia es buena! También establecemos que los términos de las descripciones tengan un estilo de negrita, para que destaquen visualmente.<span id="cke_bm_126E" style="display: none;"> </span></li> +</ul> + +<h2 id="Estilos_específicos_de_las_listas">Estilos específicos de las listas</h2> + +<p>Ahora que hemos analizado el espaciado general de las listas, exploremos algunas propiedades específicas de las listas. Para empezar, debes conocer tres propiedades que pueden establecerse en los elementos {{htmlelement("ul")}} o {{htmlelement("ol")}}:</p> + +<ul> + <li>{{cssxref("list-style-type")}}: Establece el tipo de viñetas para la lista, por ejemplo, viñetas cuadradas o circulares para una lista no ordenada; números, letras, o números romanos para una lista ordenada.</li> + <li>{{cssxref("list-style-position")}}: Establece si las viñetas aparecen dentro de los elementos de la lista o fuera de ellos, antes del inicio de cada elemento.</li> + <li>{{cssxref("list-style-image")}}: Te permite usar una imagen personalizada para la viñeta, en lugar de un simple cuadrado o círculo.</li> +</ul> + +<h3 id="El_estilo_de_la_viñeta">El estilo de la viñeta</h3> + +<p>Como ya sabes, la propiedad {{cssxref("list-style-type")}} te permite establecer qué tipo de viñeta usar. En nuestro ejemplo, hemos establecido que se usen números romanos en mayúsculas para la lista ordenada, con:</p> + +<pre class="brush: css notranslate">ol { + list-style-type: upper-roman; +}</pre> + +<p>Esto nos da el aspecto siguiente:</p> + +<p><img alt="Una lista ordenada con las viñetas establecidas para aparecer fuera del texto del elemento de lista." src="https://mdn.mozillademos.org/files/12962/outer-bullets.png" style="border-style: solid; border-width: 1px; display: block; height: 119px; margin: 0px auto; width: 376px;"></p> + +<p>Puedes encontrar muchas más opciones si echas un vistazo a la página de referencia de {{cssxref("list-style-type")}}.</p> + +<h3 id="La_posición_de_la_viñeta">La posición de la viñeta</h3> + +<p>La propiedad {{cssxref("list-style-position")}} establece si las viñetas aparecen dentro de los elementos de la lista, o fuera de ellos antes del inicio de cada elemento. El valor por defecto es <code>outside</code>, que provoca que las viñetas se sitúen fuera de los elementos de lista, como se observa arriba.</p> + +<p>Si estableces el valor en <code>inside</code>, las viñetas se ubican dentro de las líneas:</p> + +<pre class="brush: css notranslate">ol { + list-style-type: upper-roman; + list-style-position: inside; +}</pre> + +<p><img alt="an ordered list with the bullet points set to appear inside the list item text." src="https://mdn.mozillademos.org/files/12958/inner-bullets.png" style="border-style: solid; border-width: 1px; display: block; height: 123px; margin: 0px auto; width: 370px;"></p> + +<h3 id="Uso_de_una_imagen_personalizada_como_viñeta">Uso de una imagen personalizada como viñeta</h3> + +<p>La propiedad {{cssxref("list-style-image")}} te permite usar una imagen personalizada para tu viñeta. La sintaxis es muy simple:</p> + +<pre class="brush: css notranslate">ul { + list-style-image: url(star.svg); +}</pre> + +<p>Sin embargo, esta propiedad es un poco limitada por lo que respecta al control de la posición, el tamaño, etc., de las viñetas. Es más conveniente usar la familia de propiedades {{cssxref("background")}}, de la cual aprenderás mucho más en el módulo <a href="/es/docs/Learn/CSS/Building_blocks">Aplicar diseño a las cajas</a>.</p> + +<p>En nuestro ejemplo terminado, hemos aplicado estilo a la lista no ordenada de este modo (encima de lo que ya has visto arriba):</p> + +<pre class="brush: css notranslate">ul { + padding-left: 2rem; + list-style-type: none; +} + +ul li { + padding-left: 2rem; + background-image: url(star.svg); + background-position: 0 0; + background-size: 1.6rem 1.6rem; + background-repeat: no-repeat; +}</pre> + +<p>Aquí hemos hecho lo siguiente:</p> + +<ul> + <li> + <p dir="ltr" id="tw-target-text">Reducir el valor de la propiedad {{cssxref("padding-left")}} del elemento {{htmlelement ("ul")}} desde su valor predeterminado de 40 px hasta 20 px. A continuación, establecer<br> + la misma cantidad para los elementos de la lista. De este modo, todos los elementos de la lista siguen alineados con los elementos de la lista ordenada y las descripciones, pero los elementos de lista tienen algo de relleno (<code>padding</code>) para poder insertar las imágenes de fondo. Si no hiciéramos esto, las imágenes de fondo se solaparían con el texto de los elementos de la lista y quedaría un aspecto desordenado.</p> + </li> + <li> + <p dir="ltr" id="tw-target-text">Establecer la propiedad {{cssxref("list-style-type")}} en <code>none</code>, para que no aparezca la viñeta predeterminada. En lugar de ello, vamos a utilizar las propiedades {{cssxref("background")}} para manejar las viñetas.</p> + </li> + <li>Insertar una viñeta en cada elemento de la lista sin ordenar. Las propiedades relevantes son las siguientes: + <ul> + <li>{{cssxref("background-image")}}: Proporciona la ruta que apunta al archivo de imagen que quieres usar como viñeta.</li> + <li>{{cssxref("background-position")}}: Define en qué lugar del elemento seleccionado va a aparecer la imagen; en este caso le decimos <code>0 0</code>, que significa que la viñeta va a aparecer en el extremo superior izquierdo de cada elemento de lista.</li> + <li>{{cssxref("background-size")}}: Establece el tamaño de la imagen de fondo. En teoría queremos que las viñetas sean del mismo tamaño que los elementos de lista (o solo un poco menores o mayores). Utilizamos un tamaño de <code>1.6rem</code> (<code>16px</code>), que encaja muy bien con el área de relleno de <code>20px</code> que hemos elegido para que quepa la viñeta; 16 px más 4 px de espacio entre la viñeta y el texto del elemento de lista funciona bien.</li> + <li>{{cssxref("background-repeat")}}: Por defecto, las imágenes de fondo se repiten hasta rellenar todo el espacio de fondo disponible. En este caso solo queremos una copia de la imagen, de modo que establecemos el valor de esta propiedad en <code>no-repeat</code>.</li> + </ul> + </li> +</ul> + +<p>Esto nos da el resultado siguiente:</p> + +<p><img alt="an unordered list with the bullet points set as little star images" src="https://mdn.mozillademos.org/files/12956/image-bullets.png" style="border-style: solid; border-width: 1px; display: block; height: 106px; margin: 0px auto; width: 124px;"></p> + +<h3 id="Propiedad_abreviada_list-style">Propiedad abreviada list-style</h3> + +<p>Es posible configurar las tres propiedades anteriores con una sola propiedad abreviada, {{cssxref("list-style")}}. Por ejemplo, observa el CSS siguiente:</p> + +<pre class="brush: css notranslate">ul { + list-style-type: square; + list-style-image: url(example.png); + list-style-position: inside; +}</pre> + +<p>Podría reemplazarse por esto:</p> + +<pre class="notranslate">ul { + list-style: square url(example.png) inside; +}</pre> + +<p>Los valores pueden escribirse en cualquier orden, y puedes usar uno, dos o los tres (los valores por defecto que se utilizan para las propiedades que no están incluidas son <code>disc</code>, <code>none</code> y <code>outside</code>). Si se especifican tanto <code>type</code> como <code>image</code>, el tipo se usa como una segunda opción en el caso de que la imagen no sea posible cargar la imagen por cualquier motivo.</p> + +<h2 id="Control_de_numeración_de_las_listas">Control de numeración de las listas</h2> + +<p>A veces puedes querer numerar las listas de manera diferente, por ejemplo, que empiece con un número que no sea el 1, o que cuente hacia atrás, o que cuente a saltos de más de una unidad. HTML y CSS tienen algunas herramientas para ayudarte con esto.</p> + +<h3 id="start">start</h3> + +<p>El atributo {{htmlattrxref("start","ol")}} te permite empezar la numeración de la lista en un número diferente de 1. Observa el ejemplo siguiente:</p> + +<pre class="brush: html notranslate"><ol start="4"> + <li>Toast pitta, leave to cool, then slice down the edge.</li> + <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li> + <li>Wash and chop the salad.</li> + <li>Fill pitta with salad, humous, and fried halloumi.</li> +</ol></pre> + +<p>Este código da el resultado siguiente:</p> + +<p>{{ EmbedLiveSample('start', '100%', 150) }}</p> + +<h3 id="reversed">reversed</h3> + +<p>El atributo {{htmlattrxref("reversed","ol")}} empieza la lista contando hacia atrás, en lugar de hacia adelante. Observa el ejemplo siguiente:</p> + +<pre class="brush: html notranslate"><ol start="4" reversed> + <li>Toast pitta, leave to cool, then slice down the edge.</li> + <li>Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li> + <li>Wash and chop the salad.</li> + <li>Fill pitta with salad, humous, and fried halloumi.</li> +</ol></pre> + +<p>Da el resultado siguiente:</p> + +<p>{{ EmbedLiveSample('reversed', '100%', 150) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Si en una lista inversa hay más elementos de lista que el valor que se ha establecido para el atributo <code>start</code>, la numeración continuará hasta cero y luego con valores negativos.</p> +</div> + +<h3 id="value">value</h3> + +<p>El atributo {{htmlattrxref("value","ol")}} te permite establecer para tus elementos de lista unos valores numéricos específicos. Observa el ejemplo siguiente:</p> + +<pre class="brush: html notranslate"><ol> + <li value="2">Toast pitta, leave to cool, then slice down the edge.</li> + <li value="4">Fry the halloumi in a shallow, non-stick pan, until browned on both sides.</li> + <li value="6">Wash and chop the salad.</li> + <li value="8">Fill pitta with salad, humous, and fried halloumi.</li> +</ol></pre> + +<p>Da el resultado siguiente:</p> + +<p>{{ EmbedLiveSample('value', '100%', 150) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Incluso si utilizas una propiedad {{cssxref("list-style-type")}} sin números, vas a tener que usar los valores numéricos equivalentes para el atributo <code>value</code>.</p> +</div> + +<h2 id="Aprendizaje_activo_aplicar_estilo_a_una_lista_anidada">Aprendizaje activo: aplicar estilo a una lista anidada</h2> + +<p>En esta sesión de aprendizaje activo, queremos que tomes lo que has aprendido arriba y pruebes a aplicar estilo a una lista anidada. Te hemos provisto con un HTML, y queremos que hagas lo siguiente:</p> + +<ol> + <li>Poner viñetas cuadradas en la lista no ordenada.</li> + <li>Establecer un interlineado de 1,5 con respecto al tamaño de la letra tanto para la lista ordenada como para la lista no ordenada.</li> + <li>Poner letras minúsculas en la lista ordenada.</li> + <li>Juega con el ejemplo, libremente y cuanto quieras, experimenta con los tipos de viñetas, los espacios, o cualquier otra cosa con que te encuentres.</li> +</ol> + +<p>Si te equivocas, puedes volver a empezar con el botón <em>Reinicio</em>. Si te quedas encallado, pulsa el botón <em>Mostrar la solución</em> para ver una posible solución.</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><div class="body-wrapper" style="font-family: 'Open Sans Light',Helvetica,Arial,sans-serif;"> + <h2>HTML Input</h2> + <textarea id="code" class="html-input" style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;"><ul> + <li>First, light the candle.</li> + <li>Next, open the box.</li> + <li>Finally, place the three magic items in the box, in this exact order, to complete the spell: + <ol> + <li>The book of spells</li> + <li>The shiny rod</li> + <li>The goblin statue</li> + </ol> + </li> +</ul></textarea> + + <h2>CSS Input</h2> + <textarea id="code" class="css-input" style="width: 90%;height: 10em;padding: 10px;border: 1px solid #0095dd;"></textarea> + + <h2>Output</h2> + <div class="output" style="width: 90%;height: 12em;padding: 10px;border: 1px solid #0095dd;overflow: auto;"></div> + <div class="controls"> + <input id="reset" type="button" value="Reset" style="margin: 10px 10px 0 0;"> + <input id="solution" type="button" value="Show solution" style="margin: 10px 0 0 10px;"> + </div> +</div> +</pre> + +<pre class="brush: js notranslate">var htmlInput = document.querySelector(".html-input"); +var cssInput = document.querySelector(".css-input"); +var reset = document.getElementById("reset"); +var htmlCode = htmlInput.value; +var cssCode = cssInput.value; +var output = document.querySelector(".output"); +var solution = document.getElementById("solution"); + +var styleElem = document.createElement('style'); +var headElem = document.querySelector('head'); +headElem.appendChild(styleElem); + +function drawOutput() { + output.innerHTML = htmlInput.value; + styleElem.textContent = cssInput.value; +} + +reset.addEventListener("click", function() { + htmlInput.value = htmlCode; + cssInput.value = cssCode; + drawOutput(); +}); + +solution.addEventListener("click", function() { + htmlInput.value = htmlCode; + cssInput.value = 'ul {\n list-style-type: square;\n}\n\nul li {\n line-height: 1.5;\n}\n\nol {\n list-style-type: lower-alpha\n}'; + drawOutput(); +}); + +htmlInput.addEventListener("input", drawOutput); +cssInput.addEventListener("input", drawOutput); +window.addEventListener("load", drawOutput); +</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 800) }}</p> + +<h2 id="Véase_también">Véase también</h2> + +<p>Los contadores CSS proporcionan herramientas avanzadas para la personalización de las numeraciones y la aplicación de estilo a las listas, pero son bastante complejos. Te recomendamos echarles un vistazo si quieres ampliar tus conocimientos. Consulta:</p> + +<ul> + <li>{{cssxref("@counter-style")}}</li> + <li>{{cssxref("counter-increment")}}</li> + <li>{{cssxref("counter-reset")}}</li> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>La aplicación de estilo a listas se domina con relativa facilidad una vez que conoces algunos principios básicos y propiedades específicas asociados. En el artículo siguiente vamos a continuar con las técnicas de aplicación de estilo a enlaces.</p> + +<p>{{PreviousMenuNext("Learn/CSS/Styling_text/Fundamentals", "Learn/CSS/Styling_text/Styling_links", "Learn/CSS/Styling_text")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Fundamentals">Nociones de aplicación de estilo con CSS a textos y tipos de letra</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_lists">Aplicar estilo a listas</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_links">Aplicar estilo a enlaces</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Web_fonts">Tipos de letra para web</a></li> + <li><a href="/en-US/Learn/CSS/Styling_text/Typesetting_a_homepage">Escribir una página de inicio para la comunidad escolar</a></li> +</ul> diff --git a/files/es/learn/css/sábercomo/generated_content/index.html b/files/es/learn/css/sábercomo/generated_content/index.html new file mode 100644 index 0000000000..605e87f9e2 --- /dev/null +++ b/files/es/learn/css/sábercomo/generated_content/index.html @@ -0,0 +1,178 @@ +--- +title: Usando CSS para generar contenido +slug: Learn/CSS/Sábercomo/Generated_content +tags: + - CSS + - Fundamentos + - Guía + - Principiante + - Web + - graficos +translation_of: Learn/CSS/Howto/Generated_content +--- +<p>{{ CSSTutorialTOC() }}</p> + +<p>{{ previousPage("/en-US/docs/Web/Guide/CSS/Getting_Started/Color", "Color") }}Esta es la 9ª sección del tutorial CSS Getting Started; Describe algunas formas en las que puede utilizar CSS para agregar contenido cuando se muestra un documento. Modifica su hoja de estilo para agregar contenido de texto y una imagen.</p> + +<h2 class="clearLeft" id="Informacion_Contenido">Informacion: Contenido</h2> + +<p>Una de las ventajas importantes de CSS es que le ayuda a separar el estilo de un documento de su contenido. Sin embargo, hay situaciones en las que tiene sentido especificar cierto contenido como parte de la hoja de estilo, no como parte del documento.</p> + +<p>El contenido especificado en una hoja de estilo puede consistir en texto o imágenes. Especifica el contenido de su hoja de estilos cuando el contenido está estrechamente vinculado a la estructura del documento.</p> + +<div class="tuto_details"> +<div class="tuto_type"> +<p>Más detalles</p> + +<p>Especificar contenido en una hoja de estilo puede causar complicaciones. Por ejemplo, es posible que tenga versiones de idioma diferentes de su documento que comparten una hoja de estilo. Si parte de la hoja de estilo tiene que ser traducida, significa que debe colocar las partes de la hoja de estilos en archivos separados y organizar para que se vincule con las versiones de idioma adecuado de su documento.</p> + +<p>Estas complicaciones no surgen si el contenido especificado incluye símbolos o imágenes que se aplican en todos los idiomas y culturas.</p> + +<p>El contenido especificado en una hoja de estilo no se convierte en parte del DOM.</p> +</div> +</div> + +<h3 id="Text_content" name="Text_content">Texto contenido</h3> + +<p>CSS puede insertar contenido de texto antes o después de un elemento. Para especificar esto, haga una regla y agregue {{cssxref (':: before')}} o {{cssxref (':: after')}} al selector. En la declaración, especifique la propiedad {{cssxref ('content')}} con el contenido de texto como su valor.</p> + +<div class="tuto_example"> +<div class="tuto_type">Ejemplo</div> + +<h4 id="HTML">HTML</h4> + +<pre class="brush: html">Un texto donde necesito <span class="ref">alguna cosa</span> +</pre> + +<h4 id="CSS">CSS</h4> + +<pre class="brush: css">.ref::before { + font-weight: negrita; + color: navy; + content: "Reference: "; +}</pre> + +<h4 id="Output">Output</h4> + +<p>{{ EmbedLiveSample('Text_content', 600, 30) }}</p> +</div> + +<div class="tuto_details"> +<div class="tuto_type">Mas detalles</div> + +<p>El conjunto de caracteres de una hoja de estilo es UTF-8 de forma predeterminada, pero se puede especificar en el vínculo o en la hoja de estilos o en otras formas. Para obtener más información, consulte 4. 4 Representación de hoja de estilo CSS en la especificación CSS.</p> + +<p>Los caracteres individuales también se pueden especificar mediante un mecanismo de escape que utiliza la barra invertida como el carácter de escape. Por ejemplo, \ 265B es el símbolo del ajedrez para una reina negra ♛. Para obtener más información, consulte Referencia a caracteres no representados en una codificación de caracteres y también Caracteres y caso en la Especificación CSS.</p> +</div> + +<h3 id="Imagen_contenido">Imagen contenido</h3> + +<p>Para agregar una imagen antes o después de un elemento, puede especificar la URL de un archivo de imagen en el valor de la propiedad {{cssxref ('content')}}.</p> + +<div class="tuto_example"> +<div class="tuto_type">Ejemplo</div> + +<p>Esta regla añade un espacio y un icono después de cada enlace que tiene el glosario de clases:</p> + +<pre class="brush:css">a.glossary:after {content: " " url("../images/glossary-icon.gif");} +</pre> +</div> + +<p>Para agregar una imagen como fondo de un elemento, especifique la URL de un archivo de imagen en el valor de la propiedad {{cssxref ('background')}}. Esta es una propiedad abreviada que especifica el color de fondo, la imagen, cómo se repite la imagen y algunos otros detalles.</p> + +<div class="tuto_example"> +<div class="tuto_type">Ejemplo</div> + +<p>Esta regla establece el fondo de un elemento específico, utilizando una URL para especificar un archivo de imagen.</p> + +<p>El selector especifica el id del elemento. El valor no-repeat hace que la imagen aparezca sólo una vez:</p> + +<pre class="brush:css">#sidebar-box {background: url("../images/sidebar-ground.png") no-repeat;} +</pre> +</div> + +<div class="tuto_details"> +<div class="tuto_type">Mas detalles</div> + +<p>Para obtener información sobre las propiedades individuales que afectan a los fondos y sobre otras opciones al especificar imágenes de fondo, consulte {{Cssxref ('fondo')}}, página de referencia.</p> +</div> + +<h2 id="Acción_Añadir_una_imagen_de_fondo">Acción: Añadir una imagen de fondo</h2> + +<p>Esta imagen es un cuadrado blanco con una línea azul en la parte inferior:</p> + +<table style="border: 2px solid #cccccc;"> + <tbody> + <tr> + <td><img alt="Image:Blue-rule.png" class="internal" src="https://mdn.mozillademos.org/files/160/Blue-rule.png"></td> + </tr> + </tbody> +</table> + +<ol> + <li>Descargue el archivo de imagen en el mismo directorio que su archivo CSS. (Por ejemplo, haga clic con el botón derecho del ratón para obtener un menú contextual y, a continuación, seleccione Guardar imagen como y especifique el directorio que está utilizando para este tutorial).</li> + <li>Edit your CSS file and add this rule to the body, setting a background image for the entire page.</li> + <li> + <pre class="brush:css">background: url("Blue-rule.png"); +</pre> + + <p>La repetición de valor es la predeterminada, por lo que no es necesario especificarla. La imagen se repite horizontal y verticalmente, dando una apariencia como papel de escribir forrado:</p> + + <div style="position: relative; width: 24em; height: 11em; border: 2px outset #36b; overflow: hidden;"> + <p style="margin: 0px;"><img alt="Image:Blue-rule-ground.png" class="internal" src="https://mdn.mozillademos.org/files/161/Blue-rule-ground.png"></p> + + <div style="position: absolute; top: 0px; left: 0px; border: none; margin: 0px; padding: .5em 0px 0px 1em; font: 16px 'Comic Sams MS', cursive; color: blue; background-color: transparent;"> + <div style="font-style: italic; width: 24em;"> + <p><strong style="background-color: #ddddff; color: red; font: 200% serif;">C</strong>ascading <strong style="background-color: #ddddff; color: green; font: 200% serif;">S</strong>tyle <strong style="background-color: #ddddff; color: green; font: 200% serif;">S</strong>heets</p> + </div> + + <div style="font-style: normal; padding-top: 2px; height: 8em;"> + <p><strong style="background-color: #ddddff; color: red; font: 200% serif;">C</strong>ascading <strong style="background-color: #ddddff; color: red; font: 200% serif;">S</strong>tyle <strong style="background-color: #ddddff; color: red; font: 200% serif;">S</strong>heets</p> + </div> + </div> + </div> + </li> +</ol> + +<div class="tuto_example"> +<div class="tuto_type">Reto</div> + +<p>Descarga esta imagen:</p> + +<table style="border: 2px solid #cccccc;"> + <tbody> + <tr> + <td><img alt="Image:Yellow-pin.png" class="internal" src="https://mdn.mozillademos.org/files/924/Yellow-pin.png"></td> + </tr> + </tbody> +</table> + +<p>Agrega una nueva regla a tu hoja de estilos, luego, agrega la imagen al inicio de cada linea:</p> + +<div style="position: relative; width: 24em; height: 11em; border: 2px outset #36b; overflow: hidden;"> +<p style="margin: 0px;"><img alt="Image:Blue-rule-ground.png" class="internal" src="https://mdn.mozillademos.org/files/161/Blue-rule-ground.png"></p> + +<div style="position: absolute; top: 0px; left: 0px; border: none; margin: 0px; padding: .5em 0px 0px 1em; font: 16px 'Comic Sams MS', cursive; color: blue; background-color: transparent;"> +<div style="font-style: italic; width: 24em; padding-top: 8px;"><img alt="image:Yellow-pin.png" class="internal" src="https://mdn.mozillademos.org/files/924/Yellow-pin.png"> <strong style="background-color: #ddddff; color: red; font: 200% serif;">C</strong>ascading <strong style="background-color: #ddddff; color: green; font: 200% serif;">S</strong>tyle <strong style="background-color: #ddddff; color: green; font: 200% serif;">S</strong>heets</div> + +<div style="font-style: normal; padding-top: 12px; height: 8em;"><img alt="image:Yellow-pin.png" class="internal" src="https://mdn.mozillademos.org/files/924/Yellow-pin.png"> <strong style="background-color: #ddddff; color: red; font: 200% serif;">C</strong>ascading <strong style="background-color: #ddddff; color: red; font: 200% serif;">S</strong>tyle <strong style="background-color: #ddddff; color: red; font: 200% serif;">S</strong>heets</div> +</div> +</div> + +<div class="tuto_details" id="tutochallenge"> +<div class="tuto_type">Possible solution</div> + +<p>Add this rule to your stylesheet:</p> + +<pre class="brush: css">p:before{ + content: url("yellow-pin.png"); +} +</pre> + +<p> </p> +<a class="hideAnswer" href="#challenge">Hide solution</a></div> +<a href="#tutochallenge" title="Display a possible solution for the challenge">Ver la solución a este reto.</a></div> + +<h2 id="Qué_sigue">Qué sigue?</h2> + +<p>{{ nextPage("/en-US/docs/Web/Guide/CSS/Getting_Started/Lists", "Lists") }}Una forma común en que las hojas de estilos agregan contenido es marcando los elementos en las listas. La siguiente sección describe cómo <a href="/en-US/docs/Web/Guide/CSS/Getting_Started/Lists" title="/en-US/docs/Web/Guide/CSS/Getting_Started/Lists">especificar estilos para una lista de elementos.</a></p> diff --git a/files/es/learn/css/sábercomo/index.html b/files/es/learn/css/sábercomo/index.html new file mode 100644 index 0000000000..ffff1653c0 --- /dev/null +++ b/files/es/learn/css/sábercomo/index.html @@ -0,0 +1,81 @@ +--- +title: Usa CSS para resolver problemas comunes +slug: Learn/CSS/Sábercomo +translation_of: Learn/CSS/Howto +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Los siguientes enlaces apuntan a soluciones comunes a los problemas cotidianos que necesitará resolver con CSS.</p> + +<h2 id="Casos_de_uso_común">Casos de uso común</h2> + +<div class="column-container"> +<div class="column-half"> +<h3 id="Básicos">Básicos</h3> + +<ul> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/How_CSS_works#How_to_apply_your_CSS_to_your_HTML">Cómo aplicar CSS al HTML</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Syntax#White_space">How to use whitespace in CSS</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Syntax#Comments">Cómo escribir comentarios en CSS</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Simple_selectors">Cómo seleccionar elementos mediante nombre del elemento, clase o ID</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Attribute_selectors">Cómo seleccionar elementos mediante nombre del atributo y contenido</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Pseudo-classes">Cómo usar pseudo-clases</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Pseudo-elements">Cómo usar pseudo-elementos</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Selectors#Multiple_selectors_on_one_rule">Cómo aplicar múltiples selectores a la misma regla</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Values_and_units#Colors">Cómo especificar colores en CSS</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Debugging_CSS#Inspecting_the_DOM_and_CSS">Cómo depurar CSS en el navegador</a></li> +</ul> + +<h3 id="CSS_y_texto">CSS y texto</h3> + +<ul> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Fundamentals">Cómo dar estilo al texto</a></li> + <li><a href="/en-US/docs/Learn/CSS/Styling_text/Styling_lists">Cómo personalizar una lista de elementos</a></li> + <li><a href="/en-US/Learn/CSS/Styling_text/Styling_links">Cómo dar estilo a links</a></li> + <li><a href="/en-US/Learn/CSS/Styling_text/Fundamentals#Text_drop_shadows">Cómo agregar sombras al texto</a></li> +</ul> +</div> + +<div class="column-half"> +<h3 id="Cajas_y_diseños">Cajas y diseños</h3> + +<ul> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Box_properties">Cómo redimensionar cajas CSS</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Overflow">Cómo controlar el contenido que desborda</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Background_clip">Cómo controlar la parte de una caja CSS en la que se dibuja el fondo</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Types_of_CSS_boxes">Cómo defino un elemento inline, block o inline-block?</a></li> + <li><a href="/en-US/docs/Learn/CSS/Howto/create_fancy_boxes">How to create fancy boxes</a> (also see the <a href="/en-US/docs/Learn/CSS/Styling_boxes">Styling boxes</a> module, generally).</li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Box_model#Background_clip">How to use <code>background-clip</code> to control how much of the box your background image covers</a>.</li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Box_model_recap#Changing_the_box_model_completely">How to change the box model completely using <code>box-sizing</code></a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Backgrounds">How to control backgrounds</a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Borders">How to control borders</a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Styling_tables">How to style an HTML table</a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Advanced_box_effects#Box_shadows">How to add shadows to boxes</a></li> +</ul> +</div> +</div> + +<h2 id="Uncommon_or_advanced_techniques">Uncommon or advanced techniques</h2> + +<p>Beyond the basics, CSS is allows very advanced design techniques. These articles help you tackle the hardest use cases you may face.</p> + +<h3 id="General">General</h3> + +<ul> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance#Specificity">How to calculate specificity of a CSS selector</a></li> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/Cascade_and_inheritance#Controlling_inheritance">How to control inheritance in CSS</a></li> +</ul> + +<h3 id="Advanced_effects">Advanced effects</h3> + +<ul> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Advanced_box_effects#Filters">How to use filters in CSS</a></li> + <li><a href="/en-US/Learn/CSS/Styling_boxes/Advanced_box_effects#Blend_modes">How to use blend modes in CSS</a></li> +</ul> + +<h3 id="Layout">Layout</h3> + +<ul> + <li><a href="/en-US/docs/Web/Guide/CSS/Flexible_boxes">Using CSS flexible boxes</a></li> + <li><a href="/en-US/docs/Web/Guide/CSS/Using_multi-column_layouts" title="/en-US/docs/Web/Guide/CSS/Using_multi-column_layouts">Using CSS multi-column layouts</a></li> +</ul> diff --git a/files/es/learn/desarrollo_web_front-end/index.html b/files/es/learn/desarrollo_web_front-end/index.html new file mode 100644 index 0000000000..f58a9ad486 --- /dev/null +++ b/files/es/learn/desarrollo_web_front-end/index.html @@ -0,0 +1,201 @@ +--- +title: Desarrollo web Front-end +slug: Learn/Desarrollo_web_Front-end +tags: + - Aprender + - CSS + - De lado del cliente + - Estándar Web + - Estándares web + - Front-end + - HTML + - Herramientas + - JavaScript + - Novato + - Principiante +translation_of: Learn/Front-end_web_developer +--- +<p>{{learnsidebar}}</p> + +<p>¡Bienvenido a la ruta de aprendizaje para desarrolladores de la interfaz de usuario web!</p> + +<p>Aquí se te proporciona un curso estructurado que te enseñará todo lo que necesitas saber para convertirte en un desarrollador de la interfaz de usuario web. Simplemente trabaja en cada sección, aprendiendo nuevas habilidades (o mejorando las existentes) sobre la marcha. Cada sección incluye desafíos y ejercicios para evaluar tu comprensión antes de seguir adelante.</p> + +<h2 id="Temas_tratados">Temas tratados</h2> + +<p>Los temas tratados son:</p> + +<ul> + <li>Configuración básica y conocimientos sobre cómo aprender</li> + <li>Estándares web y mejores prácticas (como accesibilidad y compatibilidad entre navegadores)</li> + <li>HTML, el lenguaje que da estructura y significado al contenido web</li> + <li>CSS, el lenguaje utilizado para aplicar estilo a las páginas web</li> + <li>JavaScript, el lenguaje programado por medio de <em>scripts</em> utilizado para crear funciones dinámicas en la web.</li> + <li>Herramientas que se utilizan para facilitar el desarrollo web moderno de lado del cliente.</li> +</ul> + +<p>Puedes trabajar en las secciones en orden, pero cada una también es autónoma. Por ejemplo, si ya conoces HTML, puedes pasar a la sección CSS.</p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>No necesitas conocimientos previos para empezar este curso. Todo lo que necesitas es una computadora que pueda ejecutar navegadores web modernos, una conexión a Internet y la voluntad de aprender.</p> + +<p>Si no estás seguro de si el desarrollo de la interfaz de usuario web es para ti, y/o deseas una breve introducción antes de comenzar un curso más largo y completo, consulta una {{web.link("/es/docs/Learn/Getting_started_with_the_web", "Introducción a la Web")}}.</p> + +<h2 id="Cómo_obtener_ayuda">Cómo obtener ayuda</h2> + +<p>Hemos tratado de hacer que el desarrollo de la interfaz de usuario web sea lo más cómodo posible, pero probablemente todavía quedes encallado porque no entiendes algo o porque algún código simplemente no funciona.</p> + +<p>No entres en pánico. Todos hemos encallado, sin importar que seamos desarrolladores web principiantes o profesionales. El artículo {{web.link("/es/docs/Learn/Learning_and_getting_help", "Aprender y obtener ayuda")}} te brinda una serie de consejos para buscar información y ayudarte a ti mismo. Si aún estás atascado, no dudes en publicar una pregunta en nuestro <a href="https://discourse.mozilla.org/c/mdn/learn/">Foro de discusión</a>.</p> + +<p>Empecemos. ¡Diviértete!</p> + +<h2 id="El_camino_del_aprendizaje">El camino del aprendizaje</h2> + +<h3 id="Primeros_pasos">Primeros pasos</h3> + +<p>Tiempo para completar: 1.5 a 2 horas</p> + +<h4 id="Prerrequisitos_2">Prerrequisitos</h4> + +<p>Nada excepto conocimientos básicos de informática.</p> + +<h4 id="¿Cómo_sabré_que_estoy_listo_para_seguir_adelante">¿Cómo sabré que estoy listo para seguir adelante?</h4> + +<p>No hay evaluaciones en esta parte del curso. Pero asegúrate de no saltarla. Es importante prepararte para trabajar en la resolución de los ejercicios más adelante en el curso.</p> + +<h4 id="Guías">Guías</h4> + +<ul> + <li>{{web.link("/es/docs/Learn/Getting_started_with_the_web/Installing_basic_software", "Instalación de software básico")}}: configuración básica de las herramientas (lectura de 15 minutos)</li> + <li>{{web.link("/es/docs/Learn/Getting_started_with_the_web/The_web_and_web_standards", "Información básica sobre la web y los estándares web")}} (lectura de 45 minutos)</li> + <li>{{web.link("/es/docs/Learn/Learning_and_getting_help", "Aprender y obtener ayuda")}} (lectura de 45 minutos)</li> +</ul> + +<h3 id="Semántica_y_estructura_con_HTML">Semántica y estructura con HTML</h3> + +<p>Tiempo para completar: 35 a 50 horas</p> + +<h4 id="Prerrequisitos_3">Prerrequisitos</h4> + +<p>Nada, excepto: conocimientos básicos de informática y un entorno de desarrollo web básico.</p> + +<h4 id="¿Cómo_sabré_que_estoy_listo_para_seguir_adelante_2">¿Cómo sabré que estoy listo para seguir adelante?</h4> + +<p>Las evaluaciones de cada módulo están diseñadas para comprobar tu conocimiento del tema. Completar las evaluaciones confirma que estás listo para pasar al siguiente módulo.</p> + +<h4 id="Módulos">Módulos</h4> + +<ul> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML", "Introducción a HTML")}} (15 a 20 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/HTML/Multimedia_and_embedding", "Multimedia e inserción")}} (15 a 20 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/HTML/Tables", "tablas HTML")}} (5 a 10 horas de lectura/ejercicios)</li> +</ul> + +<h3 id="Estilo_y_diseño_con_CSS">Estilo y diseño con CSS</h3> + +<p>Tiempo para completar: 90 a 120 horas</p> + +<h4 id="Prerrequisitos_4">Prerrequisitos</h4> + +<p>Es recomendable que tengas conocimientos básicos de HTML antes de comenzar a aprender CSS. Primero deberías estudiar {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML", "Introducción a HTML")}} por lo menos.</p> + +<h4 id="¿Cómo_sabré_que_estoy_listo_para_seguir_adelante_3">¿Cómo sabré que estoy listo para seguir adelante?</h4> + +<p>Las evaluaciones de cada módulo están diseñadas para comprobar tu conocimiento del tema. Completar las evaluaciones confirma que estás listo para pasar al siguiente módulo.</p> + +<h4 id="Módulos_2">Módulos</h4> + +<ul> + <li>{{web.link("/es/docs/Learn/CSS/First_steps", "Primeros pasos de CSS" )}} (10 a 15 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/CSS/Building_blocks", "Bloques de construcción de CSS")}} (35 a 45 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/CSS/Styling_text", "Diseño de texto")}} (15 a 20 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/CSS/CSS_layout", "Diseño CSS")}} (30 a 40 horas de lectura/ejercicios)</li> +</ul> + +<h4 id="Recursos_adicionales">Recursos adicionales</h4> + +<ul> + <li>{{web.link("/es/docs/Web/CSS/Layout_cookbook", "Libro de recetas de diseño CSS")}}</li> +</ul> + +<h3 id="Interactividad_con_JavaScript">Interactividad con JavaScript</h3> + +<p>Tiempo para completar: 135 a 185 horas</p> + +<h4 id="Prerrequisitos_5">Prerrequisitos</h4> + +<p>Es recomendable que tengas conocimientos básicos de HTML antes de comenzar a aprender JavaScript. Primero deberías estudiar {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML", "Introducción a HTML")}} por lo menos.</p> + +<h4 id="¿Cómo_sabré_que_estoy_listo_para_seguir_adelante_4">¿Cómo sabré que estoy listo para seguir adelante?</h4> + +<p>Las evaluaciones de cada módulo están diseñadas para comprobar tu conocimiento del tema. Completar las evaluaciones confirma que estás listo para pasar al siguiente módulo.</p> + +<h4 id="Módulos_3">Módulos</h4> + +<ul> + <li>{{web.link("/es/docs/Learn/JavaScript/First_steps", "Primeros pasos en JavaScript")}} (30 a 40 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Building_blocks", "Bloques de construcción de JavaScript")}} (25 a 35 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Objects", "Introducción a los objetos JavaScript")}} (25 a 35 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs", "API web del lado del cliente")}} (30 a 40 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Asynchronous", "JavaScript asincrónico")}} (25 a 35 horas de lectura/ejercicios)</li> +</ul> + +<h3 id="Formularios_web_—_Trabajar_con_datos_del_usuario">Formularios web — Trabajar con datos del usuario</h3> + +<p>Tiempo para completar: 40 a 50 horas</p> + +<h4 id="Prerrequisitos_6">Prerrequisitos</h4> + +<p>Los formularios requieren conocimientos de HTML, CSS y JavaScript. Dada la complejidad de trabajar con formularios, es un tema dedicado.</p> + +<h4 id="¿Cómo_sabré_que_estoy_listo_para_seguir_adelante_5">¿Cómo sabré que estoy listo para seguir adelante?</h4> + +<p>Las evaluaciones de cada módulo están diseñadas para comprobar tu conocimiento del tema. Completar las evaluaciones confirma que estás listo para pasar al siguiente módulo.</p> + +<h4 id="Módulos_4">Módulos</h4> + +<ul> + <li>{{web.link("/es/docs/Learn/Forms", "Formularios web")}} (40 a 50 horas)</li> +</ul> + +<h3 id="Hacer_que_la_web_funcione_para_todos">Hacer que la web funcione para todos</h3> + +<p>Tiempo para completar: 60 a 75 horas</p> + +<h4 id="Prerrequisitos_7">Prerrequisitos</h4> + +<p>Es una buena idea conocer HTML, CSS y JavaScript antes de trabajar en esta sección. Muchas de las técnicas y mejores prácticas se refieren a múltiples tecnologías.</p> + +<h4 id="¿Cómo_sabré_que_estoy_listo_para_seguir_adelante_6">¿Cómo sabré que estoy listo para seguir adelante?</h4> + +<p>Las evaluaciones de cada módulo están diseñadas para comprobar tu conocimiento del tema. Completar las evaluaciones confirma que estás listo para pasar al siguiente módulo.</p> + +<h4 id="Módulos_5">Módulos</h4> + +<ul> + <li>{{web.link("/es/docs/Learn/Tools_and_testing/Cross_browser_testing", "Pruebas en varios navegadores")}} (25 a 30 horas de lectura/ejercicios)</li> + <li>{{web.link("/es/docs/Learn/Accessibility", "Accesibilidad")}} (20 a 25 horas de lectura/ejercicios)</li> +</ul> + +<h3 id="Herramientas_modernas">Herramientas modernas</h3> + +<p>Tiempo para completar: 55 a 90 horas</p> + +<h4 id="Prerrequisitos_8">Prerrequisitos</h4> + +<p>Es una buena idea conocer HTML, CSS y JavaScript antes de trabajar en esta sección, ya que las herramientas analizadas funcionan junto con muchas de estas tecnologías.</p> + +<h4 id="¿Cómo_sabré_que_estoy_listo_para_seguir_adelante_7">¿Cómo sabré que estoy listo para seguir adelante?</h4> + +<p>No hay artículos de evaluación específicos en este conjunto de módulos. Los tutoriales de casos de estudio al final del segundo y tercer módulo te preparan para comprender los conceptos básicos de las herramientas modernas.</p> + +<h4 id="Módulos_6">Módulos</h4> + +<ul> + <li>{{web.link("/es/docs/Learn/Tools_and_testing/GitHub", "Git y GitHub")}} (lectura de 5 horas)</li> + <li>{{web.link("/es/docs/Learn/Tools_and_testing/Understanding_client-side_tools", "Comprender las herramientas de desarrollo web del lado del cliente")}} (lectura de 20 a 25 horas)</li> + <li> + <p>{{web.link("/es/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks", "Comprender los marcos de JavaScript de lado del cliente")}} (30 a 60 horas de lectura/ejercicios)</p> + </li> +</ul> diff --git a/files/es/learn/getting_started_with_the_web/css_basics/index.html b/files/es/learn/getting_started_with_the_web/css_basics/index.html new file mode 100644 index 0000000000..af79920af3 --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/css_basics/index.html @@ -0,0 +1,283 @@ +--- +title: CSS básico +slug: Learn/Getting_started_with_the_web/CSS_basics +tags: + - CSS + - Codificacion/Scripting + - Estilos/Styling + - Principiante + - Web + - aprende +translation_of: Learn/Getting_started_with_the_web/CSS_basics +--- +<div>{{LearnSideBar}}</div> + +<div>{{PreviousMenuNext("Learn/Getting_started_with_the_web/HTML_basics", "Learn/Getting_started_with_the_web/JavaScript_basics","Learn/Getting_started_with_the_web")}}</div> + +<div class="summary"> +<p>CSS (<em>Hojas de Estilo en Cascada</em>) es el código que usas para dar estilo a tu página web. <em>CSS Básico</em> te lleva a través de lo que tú necesitas para empezar. Contestará a preguntas del tipo: ¿Cómo hago mi texto rojo o negro? ¿Cómo hago que mi contenido se muestre en tal y tal lugar de la pantalla? ¿Cómo decoro mi página web con imágenes de fondo y colores?</p> +</div> + +<h2 id="Entonces_¿qué_es_CSS_realmente">Entonces ¿qué es CSS, realmente?</h2> + +<p>Como HTML, CSS (<em>Cascading Style Sheets</em>) u Hojas de estilo en cascada en español, no es realmente un lenguaje de programación, tampoco es un lenguaje de marcado. Es un <em>lenguaje de hojas de estilo,</em> es decir, te permite aplicar estilos de manera selectiva a elementos en documentos HTML. Por ejemplo, para seleccionar <strong>todos</strong> los elementos de párrafo en una página HTML y volver el texto dentro de ellos de color rojo, has de escribir este CSS:</p> + +<pre class="brush: css notranslate">p { + color: red; +}</pre> + +<p>Vas a probarlo: pega estas tres líneas de CSS en un nuevo archivo en tu editor de texto y guarda este archivo como <code>style.css</code> en tu directorio <code>styles</code> (estilos).</p> + +<p>Pero aún debes aplicar el CSS a tu documento HTML, de otra manera el estilo CSS no cambiará cómo tu navegador muestra el documento HTML. (Si no has seguido nuestro proyecto, lee <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">Manejo de archivos</a> y <a href="/es/docs/Learn/Getting_started_with_the_web/HTML_basics">HTML básico</a> para averiguar qué necesitas hacer primero.)</p> + +<ol> + <li>Abre tu archivo <code>index.html</code> y pega la siguiente línea en algún lugar dentro del {{htmlelement("head")}}, es decir, entre las etiquetas <code><head></code> y <code></head></code>: + + <pre class="brush: html notranslate"><link href="styles/style.css" rel="stylesheet" type="text/css"></pre> + </li> + <li>Guarda el archivo <code>index.html</code> y cárgalo en tu navegador. Debes ver algo como esto:</li> +</ol> + +<p><img alt="Un logo de Mozilla y algunos párrafos. El texto del párrafo ha sido estilizado en rojo por nuestro css." src="https://mdn.mozillademos.org/files/9435/website-screenshot-styled.png" style="display: block; height: 832px; margin: 0px auto; width: 711px;">Si tu texto del párrafo ahora es rojo, ¡felicitaciones, ya has escrito tu primer CSS de forma exitosa!</p> + +<h3 id="Anatomía_de_una_regla_CSS">Anatomía de una regla CSS</h3> + +<p>Observa el código CSS de arriba, un poco más a detalle:</p> + +<p><img alt="Partes de una declaracion de css" src="https://mdn.mozillademos.org/files/11925/csspartes.png" style="display: block; height: 480px; margin: 0px auto; width: 850px;"></p> + +<p>La estructura completa es llamada <strong>regla predeterminada</strong> (pero a menudo «regla» para abreviar). Nota también los nombres de las partes individuales:</p> + +<dl> + <dt>Selector</dt> + <dd>El elemento HTML en el que comienza la regla. Esta selecciona el(los) elemento(s) a dar estilo (en este caso, los elementos {{htmlelement("p")}} ). Para dar estilo a un elemento diferente, solo cambia el selector.</dd> + <dt>Declaración</dt> + <dd>Una sola regla como <code>color: red;</code> especifica a cuál de las <strong>propiedades</strong> del elemento quieres dar estilo.</dd> + <dt>Propiedades</dt> + <dd>Maneras en las cuales puedes dar estilo a un elemento HTML. (En este caso, <code>color</code> es una propiedad del elemento {{htmlelement("p")}} ). En CSS, seleccionas qué propiedad quieres afectar en tu regla.</dd> + <dt>Valor de la propiedad</dt> + <dd>A la derecha de la propiedad, después de los dos puntos (:), tienes el <strong>valor de la propiedad</strong>, para elegir una de las muchas posibles apariencias para una propiedad determinada (hay muchos valores para <code>color</code> además de <code>red</code>).</dd> +</dl> + +<p>Nota las otras partes importantes de la sintaxis:</p> + +<ul> + <li>Cada una de las reglas (aparte del selector) deben estar encapsuladas entre llaves (<code>{}</code>).</li> + <li>Dentro de cada declaración, debes usar los dos puntos (<code>:</code>) para separar la propiedad de su valor.</li> + <li>Dentro de cada regla, debes usar el punto y coma (<code>;</code>) para separar una declaración de la siguiente.</li> +</ul> + +<p>De este modo para modificar varios valores de propiedad a la vez, solo necesitas escribirlos separados por punto y coma (;), así:</p> + +<pre class="brush: css notranslate">p { + color: red; + width: 500px; + border: 1px solid black; +}</pre> + +<h3 id="Seleccionar_varios_elementos">Seleccionar varios elementos</h3> + +<p>También puedes seleccionar varios elementos y aplicar una sola regla a todos ellos. Incluye varios selectores separados por comas (,). Por ejemplo:</p> + +<pre class="brush: css notranslate">p,li,h1 { + color: red; +}</pre> + +<h3 id="Diferentes_tipos_de_selectores">Diferentes tipos de selectores</h3> + +<p>Existen muchos tipos diferentes de selectores. Antes, solo viste los <strong>selectores de elementos</strong>, los cuales seleccionan todos los elementos de un tipo dado en los documentos HTML. Sin embargo puedes hacer selecciones más específicas que esas. En seguida están algunos de los tipos de selectores más comunes:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Nombre del selector</th> + <th scope="col">Qué selecciona</th> + <th scope="col">Ejemplo</th> + </tr> + </thead> + <tbody> + <tr> + <td>Selector de elemento (llamado algunas veces selector de etiqueta o tipo)</td> + <td>Todos los elementos HTML del tipo especificado.</td> + <td><code>p</code><br> + Selecciona <code><p></code></td> + </tr> + <tr> + <td>Selector de identificación (ID)</td> + <td>El elemento en la página con el ID especificado (en una página HTML dada, solo se permite un único elemento por ID).</td> + <td><code>#mi-id</code><br> + Selecciona <code><p id="mi-id"></code> y <code><a id="mi-id"></code></td> + </tr> + <tr> + <td>Selector de clase</td> + <td>Los elementos en la página con la clase especificada (una clase puede aparecer varias veces en una página).</td> + <td><code>.mi-clase</code><br> + Selecciona <code><p class="mi-clase"></code> y <code><a class="mi-clase"></code></td> + </tr> + <tr> + <td>Selector de atributo</td> + <td>Los elementos en una página con el atributo especificado.</td> + <td><code>img[src]</code><br> + Selecciona <code><img src="mimagen.png"></code> pero no <code><img></code></td> + </tr> + <tr> + <td>Selector de pseudoclase</td> + <td>Los elementos especificados, pero solo cuando esté en el estado especificado, por ejemplo cuando el puntero esté sobre él.</td> + <td><code>a:hover</code><br> + Selecciona <code><a></code>, pero solo cuando el puntero esté sobre el enlace.</td> + </tr> + </tbody> +</table> + +<p>Existen muchos más selectores para explorar, y podrás encontrar una lista más detallada en la <a href="/es/docs/Learn/CSS/Building_blocks/Selectores_CSS">guía de Selectores</a>.</p> + +<h2 id="Fuentes_y_texto">Fuentes y texto</h2> + +<p>Ahora que has explorado lo básico de CSS, empieza por añadir información y algunas reglas más a tu archivo <code>style.css</code> para que tu ejemplo se vea bonito. Primero, haz que tus fuentes y texto luzcan un poco mejor.</p> + +<ol> + <li>Antes que nada, regresa y busca las <a href="/es/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like#Fuente">fuentes de Google Fonts</a> que guardaste en un lugar seguro. Agrega el elemento {{htmlelement("link")}}<code>...</code> en algún lugar del <em>head</em> de tu archivo <code>index.html</code> (de nuevo, en cualquier lugar entre las etiquetas {{htmlelement("head")}} y <code></head></code>). Debe verse algo así: + + <pre class="brush: html notranslate"><link href="https://fonts.googleapis.com/css2?family=Open+Sans" rel="stylesheet" type="text/css"></pre> + </li> + <li>Luego, borra la regla existente en tu archivo <code>style.css</code>. Fue una buena prueba, pero el texto en rojo en realidad no se ve muy bien.</li> + <li> + <p>Añade las siguientes líneas (que se muestran a continuación), sustituyendo la asignación de <code>font-family</code> por tu selección de <code>font-family</code> que obtuviste en <a href="/es/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like#Fuente">¿Cuál será la apariencia de tu sitio Web?</a> La propiedad <code>font-family</code> se refiere a la(s) fuente(s) que deseas usar en tu texto. Esta regla define una fuente base global y un tamaño de fuente para usar en toda la página. Dado que {{htmlelement("html")}} es el elemento primario (o padre) de toda la página, todos los elementos contenidos dentro de él heredan las propiedades <code>font-size</code> y <code>font-family</code>):</p> + + <pre class="brush: css notranslate">html { + font-size: 10px; /* px quiere decir 'píxeles': el tamaño de la fuente base es ahora de 10 píxeles de altura */ + font-family: "Open Sans", sans-serif; /* Este debe ser el resto del resultado que obtuviste de Google fonts */ +}</pre> + + <div class="note"> + <p><strong>Nota</strong>: se ha añadido un comentario para explicar qué significa «px». Todo lo que está en un documento de CSS entre <code>/*</code> y <code>*/</code> es un <strong>comentario en CSS</strong>, el cual el navegador descarta cuando carga el código. Este es un espacio donde puedes escribir notas útiles sobre lo que estás haciendo.</p> + </div> + </li> + <li>Ahora escoge el tamaño de fuente para los elementos que contienen texto dentro del cuerpo del HTML ({{htmlelement("h1")}}, {{htmlelement("li")}}, y {{htmlelement("p")}}). También centra el texto del título, escoge un ancho de línea y espaciado entre letras en el contenido del texto para hacerlo un poco más legible: + <pre class="brush: css notranslate">h1 { + font-size: 60px; + text-align: center; +} + +p, li { + font-size: 16px; + line-height: 2; + letter-spacing: 1px; +}</pre> + </li> +</ol> + +<p>Puedes ajustar estos valores en px para lograr que tu diseño luzca como desees, pero por lo general tu diseño debe verse así:</p> + +<p><img alt="Un logo de Mozilla y algunos párrafos. se ha establecido una fuente sans-serif, se han ajustado los tamaños de las fuentes, la altura de las líneas y el espaciado de las letras, y se ha centrado el encabezamiento de la página principal." src="https://mdn.mozillademos.org/files/9447/website-screenshot-font-small.png" style="display: block; height: 1020px; margin: 0px auto; width: 921px;"></p> + +<h2 id="Cajas_cajas_todo_se_trata_de_cajas">Cajas, cajas, todo se trata de cajas</h2> + +<p>Una cosa que notarás sobre la escritura de CSS es que trata mucho sobre cajas —ajustando su tamaño, color, posición, etc—. Puedes pensar en la mayoría de los elementos HTML de tu página como cajas apiladas una sobre la otra.</p> + +<p><img alt="Una gran pila de cajas o cajones puestos uno encima del otro." src="https://mdn.mozillademos.org/files/9441/boxes.jpg" style="display: block; height: 463px; margin: 0px auto; width: 640px;"></p> + +<p>No es de extrañar que el diseño de CSS esté basado principalmente en el <em>modelo de caja</em>. Cada una de las cajas que ocupa espacio en tu página tiene propiedades como estas:</p> + +<ul> + <li><code>padding</code> (relleno), el espacio alrededor del contenido. En el ejemplo siguiente, es el espacio alrededor del texto del párrafo.</li> + <li><code>border</code> (marco), la línea que se encuentra fuera del relleno.</li> + <li><code>margin</code> (margen), el espacio fuera del elemento que lo separa de los demás.</li> +</ul> + +<p><img alt="tres cajas puestas una dentro de otra. De fuera a dentro están etiquetadas con el margen, el borde y el relleno" src="https://mdn.mozillademos.org/files/9443/box-model.png" style="display: block; height: 450px; margin: 0px auto; width: 574px;"></p> + +<p>En esta sección también se utiliza:</p> + +<ul> + <li><code>width</code> (ancho del elemento)</li> + <li><code>background-color</code>, el color de fondo del contenido y del relleno</li> + <li><code>color</code>, el color del contenido del elemento (generalmente texto)</li> + <li><code>text-shadow</code>: coloca una sombra difuminada en el texto dentro del elemento</li> + <li><code>display</code>: selecciona el modo de visualización para el elemento (no te preocupes de esto por ahora)</li> +</ul> + +<p>Bien, ¡continúa y agrega más código CSS a la página! Sigue añadiendo estas reglas nuevas al final de la página, y no temas experimentar cambiando los valores para ver cómo resulta.</p> + +<h3 id="Cambiar_el_color_de_la_página">Cambiar el color de la página</h3> + +<pre class="brush: css notranslate">html { + background-color: #00539F; +}</pre> + +<p>Esta regla asigna un color de fondo a la página entera. Puedes cambiar el código de color por cualquiera <a href="/es/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like#Color_de_tema">como el que elegiste usar en tu proyecto</a>.</p> + +<h3 id="Dar_estilo_al_cuerpo_del_documento">Dar estilo al cuerpo del documento</h3> + +<pre class="brush: css notranslate">body { + width: 600px; + margin: 0 auto; + background-color: #FF9500; + padding: 0 20px 20px 20px; + border: 5px solid black; +}</pre> + +<p>Ahora tienes varias declaraciones en el elemento <a href="/es/docs/Web/HTML/Element/body">body</a>. Revisa una por una:</p> + +<ul> + <li><code>width: 600px;</code> — esto hará que el cuerpo siempre tenga 600 píxeles de ancho.</li> + <li><code>margin: 0 auto;</code> — cuando seleccionas dos valores dentro de propiedades como <code>margin</code> o <code>padding</code>, el primer valor afectará los lados superior (top) <strong>e</strong> inferior (bottom) (en este caso haciéndolo en 0), y el segundo valor los lados izquierdo (left) <strong>y</strong> derecho (right) (aquí, <code>auto</code> es un valor especial que divide el espacio disponible entre derecha e izquierda). Puedes usar esta propiedad con uno, dos, tres o cuatro valores como se explica en la <a href="/es/docs/Web/CSS/padding#Sintaxis">sintaxis de padding</a>.</li> + <li><code>background-color: #FF9500;</code> — como antes, este selecciona el color de fondo de un elemento. Se ha usado un naranja rojizo para el elemento <code>body</code> en contraste con el azul oscuro del elemento {{htmlelement("html")}}. Sigue y experimenta. Siéntete libre de usar <code>white</code> o cualquiera que sea de tu agrado.</li> + <li><code>padding: 0 20px 20px 20px;</code> — tienes 4 valores puestos en el relleno, para dar un poco de espacio alrededor del contenido. Esta vez no pondrás relleno en la parte de arriba de <code>body</code>, 20 píxeles a la izquierda, abajo y derecha. Los valores se ponen: arriba, derecha, abajo e izquierda, en ese orden. Como con <code>margin</code> usar esta propiedad con uno, dos, tres o cuatro valores como se explica en la <a href="/es/docs/Web/CSS/padding#Sintaxis">sintaxis de padding</a>.</li> + <li><code>border: 5px solid black;</code> — este simplemente pone un borde de 5 píxeles de ancho, continuo y de color negro alrededor del elemento <code>body</code>.</li> +</ul> + +<h3 id="Posicionar_y_dar_estilo_al_título_principal_de_la_página">Posicionar y dar estilo al título principal de la página</h3> + +<pre class="brush: css notranslate">h1 { + margin: 0; + padding: 20px 0; + color: #00539F; + text-shadow: 3px 3px 1px black; +}</pre> + +<p>Puedes haber notado que hay un hueco horrible en la parte superior de <em>body</em>. Esto sucede porque los navegadores vienen con estilos por defecto, ¡incluso cuando aún no se ha aplicado ningún archivo CSS! Esto podría parecer una mala idea, pero se quiere que aun una página sin estilizar sea legible. Para deshacerte de este espacio elimina el estilo por defecto, agregando <code>margin: 0;</code>.</p> + +<p>Enseguida, se ha puesto un relleno arriba y abajo del título de 20 píxeles, y se hizo que el color del texto sea el mismo que el color de fondo de <code>html</code>.</p> + +<p>Una propiedad muy interesante que se ha usado aquí es <code>text-shadow</code>, que aplica una sombra al texto del elemento. Sus cuatro valores son como sigue:</p> + +<ul> + <li>El primer valor en píxeles asigna el <strong>desplazamiento horizontal</strong> de la sombra desde el texto —qué tan lejos la mueve a la derecha—. Un valor negativo la moverá a la izquierda.</li> + <li>El segundo valor en píxeles asigna el <strong>desplazamiento vertical</strong> de la sombra desde el texto —qué tan lejos la mueve hacia abajo—. En este ejemplo, un valor negativo la desplazaría hacia arriba.</li> + <li>El tercer valor en píxeles asigna <strong>radio de desenfoque</strong> de la sombra —un valor grande es igual a una sombra borrosa—.</li> + <li>El cuarto valor asigna el color base de la sombra.</li> +</ul> + +<p>Una vez más, trata de experimentar con diferentes valores para ver cómo resulta.</p> + +<h3 id="Centrar_la_imagen">Centrar la imagen</h3> + +<pre class="brush: css notranslate">img { + display: block; + margin: 0 auto; +}</pre> + +<p>Finalmente, centra la imagen para hacer que luzca mejor. Puedes usar nuevamente el truco de <code>margin: 0 auto</code> que usaste antes para <code>body</code>, pero existen diferencias que requieren que hagas algo más para que el código CSS funcione.</p> + +<p>El elemento {{htmlelement("body")}} es un elemento en nivel de bloque (<strong>block-level</strong>), lo que significa que tomará espacio en la página y que puede tener otros valores de espacio aplicables como margen. Las imágenes, por otra parte, son elementos <strong>inline</strong>, lo que quiere decir que no puedes aplicarles márgenes, debes dar a la imagen un comportamiento de <em>block-level</em> usando <code>display: block;</code>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: las instrucciones anteriores asumen que estás usando una imagen más pequeña que el ancho establecido en <code>body</code> (600 píxeles). Si tu imagen es más grande, desbordará el cuerpo, derramándose en el resto de la página. Para solucionar esto, puedes hacer lo siguiente: 1) reducir el ancho de la imagen usando un <a href="https://es.wikipedia.org/wiki/Editor_de_gráficos_rasterizados">editor gráfico</a>, o 2) usar CSS para dimensionar la imagen estableciendo la propiedad {{cssxref("width")}} en el elemento <code><img></code> con un valor menor.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: no te preocupes si aún no entiendes <code>display: block;</code> y la diferencia entre un elemento de bloque y un elemento <em>inline</em>. Lo entenderás en tanto estudies CSS a profundidad. Puedes encontrar más en cuanto a los diferentes valores disponibles para <em>display</em> en la <a href="/es/docs/Web/CSS/display">página de referencia de display</a>.</p> +</div> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Si has seguido las instrucciones de esta publicación, deberías terminar con una página que luce algo así (también puedes <a href="http://mdn.github.io/beginner-html-site-styled/">ver nuestra versión aquí</a>):</p> + +<p><img alt="El logo de Mozilla centrado con título y párrafos. Ahora se ve muy bien de estilo, con un fondo azul para toda la página y un fondo naranja para la franja de contenido principal centrada." src="https://mdn.mozillademos.org/files/9455/website-screenshot-final.png" style="display: block; height: 1084px; margin: 0px auto; width: 940px;"></p> + +<p>Si te atoraste, puedes comparar tu trabajo con el <a href="https://github.com/mdn/beginner-html-site-styled/blob/gh-pages/styles/style.css">código del ejemplo finalizado en GitHub</a>.</p> + +<p>Aquí, solo has arañado la superficie de CSS. Si quieres encontrar más, puedes ir a la <a href="/es/docs/Learn/CSS">página de aprendizaje de CSS</a>.</p> + +<p>{{PreviousMenuNext("Learn/Getting_started_with_the_web/HTML_basics", "Learn/Getting_started_with_the_web/JavaScript_basics","Learn/Getting_started_with_the_web")}}</p> diff --git a/files/es/learn/getting_started_with_the_web/cómo_funciona_la_web/index.html b/files/es/learn/getting_started_with_the_web/cómo_funciona_la_web/index.html new file mode 100644 index 0000000000..546baf0309 --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/cómo_funciona_la_web/index.html @@ -0,0 +1,100 @@ +--- +title: Cómo funciona la web +slug: Learn/Getting_started_with_the_web/Cómo_funciona_la_Web +tags: + - Cliente + - DNS + - HTTP + - IP + - Infraestructura + - Internet + - Principiante + - Protocolos + - Servidor + - TCP + - Web +translation_of: Learn/Getting_started_with_the_web/How_the_Web_works +--- +<div>{{LearnSidebar()}}</div> + +<div>{{PreviousMenu("Learn/Getting_started_with_the_web/Publishing_your_website", "Learn/Getting_started_with_the_web")}}</div> + +<div class="summary"> +<p><em>Cómo funciona la web</em> proporciona una vista simplificada de lo que sucede cuando ves una página web en un navegador web de tu computador o teléfono.</p> +</div> + +<p>Esta teoría no es esencial para escribir código web a corto plazo, pero en poco tiempo empezarás a beneficiarte realmente al entender lo que está sucediendo en el fondo.</p> + +<h2 id="Los_clientes_y_servidores">Los clientes y servidores</h2> + +<p>Las computadoras conectadas a la web se llaman <strong>clientes</strong> y <strong>servidores</strong>. Un diagrama simplificado de cómo interactúan se vería así:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/17299/Cliente-Servidor.png" style="height: 123px; width: 336px;"></p> + +<ul> + <li>Los clientes son dispositivos de los usuarios conectados a Internet (por ejemplo, tu ordenador conectado a la red Wi-Fi o el teléfono conectado a la red de telefonía móvil) y el software que se encuentra disponible y permite acceder a Internet en dichos dispositivos (normalmente, un navegador web como Firefox o Chrome).</li> + <li>Los servidores son computadores que almacenan páginas web, sitios o aplicaciones. Cuando un dispositivo cliente quiere acceder a una página web, una copia de la página web se descarga desde el servidor en el equipo cliente y se muestra en el navegador web del usuario.</li> +</ul> + +<h2 id="Las_otras_partes_de_la_caja_de_herramientas">Las otras partes de la caja de herramientas</h2> + +<p>El cliente y el servidor que describimos anteriormente, no cuentan toda la historia. Hay muchas otras partes involucradas y vamos a describirlas a continuación.</p> + +<p>Por ahora, imaginemos que la web es un camino. En un extremo de la carretera, está el cliente, que es como tu casa. En el extremo opuesto del camino, está el servidor, que es una tienda en la que deseas comprar algo.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9749/road.jpg" style="display: block; height: 427px; margin: 0px auto; width: 640px;"></p> + +<p>Además del cliente y el servidor, también tenemos que saludar a:</p> + +<ul> + <li><strong>Tu conexión a Internet</strong>: permite enviar y recibir datos en la web. Básicamente es el recorrido entre tu casa y la tienda.</li> + <li><strong>TCP/IP</strong>: <strong>Protocolo de Control de Transmisión</strong> y <strong>Protocolo de Internet</strong>, son los protocolos de comunicación que definen cómo deben viajar los datos a través de la web. Esto es, los medios de transporte que te permiten hacer un pedido, ir a la tienda y comprar los productos. En nuestro ejemplo, podría ser un coche, una bicicleta o tus propios pies.</li> + <li><strong>DNS: </strong>los servidores del <strong>Sistema de Nombres de Dominio</strong> (DNS, por sus siglas en inglés), son como una libreta de direcciones de sitios web. Cuando escribes una dirección web en el navegador, el navegador busca los DNS antes de recuperar el sitio web. El navegador necesita averiguar en qué servidor vive el sitio web y así enviar los mensajes HTTP al lugar correcto (ver más abajo). Esto es como buscar la dirección de la tienda para que puedas llegar a ella.</li> + <li><strong>HTTP: </strong><span class="st">el <strong>Protocolo de Transferencia de Hipertexto</strong></span> es un protocolo de aplicación que define un idioma para que los clientes y servidores se puedan comunicar. Esto es como el idioma que utilizas para ordenar tus compras.</li> + <li><strong>Archivos componentes</strong>: un sitio web se compone de muchos archivos diferentes, que son como las diferentes partes de los productos que comprarás en la tienda. Estos archivos se dividen en dos tipos principales: + <ul> + <li><strong>Archivos de código</strong>: los sitios web se construyen principalmente con HTML, CSS y JavaScript, aunque te encontrarás con otras tecnologías más adelante.</li> + <li><strong>Recursos: </strong>este es un nombre colectivo para el resto de materiales que conforman un sitio web, como imágenes, música, video, documentos de Word, archivos PDF, etc.</li> + </ul> + </li> +</ul> + +<h2 id="Entonces_¿qué_sucede_exactamente">Entonces, ¿qué sucede exactamente?</h2> + +<p>Cuando escribes una dirección web en el navegador (usando nuestra analogía para ir a la tienda):</p> + +<ol> + <li>El navegador va al servidor DNS y encuentra la dirección real del servidor donde el sitio web vive (encontrar la dirección de la tienda).</li> + <li>El navegador envía un mensaje de petición HTTP al servidor, pidiéndole que envíe una copia de la página web para el cliente (ir a la tienda y hacer un pedido). Este mensaje y todos los datos enviados entre el cliente y el servidor, se envían a través de tu conexión a Internet usando TCP/IP.</li> + <li>Siempre que el servidor apruebe la solicitud del cliente, el servidor enviará al cliente un mensaje «200 OK», que significa, «¡por supuesto que puedes ver ese sitio web! Aquí está.», y comenzará a enviar los archivos de la página web al navegador como una serie de pequeños trozos llamados <em>paquetes de datos</em> (la tienda te entrega tus productos y los llevas de regreso a casa).</li> + <li>El navegador reúne los pequeños trozos, forma un sitio web completo y te lo muestra (llegas a casa con tus nuevas compras).</li> +</ol> + +<h2 id="Explicación_de_los_DNS">Explicación de los DNS</h2> + +<p>Las direcciones webs reales no son las agradables y fácilmente recordables secuencias que tecleas en la barra de direcciones para encontrar tus sitios webs favoritos. En realidad, se trata de secuencias de números, algo como 63.245.217.105.</p> + +<p>Lo anterior se llama <a href="/es/docs/Glossary/IP_Address">dirección IP</a> y representa un lugar único en la web. Sin embargo, no es muy fácil de recordar, ¿verdad? Por eso se inventaron los servidores de nombres de dominio. Estos son servidores especiales que hacen coincidir una dirección web tecleada desde tu navegador («mozilla.org», por ejemplo) con la dirección real del sitio web (IP).</p> + +<p>Los sitios webs se pueden acceder directamente a través de sus direcciones IP. Intenta acceder a la página web de Mozilla escribiendo <strong><code>63.245.217.105</code></strong> en la barra de dirección de una nueva pestaña en tu navegador. Puedes encontrar la dirección IP de un sitio web escribiendo su dominio en una herramienta como <a href="https://ipinfo.info/html/ip_checker.php">IP Checker</a>.</p> + +<p><img alt="Un nombre de dominio es más que otra forma de una dirección IP" src="https://mdn.mozillademos.org/files/8405/dns-ip.png" style="height: 160px; width: 330px;"></p> + +<h2 id="Explicación_de_los_paquetes">Explicación de los paquetes</h2> + +<p>Anteriormente hemos utilizado el término <em><strong>paquetes</strong></em> para describir el formato en que los datos se envían desde el servidor al cliente. ¿Qué significa esto? Básicamente, que los datos se envían a través de la web como miles de trozos pequeños, permitiendo que muchos usuarios pueden descargar la misma página web al mismo tiempo. Si los sitios web fueran enviados como grandes trozos, sólo un usuario podría descargarlos a la vez, lo que volvería a la web muy ineficiente y poco divertida.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="/es/docs/Learn/Common_questions/How_does_the_Internet_work">¿Cómo funciona Internet</a></li> + <li><a href="https://dev.opera.com/articles/http-basic-introduction/">HTTP: Un protocolo de nivel de aplicación </a>(en inglés)</li> + <li><a href="https://dev.opera.com/articles/http-lets-get-it-on/">HTTP: Trabajemos con él</a> (en inglés)</li> + <li><a href="https://dev.opera.com/articles/http-response-codes/">Códigos de respuesta: HTTP</a> (en inglés)</li> +</ul> + +<h2 id="Crédito">Crédito</h2> + +<p>Foto de la calle: Street Composing, por <a href="https://www.flickr.com/photos/kdigga/">Kevin </a>D.</p> + +<p>{{PreviousMenu("Learn/Getting_started_with_the_web/Publishing_your_website", "Learn/Getting_started_with_the_web")}}</p> diff --git a/files/es/learn/getting_started_with_the_web/html_basics/index.html b/files/es/learn/getting_started_with_the_web/html_basics/index.html new file mode 100644 index 0000000000..e4e4f856a3 --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/html_basics/index.html @@ -0,0 +1,224 @@ +--- +title: 'HTML: básico' +slug: Learn/Getting_started_with_the_web/HTML_basics +tags: + - Aprendizaje + - HTML + - Principiante + - Web +translation_of: Learn/Getting_started_with_the_web/HTML_basics +--- +<p>{{LearnSideBar}}</p> + +<p>{{PreviousMenuNext("Learn/Getting_started_with_the_web/Dealing_with_files", "Learn/Getting_started_with_the_web/CSS_basics","Learn/Getting_started_with_the_web")}}</p> + +<p>El Lenguaje de Marcado de Hipertexto (HTML) es el código que se utiliza para estructurar y desplegar una página web y sus contenidos. Por ejemplo, sus contenidos podrían ser párrafos, una lista con viñetas, o imágenes y tablas de datos. Como lo sugiere el título, este artículo te dará una comprensión básica de HTML y cúal es su función.</p> + +<h2 id="Entonces_¿qué_es_HTML_en_realidad">Entonces, ¿qué es HTML en realidad?</h2> + +<p>HTML no es un lenguaje de programación; es un <em>lenguaje de marcado</em> que define la estructura de tu contenido. HTML consiste en una serie de elementos que usarás para encerrar diferentes partes del contenido para que se vean o comporten de una determinada manera. Las etiquetas de encierre pueden hacer de una palabra o una imagen un hipervínculo a otro sitio, se pueden cambiar palabras a cursiva, agrandar o achicar la letra, etc. Por ejemplo, toma la siguiente línea de contenido:</p> + +<pre class="notranslate">Mi gato es muy gruñon</pre> + +<p>Si quieres especificar que se trata de un párrafo, podrías encerrar el texto con la etiqueta de párrafo ({{htmlelement("p")}}):</p> + +<pre class="notranslate"><p>Mi gato es muy gruñon</p></pre> + +<h3 id="Anatomía_de_un_elemento_HTML">Anatomía de un elemento HTML</h3> + +<p>Explora este párrafo en mayor profundidad.</p> + +<p><img alt="elementos de gato gruñon" src="https://mdn.mozillademos.org/files/11913/htmlexp.png" style="display: block; height: 255px; margin: 0px auto; width: 821px;"></p> + +<p>Las partes principales del elemento son:</p> + +<ol> + <li><strong>La etiqueta de apertura</strong>: consiste en el nombre del elemento (en este caso, p), encerrado por <strong>paréntesis angulares</strong> (< >) de apertura y cierre. Establece dónde comienza o empieza a tener efecto el elemento —en este caso, dónde es el comienzo del párrafo—.</li> + <li><strong>La etiqueta de cierre</strong>: es igual que la etiqueta de apertura, excepto que incluye una barra de cierre (/) antes del nombre de la etiqueta. Establece dónde termina el elemento —en este caso dónde termina el párrafo—.</li> + <li><strong>El contenido</strong>: este es el contenido del elemento, que en este caso es sólo texto.</li> + <li><strong>El elemento</strong>: la etiqueta de apertura, más la etiqueta de cierre, más el contenido equivale al elemento.</li> +</ol> + +<p>Los elementos pueden también tener atributos, que se ven así:</p> + +<p><img alt="atributo html" src="https://mdn.mozillademos.org/files/11915/htmlatributos.png" style="display: block; height: 156px; margin: 0px auto; width: 1287px;"></p> + +<p>Los atributos contienen información adicional acerca del elemento, la cual no quieres que aparezca en el contenido real del elemento. Aquí <code>class</code> es el <em>nombre</em> del atributo y <code>editor-note</code> el <em>valor</em> del atributo. En este caso, el atributo <code>class</code> permite darle al elemento un nombre identificativo, que se puede utilizar luego para apuntarle al elemento información de estilo y demás cosas.</p> + +<p>Un atributo debe tener siempre:</p> + +<ol> + <li>Un espacio entre este y el nombre del elemento (o del atributo previo, si el elemento ya posee uno o más atributos).</li> + <li>El nombre del atributo, seguido por un signo de igual (<strong>=</strong>).</li> + <li>Comillas de apertura y de cierre, encerrando el valor del atributo.</li> +</ol> + +<p>Los atributos siempre se incluyen en la etiqueta de apertura de un elemento, nunca en la de cierre.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: el atributo con valores simples que no contengan espacios en blanco ASCII (o cualesquiera de los caracteres <code>"</code> <code>'</code> <code>`</code> <code>=</code> <code><</code> <code>></code>) pueden permanecer sin entrecomillar, pero se recomienda entrecomillar todos los valores de atributo, ya que esto hace que el código sea más consistente y comprensible.</p> +</div> + +<h3 id="Anidar_elementos">Anidar elementos</h3> + +<p>Puedes también colocar elementos dentro de otros elementos —esto se llama <strong>anidamiento</strong>—. Si, por ejemplo, quieres resaltar una palabra del texto (en el ejemplo la palabra «muy»), podemos encerrarla en un elemento {{htmlelement("strong")}}, que significa que dicha palabra se debe enfatizar:</p> + +<pre class="notranslate"><p>Mi gato es <strong>muy</strong> gruñon.</p></pre> + +<p>Debes asegurarte que los elementos estén correctamente anidados: en el ejemplo de abajo, creaste la etiqueta de apertura del elemento {{htmlelement("p")}} primero, luego la del elemento {{htmlelement("strong")}}, por lo tanto, debes cerrar esta etiqueta primero, y luego la de <p>. Esto es incorrecto:</p> + +<pre class="notranslate"><p>Mi gato es <strong>muy gruñon.</p></strong></pre> + +<p>Los elementos deben abrirse y cerrarse ordenadamente, de forma tal que se encuentren claramente dentro o fuera el uno del otro. Si estos se encuentran solapados, el navegador web tratará de adivinar lo que intentas decirle, pero puede que obtengas resultados inesperados. Así que, ¡no lo hagas!</p> + +<h3 id="Elementos_vacíos">Elementos vacíos</h3> + +<p>Algunos elementos no poseen contenido, y son llamados <strong>elementos vacíos</strong>. Toma, por ejemplo, el elemento {{htmlelement("img")}} de nuestro HTML:</p> + +<pre class="notranslate"><img src="images/firefox-icon.png" alt="Mi imagen de prueba"></pre> + +<p>Posee dos atributos, pero no hay etiqueta de cierre <code></img></code> ni contenido encerrado. Esto es porque un elemento de imagen no encierra contenido al cual afectar. Su propósito es desplegar una imagen en la página HTML, en el lugar en que aparece.</p> + +<h3 id="Anatomía_de_un_documento_HTML">Anatomía de un documento HTML</h3> + +<p>Hasta ahora has visto lo básico de elementos HTML individuales, pero estos no son muy útiles por sí solos. Ahora verás cómo los elementos individuales son combinados para formar una página HTML entera. Vuelve a visitar el código de tu ejemplo en <code>index.html</code> (que viste por primera vez en el artículo <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">Manejo de archivos</a>):</p> + +<pre class="notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Mi pagina de prueba</title> + </head> + <body> + <img src="images/firefox-icon.png" alt="Mi imagen de prueba"> + </body> +</html></pre> + +<p>Tienes:</p> + +<ul> + <li><code><!DOCTYPE html></code> — el tipo de documento. Es un preámbulo requerido. Anteriormente, cuando HTML era joven (cerca de 1991/2), los tipos de documento actuaban como vínculos a un conjunto de reglas que el código HTML de la página debía seguir para ser considerado bueno, lo que podía significar la verificación automática de errores y algunas otras cosas de utilidad. Sin embargo, hoy día es simplemente un artefacto antiguo que a nadie le importa, pero que debe ser incluido para que todo funcione correctamente. Por ahora, eso es todo lo que necesitas saber.</li> + <li><code><html></html></code> — el elemento {{htmlelement("html")}}. Este elemento encierra todo el contenido de la página entera y, a veces, se le conoce como el elemento raíz (<em>root element</em>).</li> + <li><code><head></head></code> — el elemento {{htmlelement("head")}}. Este elemento actúa como un contenedor de todo aquello que quieres incluir en la página HTML que <em>no</em> es contenido visible por los visitantes de la página. Incluye cosas como palabras clave ({{Glossary("keyword", "keywords")}}), una descripción de la página que quieres que aparezca en resultados de búsquedas, código CSS para dar estilo al contenido, declaraciones del juego de caracteres, etc.</li> + <li><code><meta charset="utf-8"></code> — {{htmlelement("meta")}}. Este elemento establece el juego de caracteres que tu documento usará en <code>utf-8</code>, que incluye casi todos los caracteres de todos los idiomas humanos. Básicamente, puede manejar cualquier contenido de texto que puedas incluir. No hay razón para no establecerlo, y puede evitar problemas en el futuro.</li> + <li><code><title></title></code> — el elemento {{htmlelement("title")}} establece el título de tu página, que es el título que aparece en la pestaña o en la barra de título del navegador cuando la página es cargada, y se usa para describir la página cuando es añadida a los marcadores o como favorita.</li> + <li><code><body></body></code> — el elemento {{htmlelement("body")}}. Encierra <em>todo</em> el contenido que deseas mostrar a los usuarios web que visiten tu página, ya sea texto, imágenes, videos, juegos, pistas de audio reproducibles, y demás.</li> +</ul> + +<h2 id="Imágenes">Imágenes</h2> + +<p>Presta atención nuevamente al elemento <em>imagen</em> {{htmlelement("img")}}:</p> + +<pre class="notranslate"><img src="images/firefox-icon.png" alt="Mi imagen de prueba"></pre> + +<p>Como ya se dijo antes, incrusta una imagen en la página, en la posición en que aparece. Lo logra a través del atributo <code>src</code> (source), el cual contiene el <em>path (ruta o ubicación)</em> de tu archivo de imagen.</p> + +<p>También se incluye un atributo <code>alt</code> (alternative) el cual contiene un texto que debería describir la imagen, y que podría ser accedido por usuarios que no pueden ver la imagen, quizás porque:</p> + +<ol> + <li>Son ciegos o tienen deficiencias visuales. Los usuarios con impedimentos visuales usualmente utilizan herramientas llamadas <em>Lectores de pantalla (Screen Readers),</em> los cuales les leen el texto contenido en el atributo alt.</li> + <li>Se produjo algún error en el código que impide que la imagen sea cargada. Como ejemplo, modifica deliberadamente la ubicación dentro del atributo <code>src</code> para que este sea incorrecto. Si guardas y recargas la página, deberías ver algo así en lugar de la imagen:</li> +</ol> + +<p><img alt="atributo html" src="https://mdn.mozillademos.org/files/11917/image.png" style="height: 36px; width: 108px;"></p> + +<p>La frase clave acerca del texto alt de arriba es «texto que debería describir la imagen». El texto alt debe proporcionarle al lector la suficiente información como para que este tenga una buena idea de qué muestra la imagen. Por lo que tu texto actual «Mi imagen de prueba» no es para nada bueno. Un texto mucho mejor para el logo de Firefox sería: <em>«El logo de Firefox: un zorro en llamas rodeando la Tierra»</em>.</p> + +<p>Prueba a dar con mejores textos alt para tu imagen.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Descubre más acerca de la accesibilidad en el <a href="/es/docs/Web/Accessibility">módulo de aprendizaje sobre la accesibilidad</a>.</p> +</div> + +<h2 id="Marcado_de_texto">Marcado de texto</h2> + +<p>Esta sección cubrirá algunos de los elementos HTML básicos que usarás para el marcado de texto.</p> + +<h3 id="Encabezados">Encabezados</h3> + +<p>Los elementos de encabezado permiten especificar que ciertas partes del contenido son encabezados, o subencabezados del contenido. De la misma forma que un libro tiene un título principal, y que a su vez puede tener títulos por cada capítulo individual, y subtítulos dentro de ellos, un documento HTML puede tenerlos también. HTML posee seis niveles de encabezados, {{htmlelement("h1")}}–{{htmlelement("h6")}}, aunque probablemente solo llegues a usar 3-4 como mucho:</p> + +<pre class="notranslate"><h1>Mi título principal</h1> +<h2>Mi título de nivel superior</h2> +<h3>Mi subtítulo</h3> +<h4>Mi sub-subtítulo</h4></pre> + +<p>Intenta ahora añadir un título apropiado para tu página HTML, antes de tu elemento {{htmlelement("img")}}.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: verás que el encabezamiento de nivel 1 tiene un estilo implícito. No utilices elementos de encabezado para hacer el texto más grande o más oscuro, porque este elemento se utiliza por <a href="/es/docs/Learn/Accessibility/HTML#Contenido_del_texto">accesibilidad</a> y otras <a href="/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#¿Por_qué_necesitamos_estructura">razones como el posicionamiento en buscadores</a> (<em>Search Engine Optimization, SEO</em>). Intenta crear una secuencia significativa de encabezados en tus páginas, sin saltarte niveles.</p> +</div> + +<h3 id="Párrafos">Párrafos</h3> + +<p>Como se explicó más arriba, los elementos {{htmlelement("p")}} se utilizan para encerrar párrafos de texto; los usarás frecuentemente para el marcado de contenido de texto regular:</p> + +<pre class="notranslate"><p>Este es un simple parrafo</p></pre> + +<p>Agrega uno o algunos párrafos a tu texto de ejemplo (deberías tenerlo de cuando estudiaste <a href="/es/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like"><em>¿Cuál será la apariencia de tu sitio web?</em></a>), colocados directamente debajo del elemento <img>.</p> + +<h3 id="Listas">Listas</h3> + +<p>Mucho del contenido web está dado por listas, así que HTML tiene elementos especiales para ellas. El marcado de listas se realiza siempre en al menos dos elementos. Los dos tipos de listas más comunes son las listas ordenadas y las desordenadas:</p> + +<ol> + <li><strong>Las listas desordenadas</strong> son aquellas en las que el orden de los items no es relevante, como en una lista de compras. Estas son encerradas en un elemento {{htmlelement("ul")}} (<em>unordered list</em>).</li> + <li><strong>Las listas ordenadas</strong> son aquellas en las que el orden sí es relevante, como en una receta. Estas son encerradas en un elemento {{htmlelement("ol")}} (<em>ordered list</em>).</li> +</ol> + +<p>Cada elemento de la lista se coloca dentro de un elemento {{htmlelement("li")}} <em>(list item</em>).</p> + +<p>Por ejemplo, si quieres transformar parte del siguiente párrafo en una lista:</p> + +<pre class="notranslate"><p>En Mozilla, somos una comunidad de tecnólogos, pensadores, y constructores que trabajan juntos... </p></pre> + +<p>Podrías hacer lo siguiente:</p> + +<pre class="notranslate"><p>En Mozilla, somos una comunidad de</p> + +<ul> + <li>tecnólogos</li> + <li>pensadores</li> + <li>constructores</li> +</ul> + +<p>trabajando juntos... </p></pre> + +<p>Intenta agregar una lista ordenada o desordenada en tu página de ejemplo<strong>.</strong></p> + +<h2 id="Vínculos">Vínculos</h2> + +<p>Los vínculos o enlaces son muy importantes —son los que hacen de la web, la web—. Para implementar un vínculo, necesitas usar un vínculo simple — {{htmlelement("a")}} — la <em>a</em> es la abreviatura de la palabra inglesa «anchor» («<em>ancla</em>»). Para convertir algún texto dentro de un párrafo en un vínculo, sigue estos pasos:</p> + +<ol> + <li>Elige algún texto. Nosotros elegimos «Manifesto Mozilla».</li> + <li>Encierra el texto en un elemento <a>, así: + <pre class="notranslate"><a>Manifesto Mozilla</a></pre> + </li> + <li>Proporciónale al elemento <a> un atributo href, así: + <pre class="notranslate"><a href="">Manifesto Mozilla</a></pre> + </li> + <li>Completa el valor de este atributo con la dirección web con la que quieras conectar al vínculo: + <pre class="notranslate"><a href="https://www.mozilla.org/es-AR/about/manifesto/">Manifesto Mozilla</a></pre> + </li> +</ol> + +<p>Podrías obtener resultados inesperados si al comienzo de la dirección web omites la parte <code>https://</code> o <code>http://</code> llamada <em>protocolo</em>. Así que luego del marcado del vínculo, haz clic en él para asegurarte que te dirige a la dirección deseada.</p> + +<div class="blockIndicator note"> +<p><code>href</code> podría parecer, en principio, una opción un tanto oscura para un nombre de atributo. Si tienes problemas para recordarla, recuerda que se refiere a <em><strong>h</strong>ypertext <strong>ref</strong>erence</em> (referencia de hipertexto).</p> +</div> + +<p>Ahora agrega un vínculo a tu página, si es que aún no lo hiciste.</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Si lograste seguir todas las instrucciones de este artículo, deberías terminar con una página que se vea así (también puedes <a href="http://mdn.github.io/beginner-html-site/">verla aquí</a>):<br> + <br> + <img alt="Una captura de pantalla de la página web que muestra el logo de Firefox, un encabezado que dice «mozilla es genial» y dos párrafos de texto de relleno." src="https://mdn.mozillademos.org/files/9351/finished-test-page-small.png" style="display: block; height: 838px; margin: 0px auto; width: 716px;"></p> + +<p>Si te estancas en algún paso, puedes comparar tu trabajo con el <a href="https://github.com/mdn/beginner-html-site/blob/gh-pages/index.html">código de ejemplo terminado</a> en Github.</p> + +<p>Aquí realmente solo has rasguñado la superficie de HTML. Para aprender más, ve a la <a href="/es/Learn/HTML">página de Aprendizaje HTML</a>.</p> + +<p>{{PreviousMenuNext("Learn/Getting_started_with_the_web/Dealing_with_files", "Learn/Getting_started_with_the_web/CSS_basics","Learn/Getting_started_with_the_web")}}</p> diff --git a/files/es/learn/getting_started_with_the_web/index.html b/files/es/learn/getting_started_with_the_web/index.html new file mode 100644 index 0000000000..05cadcde6c --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/index.html @@ -0,0 +1,68 @@ +--- +title: Primeros pasos en la Web +slug: Learn/Getting_started_with_the_web +tags: + - CSS + - Diseño + - Guía + - HTML + - Index + - Novato + - Principiante + - edición + - editor + - 'l10n:priority' + - teoria + - Índice +translation_of: Learn/Getting_started_with_the_web +--- +<div>{{LearnSidebar}}</div> + +<div class="summary"> +<p><em>Introducción a la Web</em> es una serie concisa que te presenta los aspectos prácticos del desarrollo web. Configurarás las herramientas que necesitas para construir una sencilla página web y publicar tu propio código.</p> +</div> + +<h2 id="La_historia_de_tu_primer_sitio_web">La historia de tu primer sitio web</h2> + +<p>Es mucho trabajo crear un sitio web profesional, así que si eres nuevo en el desarrollo web, te animamos a que empieces poco a poco. No crearás otro Facebook de inmediato, pero no es difícil tener tu propio sitio web sencillo en línea, así que comenzaremos por ahí.</p> + +<p>Al trabajar en orden a través de los artículos que se enumeran a continuación, pasarás de la nada a tener tu primera página web en línea. ¡Comencemos nuestro viaje!</p> + +<h3 id="web.linkesdocsLearnGetting_started_with_the_webInstalling_basic_softwareInstalación_de_software_básico">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Installing_basic_software","Instalación de software básico")}}</h3> + +<p>Cuando se trata de herramientas para crear un sitio web, hay mucho para elegir. Si recién estás comenzando, es posible que te sientas confundido por la variedad de editores de código, marcos de desarrollo y herramientas de prueba que existen. En {{web.link("/es/docs/Learn/Getting_started_with_the_web/Installing_basic_software", "Instalación de software básico")}}, te mostramos paso a paso cómo instalar solo el software que necesitas para comenzar un desarrollo web básico.</p> + +<h3 id="web.linkesdocsLearnGetting_started_with_the_webWhat_will_your_website_look_like¿Cuál_será_la_apariencia_de_tu_sitio_web">{{web.link("/es/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like","¿Cuál será la apariencia de tu sitio web?")}}</h3> + +<p>Antes de comenzar a escribir el código para tu sitio web, primero lo debes planificar. ¿Qué información estás mostrando?, ¿qué fuentes y colores estás usando?, en {{web.link("/es/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like", "¿cuál será la apariencia de tu sitio web?")}}, describimos un método simple que puedes seguir para planificar el contenido y modelado de tu sitio.</p> + +<h3 id="web.linkesdocsLearnGetting_started_with_the_webDealing_with_filesManejo_de_archivos">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Dealing_with_files","Manejo de archivos")}}</h3> + +<p>Un sitio web consta de muchos archivos: texto del contenido, código, hojas de estilo, contenido multimedia, etc. Cuando estás creando un sitio web, necesitas ensamblar estos archivos en una estructura sensata y asegurarte de que se puedan comunicar entre sí. {{web.link("/es/docs/Learn/Getting_started_with_the_web/Dealing_with_files", "Manejo de archivos")}} explica cómo configurar una estructura de archivos sensible para tu sitio web y qué problemas debes tener en cuenta.</p> + +<h3 id="web.linkesdocsLearnGetting_started_with_the_webHTML_basicsConceptos_básicos_de_HTML">{{web.link("/es/docs/Learn/Getting_started_with_the_web/HTML_basics","Conceptos básicos de HTML")}}</h3> + +<p>El lenguaje de marcado de hipertexto (HTML) es el código que utilizas para estructurar tu contenido web y darle significado y propósito. Por ejemplo, ¿mi contenido es un conjunto de párrafos o una lista de viñetas?, ¿tengo imágenes insertadas en mi página?, ¿tengo una tabla de datos?; Sin abrumarte, {{web.link("/es/docs/Learn/Getting_started_with_the_web/HTML_basics", "conceptos básicos de HTML")}} proporciona suficiente información para familiarizarte con HTML.</p> + +<h3 id="web.linkesdocsLearnGetting_started_with_the_webCSS_basicsConceptos_básicos_de_CSS">{{web.link("/es/docs/Learn/Getting_started_with_the_web/CSS_basics","Conceptos básicos de CSS")}}</h3> + +<p>Hojas de estilo en cascada (CSS) es el código que utilizas para aplicar estilo a tu sitio web. Por ejemplo, ¿desea que el texto sea negro o rojo?, ¿dónde se debe dibujar el contenido en la pantalla?, ¿qué imágenes de fondo y colores se deben utilizar para decorar tu sitio web?, {{web.link("/es/docs/Learn/Getting_started_with_the_web/CSS_basics", "Conceptos básicos de CSS")}} te indica lo que necesitas para empezar.</p> + +<h3 id="web.linkesdocsLearnGetting_started_with_the_webJavaScript_basicsConceptos_básicos_de_JavaScript">{{web.link("/es/docs/Learn/Getting_started_with_the_web/JavaScript_basics","Conceptos básicos de JavaScript")}}</h3> + +<p>JavaScript es el lenguaje de programación que utilizas para agregar funciones interactivas a tu sitio web. Algunos ejemplos podrían ser juegos, cosas que suceden cuando se presionan botones o se ingresan datos en formularios, efectos de estilo dinámico, animación y mucho más. {{web.link("/es/docs/Learn/Getting_started_with_the_web/JavaScript_basics", "Conceptos básicos de JavaScript")}} te da una idea de lo que es posible con este interesante lenguaje y cómo empezar.</p> + +<h3 id="web.linkesdocsLearnGetting_started_with_the_webPublishing_your_websitePublicar_tu_sitio_web">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Publishing_your_website","Publicar tu sitio web")}}</h3> + +<p>Una vez que hayas terminado de escribir el código y organizado los archivos que componen tu sitio web, lo debes poner todo en línea para que la gente lo pueda encontrar. {{web.link("/es/docs/Learn/Getting_started_with_the_web/Publishing_your_website", "Publica tu código de ejemplo")}} describe cómo publicar tu código de ejemplo en línea con el mínimo esfuerzo.</p> + +<h3 id="web.linkesdocsLearnGetting_started_with_the_webHow_the_Web_worksCómo_funciona_la_web">{{web.link("/es/docs/Learn/Getting_started_with_the_web/How_the_Web_works","Cómo funciona la web")}}</h3> + +<p>Cuando accedes a tu sitio web favorito, suceden muchas cosas complicadas en segundo plano que quizás no conozcas. {{web.link("/es/docs/Learn/Getting_started_with_the_web/How_the_Web_works", "Cómo funciona la web")}} describe lo que sucede cuando ves una página web en tu dispositivo favorito.</p> + +<h2 id="Ve_también">Ve también</h2> + +<ul> + <li><a href="https://www.youtube.com/playlist?list=PLo3w8EB99pqLEopnunz-dOOBJ8t-Wgt2g">La web desmitificada</a>: Una gran serie de videos que explican los fundamentos de la web, dirigida a completamente novatos en el desarrollo web. Creada por <a href="https://twitter.com/JeremiePat">Jérémie Patonnier</a>.</li> + <li>{{web.link("/es/docs/Learn/Getting_started_with_the_web/The_web_and_web_standards", "La web y sus estándares")}}: Este artículo proporciona algunos útiles antecedentes sobre la web: cómo surgió, qué son las tecnologías web estándar, cómo trabajan juntas, por qué "desarrollador web" es una gran carrera para elegir y qué tipo de mejores prácticas aprenderás a través del curso.</li> +</ul> diff --git a/files/es/learn/getting_started_with_the_web/instalacion_de_software_basico/index.html b/files/es/learn/getting_started_with_the_web/instalacion_de_software_basico/index.html new file mode 100644 index 0000000000..84ffdcf666 --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/instalacion_de_software_basico/index.html @@ -0,0 +1,83 @@ +--- +title: Instalación de software básico +slug: Learn/Getting_started_with_the_web/Instalacion_de_software_basico +tags: + - Aprender + - Configuración + - Herramientas + - Navegadores + - Novato + - Principiantes + - aprende + - buscador + - editor de textos + - instalar + - 'l10n:priority' +translation_of: Learn/Getting_started_with_the_web/Installing_basic_software +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/Getting_started_with_the_web/What_will_your_website_look_like", "Learn/Getting_started_with_the_web")}}</div> + +<div class="summary"> +<p>La <em>Instalación de software básico</em>, te muestra las herramientas que necesitas para hacer el desarrollo web simple, y la forma de instalarlas correctamente.</p> +</div> + +<h2 id="¿Qué_herramientas_usan_los_profesionales">¿Qué herramientas usan los profesionales?</h2> + +<ul> + <li><strong>Una computadora</strong>. Tal vez esto suena obvio para algunas personas, pero habrá quien esté leyendo este artículo desde el móvil o una computadora de biblioteca. Para el desarrollo web serio, es mejor invertir en un equipo de escritorio o portátil con Windows, Mac o Linux.</li> + <li><strong>Un editor de texto</strong>, para escribir código. Puedes usar un editor de texto libre (ej. <a href="http://brackets.io/">Brackets</a>, <a href="https://atom.io/">Atom</a>, <a href="https://notepad-plus-plus.org/">Notepad++</a>, <a href="https://www.sublimetext.com/">Sublime Text</a>, <a href="https://www.gnu.org/software/emacs/">GNU Emacs</a>, <a href="https://www.vim.org/">VIM</a>, <a href="https://code.visualstudio.com/">Visual Studio Code</a>, <a href="https://www.jetbrains.com/webstorm/">WebStorm</a>) o un editor híbrido (<a href="https://www.adobe.com/products/dreamweaver.html">Dreamweaver</a>). Los editores de documentos de oficina no son adecuados para esto, pues dependen de elementos ocultos que interfieren con los motores de renderizado usados por los navegadores.</li> + <li><strong>Navegadores web</strong>, para probar el código. Actualmente los navegadores más usados son <a href="https://www.mozilla.org/en-US/firefox/new/">Firefox</a>, <a href="https://www.google.com/chrome/browser/">Chrome</a>, <a href="http://www.opera.com/">Opera</a>, <a href="https://www.apple.com/safari/">Safari</a>, <a href="https://vivaldi.com/es/">Vivaldi</a>, <a href="http://windows.microsoft.com/en-us/internet-explorer/download-ie">Internet Explorer</a> y <a href="https://www.microsoft.com/en-us/windows/microsoft-edge">Microsoft Edge</a>. También debes comprobar cómo funciona tu web en dispositivos móviles y en cualquier navegador antiguo que tu público objetivo pueda estar usando aún (tal como IE 6–8.)</li> + <li><strong>Un editor de gráficos o imágenes</strong>, como <a href="http://www.gimp.org/">GIMP</a>, <a href="http://www.getpaint.net/">Paint.NET</a> o <a href="https://www.adobe.com/products/photoshop.html">Photoshop</a>, para crear imágenes para tus páginas web.</li> + <li><strong>Un sistema de control de versiones</strong>, para administrar archivos en servidores, colaborar en un proyecto con un equipo, compartir código y recursos, y evitar conflictos de edición. Hoy en día <a href="http://git-scm.com/">Git</a> es el sistema de control de versiones más popular y el servicio de alojamiento de código <a href="https://github.com/">GitHub</a>, basado en Git, también es muy popular.</li> + <li><strong>Un programa de FTP</strong>, para cargar páginas web en un servidor para el público (Git está reemplazando cada vez más a FTP para ese fin). Hay un montón de estos programas disponibles incluyendo <a href="https://cyberduck.io/">Cyberduck</a>, <a href="http://fetchsoftworks.com/">Fetch</a> y <a href="https://filezilla-project.org/">FileZilla</a>.</li> + <li><strong>Un sistema de automatización</strong>, como <a href="http://gruntjs.com/">Grunt</a> o <a href="http://gulpjs.com/">Gulp</a> para realizar tareas repetitivas de forma automática, por ejemplo minimización de código y ejecución de pruebas.</li> + <li>Bibliotecas, marcos de desarrollo (<code>frameworks</code>), etc., para acelerar la escritura de funciones comunes. Una biblioteca tiende a ser un archivo JavaScript o CSS existente que proporciona una funcionalidad lista para usar para que la utilices en tu código. Un framework tiende a llevar esta idea más allá, ofreciendo un sistema completo con alguna sintaxis personalizada para que puedas escribir una aplicación web basada en él.</li> + <li>¡Muchas más herramientas!</li> +</ul> + +<h2 id="Ahora_mismo_¿qué_herramientas_necesitas_realmente">Ahora mismo: ¿qué herramientas necesitas realmente?</h2> + +<p>Esto parece una lista espeluznante pero, afortunadamente, puedes comenzar a trabajar en el desarrollo web sin saber nada de la mayoría de estas herramientas. En este artículo solo tendrás que configurar lo mínimo: un editor de texto y algunos navegadores web modernos.</p> + +<h3 id="Instalación_de_un_editor_de_texto">Instalación de un editor de texto</h3> + +<p>Probablemente ya tengas un editor de texto básico instalado en tu computadora. De manera predeterminada Windows incluye el {{Interwiki("wikipedia", "Bloc de notas")}} y OS X viene con {{Interwiki("wikipedia", "TextEdit")}}. Las <em>distros</em> (versiones) de Linux varían: Ubuntu viene con {{Interwiki("wikipedia", "Gedit")}}; distribuciones basadas en KDE suelen traer <a href="http://kate-editor.org/">Kate</a> o <a href="https://es.wikipedia.org/wiki/KWrite">Kwrite</a>.</p> + +<p>Para el desarrollo Web, probablemente hay cosas mejores que el Bloc de notas o TextEdit. Una recomendación puede ser empezar con <a href="http://brackets.io">Brackets</a>, un editor gratuito que ofrece vistas previas en vivo y sugerencias de código.</p> + +<h3 id="Instalación_de_navegadores_web_modernos">Instalación de navegadores web modernos</h3> + +<p>Por ahora, solo tendrás que instalar un par de navegadores web de escritorio para poner a prueba tu código. Selecciona tu sistema operativo y pulsa los enlaces pertinentes para descargar los instaladores de tus navegadores preferidos:</p> + +<ul> + <li>Linux: <a href="https://www.mozilla.org/es-ES/firefox/new/">Firefox</a>, <a href="https://www.google.com/chrome/browser/">Chrome</a>, <a href="http://www.opera.com/es/">Opera</a>, <a href="https://vivaldi.com/es/">Vivaldi</a>.</li> + <li>Windows: <a href="https://www.mozilla.org/es-ES/firefox/new/">Firefox</a>, <a href="https://www.google.com/chrome/browser/">Chrome</a>, <a href="http://www.opera.com/es/">Opera</a>, <a href="https://vivaldi.com/es/">Vivaldi</a>, <a href="http://windows.microsoft.com/en-us/internet-explorer/download-ie">Internet Explorer</a> (si tienes Windows 8 o superior, puedes instalar IE 10 o posterior, de lo contrario, deberías instalar un navegador alternativo).</li> + <li>Mac: <a href="https://www.mozilla.org/es-ES/firefox/new/">Firefox</a>, <a href="https://www.google.com/chrome/browser/">Chrome</a>, <a href="http://www.opera.com/es/">Opera</a>, <a href="https://vivaldi.com/es/">Vivaldi</a>, <a href="https://www.apple.com/safari/">Safari</a> (Safari de manera predeterminada viene con iOS y OS X)</li> +</ul> + +<p>Antes de continuar, deberías instalar al menos dos de estos navegadores y tenerlos disponibles para pruebas.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Internet Explorer no es compatible con algunas funciones web modernas y es posible que no puedas ejecutar tu proyecto. Por lo general, no necesitas preocuparte por hacer que tus proyectos web sean compatibles con él, ya que muy pocas personas todavía lo usan; ciertamente, no te preocupes demasiado por él mientras aprendes. En ocasiones, es posible que te encuentres con un proyecto que requiera soporte.</p> +</div> + +<h3 id="Instalación_de_un_servidor_web_local">Instalación de un servidor web local</h3> + +<p>Algunos ejemplos necesitarás ejecutarlos a través de un servidor web para que funcionen exitosamente. Puedes encontrar cómo hacer esto en {{web.link("/es/docs/Learn/Common_questions/set_up_a_local_testing_server", "¿Cómo se configura un servidor de prueba local?")}}</p> + +<p>{{NextMenu("Learn/Getting_started_with_the_web/What_will_your_website_look_like", "Learn/Getting_started_with_the_web")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li id="Instalacion_de_software_basico">{{web.link("/es/Learn/Getting_started_with_the_web/Instalacion_de_software_basico", "Instalación de software básico")}}</li> + <li id="Como_se_vera_tu_sitio_web">{{web.link("/es/Learn/Getting_started_with_the_web/What_will_your_website_look_like", "¿Cómo se verá tu sitio web?")}}</li> + <li id="Manejo_de_archivos">{{web.link("/es/Learn/Getting_started_with_the_web/Manejando_los_archivos", "Manejo de archivos")}}</li> + <li id="Conceptos_basicos_de_HTML">{{web.link("/es/Learn/Getting_started_with_the_web/HTML_basics", "Conceptos básicos de HTML")}}</li> + <li id="Conceptos_basicos_de_CSS">{{web.link("/es/Learn/Getting_started_with_the_web/CSS_basics", "Conceptos básicos de CSS")}}</li> + <li id="Conceptos_basicos_de_JavaScript">{{web.link("/es/Learn/Getting_started_with_the_web/JavaScript_basics", "Conceptos básicos de JavaScript")}}</li> + <li id="Publicar_tu_sitio_web">{{web.link("/es/Learn/Getting_started_with_the_web/Publishing_your_website", "Publicar tu sitio web")}}</li> + <li id="Como_funciona_la_web">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Cómo_funciona_la_Web", "Cómo funciona la Web")}}</li> +</ul> diff --git a/files/es/learn/getting_started_with_the_web/javascript_basics/index.html b/files/es/learn/getting_started_with_the_web/javascript_basics/index.html new file mode 100644 index 0000000000..78fa13eccb --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/javascript_basics/index.html @@ -0,0 +1,456 @@ +--- +title: Fundamentos de JavaScript +slug: Learn/Getting_started_with_the_web/JavaScript_basics +tags: + - Aprender + - CodingScripting + - JavaScript + - Novato + - Principiante + - Web + - 'l10n:priority' +translation_of: Learn/Getting_started_with_the_web/JavaScript_basics +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext( "Learn/Getting_started_with_the_web/CSS_basics","Learn/Getting_started_with_the_web/Publishing_your_website","Learn/Getting_started_with_the_web")}}</div> + +<div class="summary"> +<p>JavaScript es el lenguaje de programación que debes usar para añadir características interactivas a tu sitio web, (por ejemplo, juegos, eventos que ocurren cuando los botones son presionados o los datos son introducidos en los formularios, efectos de estilo dinámicos, animación, y mucho más). Este artículo te ayudará a comenzar con este lenguaje extraordinario y te dará una idea de qué es posible hacer con él.</p> +</div> + +<h2 id="¿Qué_es_JavaScript_realmente">¿Qué es JavaScript realmente?</h2> + +<p>{{Glossary("JavaScript")}} es un robusto lenguaje de programación que se puede aplicar a un documento {{Glossary("HTML")}} y usarse para crear interactividad dinámica en los sitios web. Fue inventado por Brendan Eich, cofundador del proyecto Mozilla, Mozilla Foundation y la Corporación Mozilla.</p> + +<p>Puedes hacer casi cualquier cosa con JavaScript. Puedes empezar con pequeñas cosas como carruseles, galerías de imágenes, diseños fluctuantes, y respuestas a las pulsaciones de botones. Con más experiencia, serás capaz de crear juegos, animaciones 2D y gráficos 3D, aplicaciones integradas basadas en bases de datos ¡y mucho más!</p> + +<p>JavaScript por sí solo es bastante compacto aunque muy flexible, y los desarrolladores han escrito gran cantidad de herramientas encima del núcleo del lenguaje JavaScript, desbloqueando una gran cantidad de funcionalidad adicional con un mínimo esfuerzo. Esto incluye:</p> + +<ul> + <li>Interfaces de Programación de Aplicaciones del Navegador ({{Glossary("API","APIs")}}) — APIs construidas dentro de los navegadores que ofrecen funcionalidades como crear dinámicamente contenido HTML y establecer estilos CSS, hasta capturar y manipular un vídeo desde la cámara web del usuario, o generar gráficos 3D y muestras de sonido.</li> + <li>APIs de terceros, que permiten a los desarrolladores incorporar funcionalidades en sus sitios de otros proveedores de contenidos como Twitter o Facebook.</li> + <li>Marcos de trabajo y librerías de terceros que puedes aplicar a tu HTML para que puedas construir y publicar rápidamente sitios y aplicaciones.</li> +</ul> + +<p>Ya que se supone que este artículo es solo una introducción ligera a JavaScript, la intención no es confundirte en esta etapa hablando en detalle sobre cuál es la diferencia entre el núcleo del lenguaje JavaScript y las diferentes herramientas listadas arriba. Puedes aprender todo eso en detalle más tarde, en el <a href="/es/docs/Learn/JavaScript">Área de Aprendizaje en MDN</a>, y en el resto de MDN.</p> + +<p>Debajo se presentan algunos aspectos del núcleo del lenguaje y también jugarás con unas pocas características de la API del navegador. ¡Diviértete!</p> + +<h2 id="Ejemplo_«¡Hola_Mundo!»">Ejemplo «<em>¡Hola Mundo!</em>»</h2> + +<p>La sección de arriba suena realmente emocionante, y debería serlo. JavaScript es una de las tecnologías web más emocionantes, y cuando comiences a ser bueno en su uso, tus sitios web entrarán en una nueva dimensión de energía y creatividad.</p> + +<p>Sin embargo, sentirse cómodo con JavaScript es un poco más difícil que sentirse cómodo con HTML y CSS. Deberás comenzar poco a poco y continuar trabajando en pasos pequeños y consistentes. Para comenzar, mostraremos cómo añadir JavaScript básico a tu página, creando un «<em>¡Hola Mundo!</em>» de ejemplo (<a href="https://es.wikipedia.org/wiki/Hola_mundo">el estándar en los ejemplos básicos de programación</a>).</p> + +<div class="warning"> +<p><strong>Importante</strong>: si no has venido siguiendo el resto de nuestro curso, <a href="https://github.com/mdn/beginner-html-site-styled/archive/gh-pages.zip">descarga este código de ejemplo</a> y úsalo como punto de partida.</p> +</div> + +<ol> + <li>Primero, ve a tu sitio de pruebas y crea una carpeta llamada <code>scripts</code>. Luego, dentro de la nueva carpeta de scripts, crea un nuevo archivo llamado <code>main.js</code> y guárdalo.</li> + <li>A continuación, abre tu archivo <code>index.html</code> e introduce el siguiente código en una nueva línea, justo antes de la etiqueta de cierre <code></body></code>: + <pre class="brush: html notranslate"><font><font><script src="scripts/main.js"></script></font></font></pre> + </li> + <li>Esto hace básicamente el mismo trabajo que el elemento {{htmlelement("link")}} para CSS: aplica el código JavaScript a la página, para que pueda actuar sobre el HTML (y CSS, o cualquier cosa en la página).</li> + <li>Ahora añade el siguiente código al archivo <code>main.js</code>: + <pre class="brush: js notranslate">const miTitulo = document.querySelector('h1'); +miTitulo.textContent = '¡Hola mundo!';</pre> + </li> + <li>Finalmente, asegúrate de que has guardado los archivos HTML y JavaScript, y abre <code>index.html</code> en el navegador. Deberías ver algo así: <img alt="" src="https://mdn.mozillademos.org/files/9543/hello-world.png" style="display: block; height: 236px; margin: 0px auto; width: 806px;"></li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: la razón por la que has puesto el elemento {{htmlelement("script")}} casi al final del documento HTML es porque <strong>el navegador carga el HTML en el orden en que aparece en el archivo</strong>.</p> + +<p>Si se cargara primero JavaScript y se supone que debe afectar al HTML que tiene debajo, podría no funcionar, ya que ha sido cargado antes que el HTML sobre el que se supone debe trabajar. Por lo tanto, colocar el JavaScript cerca del final de la página es normalmente la mejor estrategia. Para aprender más sobre enfoques alternativos, mira <a href="/es/docs/Learn/JavaScript/First_steps/Qué_es_JavaScript#Estrategias_de_carga_de_scripts">Estrategias de carga de scripts</a>.</p> +</div> + +<h3 id="¿Qué_ha_ocurrido">¿Qué ha ocurrido?</h3> + +<p>El texto del título ha sido cambiado por <em>¡Hola mundo!</em> usando JavaScript. Hiciste esto primero usando la función <code>{{domxref("Document.querySelector", "querySelector()")}}</code> para obtener una referencia al título y almacenarla en una variable llamada <code>miTitulo</code>. Esto es muy similar a lo que hiciste con CSS usando selectores —quieres hacer algo con un elemento, así que tienes que seleccionarlo primero—.</p> + +<p>Después de eso, estableciste el valor de la propiedad {{domxref("Node.textContent", "textContent")}} de la variable <code>miTitulo</code> (que representa el contenido del título) como <em>¡Hola mundo!</em></p> + +<div class="note"> +<p><strong>Nota</strong>: Las dos características que has utilizado en este ejercicio forman parte de la API del <a href="/es/docs/Web/API/Document_Object_Model">Modelo de Objeto de Documento (DOM)</a>, que tiene la capacidad de manipular documentos.</p> +</div> + +<h2 id="Curso_intensivo_de_fundamentos_del_lenguaje">Curso intensivo de fundamentos del lenguaje</h2> + +<p>Ahora se explicarán algunas de las funciones básicas del lenguaje JavaScript para que puedas comprender mejor cómo funciona todo. Mejor aún, estas características son comunes para todos los lenguajes de programación. Si puedes entender esos fundamentos, deberías ser capaz de comenzar a programar en casi cualquier cosa.</p> + +<div class="warning"> +<p><strong>Importante</strong>: en este artículo, trata de introducir las líneas de código de ejemplo en la consola de tu navegador para ver lo que sucede. Para más detalles sobre consolas JavaScript, mira <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">Descubre las herramientas de desarrollo de los navegadores</a>.</p> +</div> + +<h3 id="Variables">Variables</h3> + +<p>Las {{Glossary("Variable", "Variables")}} son contenedores en los que puedes almacenar valores. Primero debes declarar la variable con la palabra clave <code><a href="/es/docs/Web/JavaScript/Reference/Statements/var">var</a></code> (menos recomendado) o <code><a href="/es/docs/Web/JavaScript/Reference/Statements/let">let</a></code>, seguida del nombre que le quieras dar. Se recomienda más el uso de <code>let</code> que de <code>var</code> (más adelante se profundiza un poco sobre esto):</p> + +<pre class="brush: js notranslate">let nombreDeLaVariable;</pre> + +<div class="note"> +<p><strong>Nota</strong>: todas las líneas en JS deben acabar en punto y coma (;) para indicar que es ahí donde termina la declaración. Si no los incluyes puedes obtener resultados inesperados. Sin embargo, algunas personas creen que es una buena práctica tener punto y coma al final de cada declaración. Hay otras reglas para cuando se debe y no se debe usar punto y coma. Para más detalles, vea <a href="http://news.codecademy.com/your-guide-to-semicolons-in-javascript/">Guía del punto y coma en JavaScript</a> (en inglés).</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: puedes llamar a una variable con casi cualquier nombre, pero hay algunas restricciones (ver <a href="/es/docs/Web/JavaScript/Guide/Grammar_and_Types#Variables">este artículo sobre las reglas existentes</a>). Si no estás seguro, puedes <a href="https://mothereff.in/js-variables">comprobar el nombre de la variable</a> para ver si es válido.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: JavaScript distingue entre mayúsculas y minúsculas. <code>miVariable</code> es una variable distinta a <code>mivariable</code>. Si estás teniendo problemas en tu código, revisa las mayúsculas y minúsculas.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: para más detalles sobre la diferencia entre <code>var</code> y <code>let</code>, vea <a href="/es/docs/Learn/JavaScript/First_steps/Variables#Diferencia_entre_var_y_let">Diferencia entre var y let</a>.</p> +</div> + +<p>Tras declarar una variable, puedes asignarle un valor:</p> + +<pre class="brush: js notranslate">nombreDeLaVariable = 'Bob';</pre> + +<p>Puedes hacer las dos cosas en la misma línea si lo necesitas:</p> + +<pre class="brush: js notranslate">let nombreDeLaVariable = 'Bob';</pre> + +<p>Puedes obtener el valor de la variable llamándola por su nombre:</p> + +<pre class="brush: js notranslate">nombreDeLaVariable;</pre> + +<p>Después de haberle dado un valor a la variable, puedes volver a cambiarlo:</p> + +<pre class="brush: js notranslate">let nombreDeLaVariable = 'Bob'; +nombreDeLaVariable = 'Steve';</pre> + +<p>Advierte que las variables tienen distintos <a href="/es/docs/Web/JavaScript/Data_structures">tipos de datos</a>:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="row">Variable</th> + <th scope="col">Explicación</th> + <th scope="col">Ejemplo</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">{{Glossary("String","String")}}</th> + <td>Esto es una secuencia de texo conocida como cadena. Para indicar que la variable es una cadena, debes escribirlo entre comillas.</td> + <td><code>let miVariable = 'Bob';</code></td> + </tr> + <tr> + <th scope="row">{{Glossary("Number")}}</th> + <td> + <p>Esto es un número. Los números no tienen comillas.</p> + </td> + <td><code>let miVariable = 10;</code></td> + </tr> + <tr> + <th scope="row">{{Glossary("Boolean")}}</th> + <td>Tienen valor verdadero/falso. <code>true</code>/<code>false</code> son palabras especiales en JS, y no necesitan comillas.</td> + <td><code>let miVariable = true;</code></td> + </tr> + <tr> + <th scope="row">{{Glossary("Array")}}</th> + <td>Una estructura que te permite almacenar varios valores en una sola referencia.</td> + <td><code>let miVariable = [1,'Bob','Steve',10];</code><br> + Llama a cada miembro del array así: <code>miVariable[0]</code>, <code>miVariable[1]</code>, etc.</td> + </tr> + <tr> + <th scope="row">{{Glossary("Object")}}</th> + <td> + <p>Básicamente cualquier cosa. Todo en JavaScript es un objeto y puede ser almacenado en una variable. Mantén esto en mente mientras aprendes.</p> + </td> + <td><code>let miVariable = document.querySelector('h1');</code><br> + Todos los ejemplos anteriores también.</td> + </tr> + </tbody> +</table> + +<p>Entonces, ¿para qué necesitamos las variables? Las variables son necesarias para hacer cualquier cosa interesante en programación. Si los valores no pudieran cambiar, entonces no podrías hacer nada dinámico, como personalizar un mensaje de bienvenida de un usuario que visita tu página, cambiar la imagen que se muestra en una galería de imágenes, etc.</p> + +<h3 id="Comentarios">Comentarios</h3> + +<p>Puedes escribir comentarios entre el código JavaScript, igual que puedes en CSS. El navegador ignora el texto marcado como comentario. En JavaScript, los comentarios de una sola línea se escriben así:</p> + +<pre class="brush: js notranslate">// Esto es un comentario</pre> + +<p>Pero también puedes escribir comentarios en más de una línea, igual que en CSS:</p> + +<pre class="brush: js notranslate">/* +Esto es un comentario +de varias líneas. +*/</pre> + +<h3 id="Operadores">Operadores</h3> + +<p>Un {{Glossary("operator", "operador")}} es básicamente un símbolo matemático que puede actuar sobre dos valores (o variables) y producir un resultado. En la tabla de abajo aparecen los operadores más simples, con algunos ejemplos para probarlos en la consola del navegador.</p> + +<table class="standard-table" style="height: 679px; width: 702px;"> + <thead> + <tr> + <th scope="row">Operador</th> + <th scope="col">Explicación</th> + <th scope="col">Símbolo(s)</th> + <th scope="col">Ejemplo</th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">Suma/concatena</th> + <td>Se usa para sumar dos números, o juntar dos cadenas en una.</td> + <td><code>+</code></td> + <td><code>6 + 9;<br> + "Hola " + "mundo!";</code></td> + </tr> + <tr> + <th scope="row">Resta, multiplicación, división</th> + <td>Estos hacen lo que esperarías que hicieran en las matemáticas básicas.</td> + <td><code>-</code>, <code>*</code>, <code>/</code></td> + <td><code>9 - 3;<br> + 8 * 2; // La multiplicación en JS es un asterisco<br> + 9 / 3;</code></td> + </tr> + <tr> + <th scope="row">Operador de asignación</th> + <td>Los has visto anteriormente: asigna un valor a una variable.</td> + <td><code>=</code></td> + <td><code>let miVariable = 'Bob';</code></td> + </tr> + <tr> + <th scope="row">identidad/igualdad</th> + <td>Comprueba si dos valores son iguales entre sí, y devuelve un valor de <code>true</code>/<code>false</code> (booleano).</td> + <td><code>===</code></td> + <td><code>let miVariable = 3;<br> + miVariable === 4;</code></td> + </tr> + <tr> + <th scope="row">Negación, distinto (no igual)</th> + <td><br> + En ocasiones utilizado con el operador de identidad, la negación es en JS el equivalente al operador lógico NOT — cambia <code>true</code> por <code>false</code> y viceversa.</td> + <td><code>!</code>, <code>!==</code></td> + <td> + <p>La expresión básica es <code>true</code>, pero la comparación devuelve <code>false</code> porque lo hemos negado:</p> + + <p><code>let miVariable = 3;<br> + !miVariable === 3;</code></p> + + <p>Aquí estamos comprobando "<code>miVariable</code> NO es igual a 3". Esto devuelve <code>false</code>, porque <code>miVariable</code> ES igual a 3.</p> + + <p><code><code>let miVariable = 3;</code><br> + miVariable !== 3;</code></p> + </td> + </tr> + </tbody> +</table> + +<p>Hay muchos operadores por explorar, pero con esto será suficiente por ahora. Mira <a href="/es/docs/Web/JavaScript/Reference/Operators">Expresiones y operadores</a> para ver la lista completa.</p> + +<div class="note"> +<p><strong>Nota</strong>: mezclar tipos de datos puede dar lugar a resultados extraños cuando se hacen cálculos, así que asegúrate de que relacionas tus variables correctamente y de que recibes los resultados que esperabas. Por ejemplo, teclea: <code>"3" + "25"</code> en tu consola. ¿Por qué no obtienes lo que esperabas? Porque las comillas convierten los números en "strings" (el término inglés para denominar cadenas de caracteres) y de este modo has acabado con los "strings" concatenados entre sí, y no con los números sumados. Si tecleas: <code>35 + 25</code>, obtendrás el resultado correcto.</p> +</div> + +<h3 id="Condicionales">Condicionales</h3> + +<p>Las condicionales son estructuras de código que permiten comprobar si una expresión devuelve <em>true</em> o no, y después ejecuta un código diferente dependiendo del resultado. La forma de condicional más común es la llamada <code>if... else</code>. Entonces, por ejemplo:</p> + +<pre class="brush: js notranslate">let helado = 'chocolate'; +if (helado === 'chocolate') { + alert('¡Sí, amo el helado de chocolate!'); +} else { + alert('Awwww, pero mi favorito es el de chocolate...'); +}</pre> + +<p>La expresión dentro de <code>if (... )</code> es el criterio — este usa al operador de identidad (descrito arriba) para comparar la variable <code>helado</code> con la cadena <code>chocolate</code> para ver si las dos son iguales. Si esta comparación devuelve <code>true</code>, el primer bloque de código se ejecuta. Si no, ese código se omite y se ejecuta el segundo bloque de código después de la declaración <code>else</code>.</p> + +<h3 id="Funciones">Funciones</h3> + +<p>Las {{Glossary("Function", "funciones")}} son una manera de encapsular una funcionalidad que quieres reutilizar, de manera que puedes llamar esa función con un solo nombre, y no tendrás que escribir el código entero cada vez que la utilices. Ya has visto algunas funciones más arriba, por ejemplo:</p> + +<ol> + <li> + <pre class="brush: js notranslate"><code>let</code> nombreDeLaVariable = document.querySelector('h1');</pre> + </li> + <li> + <pre class="brush: js notranslate">alert('¡Hola!');</pre> + </li> +</ol> + +<p>Estas funciones <code>document.querySelector</code> y <code>alert</code> están integradas en el navegador para poder utilizarlas en cualquier momento.</p> + +<p>Si ves algo que parece un nombre de variable, pero tiene paréntesis —<code>()</code>— al final, probablemente es una función. Las funciones con frecuencia toman {{Glossary("Argument", "argumentos")}} —pedazos de datos que necesitan para hacer su trabajo—. Estos se colocan dentro de los paréntesis, y se separan con comas si hay más de uno.</p> + +<p>Por ejemplo, la función <code>alert()</code> hace aparecer una ventana emergente dentro de la ventana del navegador, pero necesitas asignarle una cadena como argumento para decirle qué mensaje se debe escribir en la ventana emergente.</p> + +<p>Las buenas noticias son que podemos definir nuestras propias funciones —en el siguiente ejemplo escribimos una función simple que toma dos números como argumentos y los multiplica entre sí—:</p> + +<pre class="brush: js notranslate">function multiplica(num1,num2) { + <code>let</code> resultado = num1 * num2; + return resultado; +}</pre> + +<p>Trata de ejecutar la función anterior en la consola. Después trata de usar la nueva función algunas veces, p.ej:</p> + +<pre class="brush: js notranslate">multiplica(4, 7); +multiplica(20, 20); +multiplica(0.5, 3); +</pre> + +<div class="note"> +<p><strong>Nota</strong>: la sentencia <a href="/es/docs/Web/JavaScript/Reference/Statements/return"><code>return</code></a> le dice al navegador que devuelva la variable <code>resultado</code> fuera de la función, para que esté disponible para su uso. Esto es necesario porque las variables definidas dentro de funciones, solo están disponibles dentro de esas funciones. Esto se conoce como «{{Glossary("Scope", "ámbito")}} (<em>scope</em> en inglés) de la variable». Lee más sobre <a href="/es/docs/Web/JavaScript/Guide/Grammar_and_types#%C3%81mbito_de_variable">ámbito o alcance de la variable</a>.</p> +</div> + +<h3 id="Eventos">Eventos</h3> + +<p>Para crear una interacción real en tu sitio web, debes usar eventos. Estos son unas estructuras de código que captan lo que sucede en el navegador, y permite que en respuesta a las acciones que suceden se ejecute un código. El ejemplo más obvio es un clic (<a href="/es/docs/Web/Events/click">click event</a>), que se activa al hacer clic sobre algo. Para demostrar esto, prueba ingresando lo siguiente en tu consola, luego da clic sobre la página actual:</p> + +<pre class="brush: js notranslate">document.querySelector('html').onclick = function() { + alert('¡Ouch! ¡Deja de pincharme!'); +} +</pre> + +<p>Hay muchas maneras de enlazar un evento a un elemento; aquí hemos seleccionado el elemento {{htmlelement("html")}} y le asignamos a su propiedad <code><a href="/es/docs/Web/API/GlobalEventHandlers/onclick">onclick</a></code> una función anónima (función sin nombre) que contiene el código que se ejecutará cuando el evento suceda.</p> + +<p>Nota que</p> + +<pre class="brush: js notranslate">document.querySelector('html').onclick = function(){}; +</pre> + +<p>es equivalente a</p> + +<pre class="brush: js notranslate"><code>let</code> miHTML = document.querySelector('html'); +miHTML.onclick = function(){}; +</pre> + +<p>es solo un modo más corto de escribirlo.</p> + +<h2 id="Sobrecargar_tu_sitio_web_de_ejemplo">Sobrecargar tu sitio web de ejemplo</h2> + +<p>Ahora vas a repasar un poco lo básico de JavaScript. Añadirás un par de funcionalidades a tu sitio para demostrar lo que puedes hacer.</p> + +<h3 id="Añadir_un_cambiador_de_imagen">Añadir un cambiador de imagen</h3> + +<p>En esta sección añadirás otra imagen a tu sitio usando la DOM API y agregarás un poco de código para cambiar entre imágenes al hacer clic.</p> + +<ol> + <li>Primero que todo, busca una imagen que te guste para tu sitio. Asegúrate que sea del mismo tamaño que la primera, o lo más cerca posible.</li> + <li>Guarda tu imagen en tu carpeta <code>images</code>.</li> + <li>Renombra esta imagen «firefox2.png» (sin las comillas).</li> + <li>Ve a tu archivo <code>main.js</code> y agrega el siguiente JavaScript (si tu JavaScript de <em>«Hola Mundo»</em> está aún allí, bórralo). + <pre class="brush: js notranslate"><code>let </code>miImage = document.querySelector('img'); +miImage.onclick = function () { + <code>let </code>miSrc = miImage.getAttribute('src'); + if (miSrc === 'images/firefox-icon.png') { + miImage.setAttribute('src','images/firefox2.png'); + } else { + miImage.setAttribute('src', 'images/firefox-icon.png'); + } +}</pre> + </li> + <li>Guarda todos los archivos y carga <code>index.html</code> en tu navegador. Ahora cuando hagas clic en la imagen, ¡esta debe cambiar por otra!</li> +</ol> + +<p>Esto fue lo que sucedió: se almacena una referencia a tu elemento {{htmlelement("img")}} en la variable <code>miImage</code>. Luego, haces que esta propiedad del manejador de evento <code>onclick</code> de la variable sea igual a una función sin nombre (una función «anónima»). Ahora, cada vez que se haga clic en la imagen:</p> + +<ol> + <li>El código recupera el valor del atributo <code>src</code> de la imagen.</li> + <li>El código usa una condicional para comprobar si el valor <code>src</code> es igual a la ruta de la imagen original: + <ol> + <li>Si es así, el código cambia el valor de <code>src</code> a la ruta de la segunda imagen, forzando a que se cargue la otra imagen en el elemento {{htmlelement("img")}}.</li> + <li>Si no es así (significa que ya fue modificada), se cambiará el valor de <code>src</code> nuevamente a la ruta de la imagen original, regresando a como era en un principio.</li> + </ol> + </li> +</ol> + +<h3 id="Añadir_un_mensaje_de_bienvenida_personalizado">Añadir un mensaje de bienvenida personalizado</h3> + +<p>Ahora añadirás un poco más de código, para cambiar el título de la página o incluir un mensaje personalizado de bienvenida para cuando el usuario ingrese por primera vez. Este mensaje de bienvenida permanecerá luego de que el usuario abandone la página y estará disponible para cuando regrese. Lo guardarás usando <a href="/es/docs/Web/API/Web_Storage_API">Web Storage API</a>. También se incluirá una opción para cambiar el usuario y por lo tanto también el mensaje de bienvenida en cualquier momento que se requiera.</p> + +<ol> + <li>En <code>index.html</code>, agrega el siguiente código antes del elemento {{htmlelement("script")}}: + + <pre class="brush: html notranslate"><button>Cambiar de usuario</button></pre> + </li> + <li>En <code>main.js</code>, agrega el siguiente código al final del archivo, exactamente como está escrito. Esto toma referencia al nuevo botón que se agregó y al título y los almacena en variables: + <pre class="brush: js notranslate"><code>let</code> miBoton = document.querySelector('button'); +<code>let</code> miTitulo = document.querySelector( 'h1');</pre> + </li> + <li>Ahora agrega la siguiente función para poner el saludo personalizado, lo que no causará nada aún, pero arreglarás esto en un momento: + <pre class="brush: js notranslate">function estableceNombreUsuario() { + <code>let</code> miNombre = prompt('Por favor, ingresa tu nombre.'); + localStorage.setItem('nombre', miNombre); + miTitulo.textContent = 'Mozilla es genial,' + miNombre; +}</pre> + La función <code>estableceNombreUsuario()</code> contiene una función <a href="/es/docs/Web/API/Window/prompt"><code>prompt()</code></a>, que crea un cuadro de diálogo como lo hace <code>alert()</code>; la diferencia es que <code>prompt()</code> pide al usuario un dato, y almacena este dato en una variable cuando el botón <strong>Aceptar </strong>del cuadro de diálogo es presionado. En este caso, pedirás al usuario que ingrese su nombre. Luego, llamarás la API <code>localStorage</code>, que nos permite almacenar datos en el navegador y recuperarlos luego. Usarás la función <code>setItem()</code> de localStorage, que crea y almacena un dato en el elemento llamado <code>'nombre'</code>, y coloca este valor en la variable <code>miNombre</code> que contiene el nombre que el usuario ingresó. Finalmente, establecerás el <code>textContent</code> del título a una cadena, más el nombre de usuario recientemente almacenado.</li> + <li>Luego, agregarás este bloque <code>if ... else</code>. Se podría llamar a esto el código de inicialización, como se ha establecido para cuando carga la app por primera vez: + <pre class="brush: js notranslate">if (!localStorage.getItem('nombre')) { + estableceNombreUsuario(); +} +else { + <code>let</code> nombreAlmacenado = localStorage.getItem('nombre'); + miTitulo.textContent = 'Mozilla es genial,' + nombreAlmacenado; +}</pre> + La primera línea de este bloque usa el operador de negación (NO lógico representado por <code>!</code>) para comprobar si el elemento <code>'nombre'</code> existe. Si no existe, la función <code>estableceNombreUsuario()</code> se iniciará para crearlo. Si ya existe (como por ejemplo cuando el usuario ya ingresó al sitio), se recupera el dato del nombre usando <code>getItem()</code> y se fija mediante <code>textContent</code> del título a la cadena, más el nombre del usuario, como hiciste dentro de <code>estableceNombreUsuario()</code>.</li> + <li>Finalmente, agrega abajo el evento <code>onclick</code> que manipulará el botón, de modo que cuando sea pulsado se inicie la función <code>estableceNombreUsuario()</code>. Esto permitirá al usuario establecer un nuevo nombre cada vez que lo desee al pulsar el botón: + <pre class="brush: js notranslate">miBoton.onclick = function() { + <code>estableceNombreUsuario</code>(); +}</pre> + </li> +</ol> + +<p>Ahora cuando visites tu sitio por primera vez, este te pedirá tu nombre y te dará un mensaje personalizado de bienvenida. Puedes cambiar cuantas veces quieras el nombre al presionar el botón. Y como un bonus añadido, ya que el nombre se almacena en el localStorage, este permanecerá después de que cierre el sitio, ¡manteniendo ahí el mensaje personalizado cuando abras el sitio la próxima vez!</p> + +<h3 id="¿Un_nombre_de_usuario_nulo">¿Un nombre de usuario nulo?</h3> + +<p>Cuando ejecutes el ejemplo y obtengas el cuadro de diálogo que solicita que introduzcas tu nombre de usuario, intenta pulsar el botón <em>Cancelar</em>. Deberías terminar con un título que diga que <em>Mozilla es genial, null</em>. Esto sucede porque, cuando cancelas el mensaje, el valor se establece como <code>null</code>. Null (nulo) es un valor especial en JavaScript que se refiere a la ausencia de un valor.</p> + +<p>Además, prueba a dar clic en <em>Aceptar</em> sin introducir un nombre. Deberías terminar con un título que diga que <em>Mozilla es genial</em>, por razones bastante obvias.</p> + +<p>Para evitar estos problemas, podrías comprobar que el usuario no ha introducido un nombre en blanco. Actualiza tu función <code>estableceNombreUsuario()</code> a lo siguiente:</p> + +<pre class="brush: js notranslate">function estableceNombreUsuario() { + let miNombre = prompt('Introduzca su nombre.'); + if(!miNombre) { + estableceNombreUsuario(); + } else { + localStorage.setItem('nombre', miNombre); + miTitulo.innerHTML = 'Mozilla is genial, ' + miNombre; + } +}</pre> + +<p>En el lenguaje humano, esto significa que si <code>miNombre</code> no tiene ningún valor, ejecute <code>estableceNombreUsuario()</code> de nuevo desde el principio. Si tiene un valor (si la afirmación anterior no es verdadera), entonces almacene el valor en <code>localStorage</code> y establézcalo como el texto del título.</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Si has seguido las instrucciones en este artículo, tendrás una página que luzca como esta (también puede <a href="http://mdn.github.io/beginner-html-site-scripted/">ver nuestra versión aquí</a>):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9539/website-screen-scripted.png" style="display: block; height: 995px; margin: 0px auto; width: 800px;"></p> + +<p>Si tuviste problemas, siempre puedes comparar su trabajo con el <a href="https://github.com/mdn/beginner-html-site-scripted/blob/gh-pages/scripts/main.js">código terminado del ejemplo en GitHub</a>.</p> + +<p>Aquí solo has rozado la superficie de JavaScript. Si has disfrutado aprendiendo y deseas avanzar más, visita la <a href="/es/docs/Web/JavaScript/Guide">Guía de JavaScript</a>.</p> + +<h2 id="Ve_también">Ve también</h2> + +<dl> + <dt><a href="/es/docs/Learn/JavaScript">JavaScript</a></dt> + <dd>Sumérgete en JavaScript con mucho más detalle.</dd> + <dt><a href="https://learnjavascript.online/">Aprende JavaScript</a></dt> + <dd>¡Este es un excelente material para los aspirantes a desarrolladores web! Aprende JavaScript en un entorno interactivo, con lecciones cortas y pruebas interactivas, guiadas por una evaluación automatizada. Las primeras 40 lecciones son gratis. El curso completo está disponible por un pequeño pago único (en inglés).</dd> +</dl> + +<p>{{PreviousMenuNext( "Learn/Getting_started_with_the_web/CSS_basics","Learn/Getting_started_with_the_web/Publishing_your_website","Learn/Getting_started_with_the_web")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li id="Installing_basic_software"><a href="/es/Learn/Getting_started_with_the_web/Installing_basic_software">Instalación de software básico</a></li> + <li id="What_will_your_website_look_like"><a href="/es/Learn/Getting_started_with_the_web/What_will_your_website_look_like">¿Cómo será tu sitio web?</a></li> + <li id="Dealing_with_files"><a href="/es/Learn/Getting_started_with_the_web/Dealing_with_files">El trato con archivos</a></li> + <li id="HTML_basics"><a href="/es/Learn/Getting_started_with_the_web/HTML_basics">Conceptos básicos de HTML</a></li> + <li id="CSS_basics"><a href="/es/Learn/Getting_started_with_the_web/CSS_basics">Conceptos básicos de CSS</a></li> + <li id="JavaScript_basics"><a href="/es/Learn/Getting_started_with_the_web/JavaScript_basics">Conceptos básicos de JavaScript</a></li> + <li id="Publishing_your_website"><a href="/es/Learn/Getting_started_with_the_web/Publishing_your_website">Publica tu sitio web</a></li> + <li id="How_the_web_works"><a href="/es/Learn/Getting_started_with_the_web/How_the_Web_works">Como funciona la web</a></li> +</ul> diff --git a/files/es/learn/getting_started_with_the_web/la_web_y_los_estandares_web/index.html b/files/es/learn/getting_started_with_the_web/la_web_y_los_estandares_web/index.html new file mode 100644 index 0000000000..daf6e77d18 --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/la_web_y_los_estandares_web/index.html @@ -0,0 +1,172 @@ +--- +title: La web y los estándares web +slug: Learn/Getting_started_with_the_web/La_web_y_los_estandares_web +tags: + - Estándares web + - Front-end + - Interfáz de Usuario + - Novato + - Principiante + - Web + - aprende +translation_of: Learn/Getting_started_with_the_web/The_web_and_web_standards +--- +<p dir="ltr">{{learnsidebar}}</p> + +<p dir="ltr">Este artículo proporciona algunos antecedentes útiles sobre la Web — cómo surgió, qué son las tecnologías web estándar, cómo funcionan juntas, por qué "desarrollador web" es una gran carrera para elegir y qué tipos de mejores prácticas aprenderás a través de este curso.</p> + +<h2 dir="ltr" id="Breve_historia_de_la_web">Breve historia de la web</h2> + +<p dir="ltr">Mantendremos esto muy breve, ya que hay muchos artículos (más) detallados de la historia de la web, a los que enlazaremos más adelante (también intenta buscar "historia de la web" en tu motor de búsqueda favorito y ve lo que obtienes, si estás interesado en más detalles).</p> + +<p dir="ltr">A fines de la década de 1960, las fuerzas armadas de EE. UU. desarrollaron una red de comunicación llamada {{Glossary("Arpanet")}}. Esta se puede considerar una precursora de la Web, ya que trabajó en la {{interwiki("wikipedia", "conmutación de paquetes")}} y presentó la primera implementación de la {{interwiki("wikipedia", "Familia de protocolos de internet")}} TCP/IP. Estas dos tecnologías forman la base de la infraestructura sobre la que se construye Internet.</p> + +<p dir="ltr">En 1980, Tim Berners-Lee (a menudo denominado TimBL) escribió un programa de block de notas llamado ENQUIRE, que presentaba el concepto de enlaces entre diferentes nodos. ¿Te suena familiar?</p> + +<p dir="ltr">Avanzó rápidamente hasta 1989, y TimBL escribió <a href="https://www.w3.org/History/1989/proposal.html" rel="noopener">Gestión de la información: una propuesta</a> e hipertexto en el CERN; estas dos publicaciones juntas proporcionaron los antecedentes de cómo funcionaría la web. Recibieron una buena cantidad de interés, suficiente para convencer a los jefes de TimBL de que le permitieran seguir adelante y creara un sistema de hipertexto global.</p> + +<p dir="ltr">A finales de 1990, TimBL había creado todo lo necesario para ejecutar la primera versión de la web: {{web.link("/es/docs/Web/HTTP", "HTTP")}}, {{web.link("/es/docs/Web/HTML", "HTML")}}, el primer navegador web, que se llamaba {{interwiki("wikipedia", "WorldWideWeb")}}, un servidor HTTP y algunas páginas web para mirar.</p> + +<p dir="ltr">En los años siguientes, la web explotó, se lanzaron varios navegadores, se instalaron miles de servidores web y se crearon millones de páginas web. Bien, este es un muy sencillo resumen de lo que sucedió, pero les prometí un breve resumen.</p> + +<p dir="ltr">Un último dato importante para compartir es que en 1994, TimBL fundó el {{interwiki("wikipedia", "World Wide Web Consortium")}} (W3C), una organización que reúne a representantes de muchas empresas de tecnología diferentes para trabajar juntos en la creación de especificaciones de tecnología web. Después de eso, siguieron otras tecnologías como {{web.link("/es/docs/Web/CSS", "CSS")}} y {{web.link("/es/docs/Web/JavaScript", "JavaScript")}}, y la web comenzó a parecerse más a la web que conocemos hoy.</p> + +<h2 dir="ltr" id="Estándares_web">Estándares web</h2> + +<p dir="ltr"><strong>Los estándares web</strong> son las tecnologías que utilizamos para crear sitios web. Estos estándares existen como extensos documentos técnicos llamados <em>especificaciones</em>, que detallan exactamente cómo debería funcionar la tecnología. Estos documentos no son muy útiles para aprender a usar las tecnologías que describen (es por eso que tenemos sitios como <em>MDN Web Docs</em>), sino que están pensados para que los utilicen los ingenieros de software para implementar esas tecnologías (generalmente en los navegadores web).</p> + +<p dir="ltr">Por ejemplo, el <a href="https://html.spec.whatwg.org/multipage/" rel="noopener">lleno de vida Estándar HTML</a> describe exactamente cómo se debe implementar HTML (todos los elementos HTML y sus APIs asociadas y otras tecnologías circundantes).</p> + +<p dir="ltr">Los estándares web son creados por organismos de estándares — instituciones que invitan a grupos de personas de diferentes compañías de tecnología a unirse y acordar cómo deberían funcionar las tecnologías de la mejor manera posible para cumplir con todos sus casos de uso. El W3C es el organismo de estándares web más conocido, pero hay otros como <a href="https://whatwg.org/" rel="noopener">WHATWG</a> (que fueron responsables de la modernización del lenguaje HTML), <a href="https://www.ecma-international.org/" rel="noopener">ECMA</a> (que publica el estándar para ECMAScript, en el que se basa JavaScript), <a href="https://www.khronos.org/" rel="noopener">Khronos</a> (que publica tecnologías para gráficos 3D, como WebGL) y otras.</p> + +<h3 dir="ltr" id="Estándares_abiertos">Estándares "abiertos"</h3> + +<p dir="ltr">Uno de los aspectos clave de los estándares web, que TimBL y el W3C acordaron desde el principio, es que la web (y las tecnologías web) deben ser libres tanto para contribuir como para usar, y no estar gravadas por patentes/licencias. Por lo tanto, cualquiera puede escribir el código para crear un sitio web de forma gratuita y cualquiera puede contribuir al proceso de creación de estándares, donde se escriben las especificaciones.</p> + +<p dir="ltr">Debido a que las tecnologías web se crean abiertamente, en colaboración entre muchas empresas diferentes, significa que ninguna empresa las puede controlar, lo cual es algo realmente bueno. No querrías que una sola empresa decidiera repentinamente poner toda la web detrás de un muro de pago, o lanzar una nueva versión de HTML que todos tienen que comprar para continuar creando sitios web, o peor aún, simplemente decidiendo que ya no están interesados, y simplemente apagarlas.</p> + +<p dir="ltr">Esto permite que la web siga siendo un recurso público de libre acceso.</p> + +<h3 dir="ltr" id="No_rompas_la_web">No rompas la web</h3> + +<p dir="ltr">Otra frase que escucharás sobre los estándares web abiertos es "no rompas la web" — la idea es que cualquier tecnología web nueva que se introduzca debe ser compatible con versiones anteriores (es decir, los sitios web antiguos seguirán funcionando) y compatibles con versiones posteriores (las tecnologías futuras a su vez serán compatibles con las que tenemos actualmente). A medida que avances en el material de aprendizaje que se presenta aquí, comenzarás a aprender cómo se hace posible esto con un trabajo de diseño e implementación muy inteligente.</p> + +<h2 id="Ser_desarrollador_web_es_bueno">Ser desarrollador web es bueno</h2> + +<p>La industria web es un mercado muy atractivo para ingresar si estás buscando trabajo. Las cifras publicadas recientemente dicen que actualmente hay alrededor de 19 millones de desarrolladores web en el mundo, y esa cifra se establecerá en más del doble en la próxima década. Y al mismo tiempo, hay una escasez de habilidades en la industria, entonces, ¿qué mejor momento para aprender sobre desarrollo web?</p> + +<p>Sin embargo, no todo es diversión y juegos — crear sitios web es una propuesta más complicada de lo que solía ser, y tendrás que dedicar algo de tiempo a estudiar todas las diferentes tecnologías que necesitas usar, todas las técnicas y las mejores prácticas que necesitas conocer y todos los patrones típicos que se te pedirá que implementes. Te tomará unos meses comenzar realmente a involucrarte en él, y luego deberás seguir aprendiendo para que tu conocimiento se mantenga actualizado con todas las nuevas herramientas y funciones que aparecen en la plataforma web, y seguir practicando y perfeccionando tu oficio.</p> + +<p><em>Lo único constante es el cambio.</em></p> + +<p>¿Esto suena difícil? No te preocupes: nuestro objetivo es brindarte todo lo que necesitas saber para comenzar, y las cosas serán más fáciles. Una vez que aceptes el cambio constante y la incertidumbre de la web, comenzarás a disfrutar. Como parte de la comunidad web, tendrás toda una red de contactos y material útil para ayudarte, y comenzarás a disfrutar de las posibilidades creativas que brinda.</p> + +<p>Ahora eres un creativo digital. Disfruta de la experiencia y el potencial de ganarte la vida.</p> + +<h2 id="Descripción_de_las_tecnologías_web_modernas">Descripción de las tecnologías web modernas</h2> + +<p>Hay una serie de tecnologías que debes aprender si deseas ser un desarrollador web front-end. En esta sección las describiremos brevemente. Para obtener una explicación más detallada de cómo funcionan juntas algunas de ellas, lee nuestro artículo {{web.link("/es/docs/Learn/Getting_started_with_the_web/How_the_Web_works", "Cómo funciona la web")}}.</p> + +<h3 id="Navegadores">Navegadores</h3> + +<p>Probablemente estés leyendo estas palabras dentro de un navegador web en este mismo momento (a menos que las hayas impreso o estés utilizando tecnología de asistencia, como un lector de pantalla para leerlas). Los navegadores web son los programas de software que la gente usa para consumir la web e incluyen <a href="https://www.mozilla.org/es-MX/firefox/" rel="noopener">Firefox</a>, <a href="https://www.google.com/intl/es-419/chrome/" rel="noopener">Chrome</a>, <a href="https://www.opera.com/es" rel="noopener">Opera</a>, <a href="https://www.apple.com/mx/safari/" rel="noopener">Safari</a> y <a href="https://www.microsoft.com/es-es/edge" rel="noopener">Edge</a>.</p> + +<h3 id="HTTP">HTTP</h3> + +<p>El Protocolo de transferencia de hipertexto, o {{web.link("/es/docs/Web/HTTP/Basics_of_HTTP", "HTTP")}}, es un protocolo de mensajería que permite a los navegadores web comunicarse con los servidores web (donde se almacenan los sitios web). Una conversación típica es algo así como</p> + +<pre class="brush: bash notranslate">"Hola servidor web. ¿Me puedes dar los archivos que necesito para renderizar bbc.co.uk"? + +"Seguro navegador web — aquí los tienes" + +[Descarga archivos y renderiza la página web]</pre> + +<p>La sintaxis real de los mensajes HTTP (llamados peticiones y respuestas) no es tan legible para los humanos, pero esto te da una idea básica.</p> + +<h3 id="HTML_CSS_y_JavaScript">HTML, CSS y JavaScript</h3> + +<p>{{web.link("/es/docs/Web/HTML", "HTML")}}, {{web.link("/es/docs/Web/CSS", "CSS")}} y {{web.link("/es/docs/Web/JavaScript", "JavaScript")}} son las tres tecnologías principales que utilizarás para crear un sitio web:</p> + +<ul> + <li> + <p>El lenguaje de marcado de hipertexto, o <strong>HTML</strong>, es un lenguaje de marcado que consta de diferentes elementos en los que puedes ajustar (marcar) el contenido para darle significado (semántica) y estructura. El HTML simple se ve así:</p> + + <pre class="brush: html notranslate"><code><h1>Este es un encabezado de alto nivel</h1> + +<p>Este es un párrafo de texto.</p> + +<img src="cat.jpg" alt="Una imagen de mi gato"></code></pre> + + <p>Si adoptamos una analogía de la construcción de casas, HTML sería como los cimientos y las paredes de la casa, que le dan estructura y la mantienen unida.</p> + </li> + <li> + <p>Hojas de estilo en cascada (<strong>CSS</strong> por "<em>Cascading Style Sheets</em>") es un lenguaje basado en reglas que se utiliza para aplicar estilos a tu HTML, por ejemplo, establecer colores del texto y del fondo, agregar bordes, animar cosas o diseñar una página de cierta manera. Como un sencillo ejemplo, el siguiente código convertirá nuestro párrafo HTML en rojo:</p> + + <pre class="notranslate">p { + color: red; +}</pre> + + <p>En la analogía de la casa, CSS es como la pintura, el papel tapiz, las alfombras y los cuadros que usarías para hacer que la casa se vea bien.</p> + </li> + <li> + <p><strong>JavaScript</strong> es el lenguaje de programación que usamos para agregar interactividad a los sitios web, desde el cambio de estilo dinámico hasta la obtención de actualizaciones desde el servidor, pasando por gráficos complejos en 3D. El siguiente JavaScript simple almacenará en la memoria una referencia a nuestro párrafo y cambiará el texto dentro de él:</p> + + <pre class="brush: js notranslate">let pElem = document.querySelector('p'); +pElem.textContent = '¡Cambiamos el texto!';</pre> + + <p>En la analogía de la casa, JavaScript es como la cocina, el televisor, el microondas o la secadora de pelo — las cosas que le dan a tu casa una útil funcionalidad.</p> + </li> +</ul> + +<h3 id="Herramientas">Herramientas</h3> + +<p>Una vez que hayas aprendido las tecnologías "sin procesar" que se pueden usar para crear páginas web (como HTML, CSS y JavaScript), pronto comenzarás a encontrar varias herramientas que puedes usar para hacer tu trabajo más fácil y/o más eficiente. Algunos ejemplos incluyen:</p> + +<ul> + <li>Las {{web.link("/es/docs/Learn/Common_questions/What_are_browser_developer_tools", "herramientas de desarrollo")}} dentro de los navegadores modernos que se pueden usar para depurar tu código.</li> + <li>{{web.link("/es/docs/Learn/Tools_and_testing/Cross_browser_testing", "Herramientas de prueba")}} que puedes usar para ejecutar pruebas y mostrar si tu código se está comportando como lo esperabas.</li> + <li>Bibliotecas y marcos de desarrollo construidos sobre JavaScript que te permiten crear ciertos tipos de sitios web de manera mucho más rápida y efectiva.</li> + <li>Las llamadas "Linternas" (<code>Linters</code> en inglés), que toman un conjunto de reglas, examinan tu código y resaltan los lugares donde no has seguido las reglas correctamente.</li> + <li>Minificadores, que eliminan todos los espacios en blanco de tus archivos de código fuente para que sean más pequeños y, por lo tanto, se descarguen del servidor más rápidamente.</li> +</ul> + +<h3 id="Marcos_de_desarrollo_y_lenguajes_de_lado_del_servidor">Marcos de desarrollo y lenguajes de lado del servidor</h3> + +<p>HTML, CSS y JavaScript son lenguajes de la interfaz del usuario ("<code>front-end</code>" o del lado del cliente), lo cual significa que los ejecuta el navegador para producir la interfaz del sitio web que los usuarios pueden utilizar.</p> + +<p>Hay otra clase de lenguajes llamados lenguajes de la interfaz de admiración ("<code>back-end</code>" o de lado del servidor), lo cual significa que se ejecutan en el servidor antes de que el resultado se envíe al navegador para que se muestre. Un uso típico de un lenguaje de lado del servidor es obtener algunos datos de una base de datos y generar algo de HTML para contener los datos, antes de enviar el HTML al navegador para mostrárselo al usuario.</p> + +<p>Los lenguajes de lado del servidor de ejemplo incluyen ASP.NET, Python, PHP y NodeJS.</p> + +<h2 id="Mejores_prácticas_web">Mejores prácticas web</h2> + +<p>Hemos hablado brevemente sobre las tecnologías que utilizarás para crear sitios web. Ahora analicemos las mejores prácticas que debes emplear para asegurarte de que estás utilizando esas tecnologías de la mejor manera posible.</p> + +<p>Al hacer desarrollo web, la principal causa de incertidumbre proviene del hecho de que no sabes qué combinación de tecnologías utilizará cada usuario para ver tu sitio web:</p> + +<ul> + <li>El usuario 1 podría estar mirándolo en un iPhone, con una pantalla pequeña y estrecha.</li> + <li>El usuario 2 puede estar mirándolo en una computadora portátil con Windows con un monitor de pantalla ancha adjunto.</li> + <li>El usuario 3 puede ser ciego y usar un lector de pantalla para leerle la página web.</li> + <li>El usuario 4 podría estar usando una máquina de escritorio realmente antigua que no puede ejecutar navegadores modernos.</li> +</ul> + +<p>Debido a que no sabes exactamente qué usarán tus usuarios, debes diseñar a la defensiva — hacer que tu sitio web sea lo más flexible posible, de modo que todos los usuarios anteriores puedan hacer uso de él, incluso si no todos obtienen la misma experiencia. En resumen, estamos tratando de hacer que la web funcione para todos, tanto como sea posible.</p> + +<p>Encontrarás los siguientes conceptos en algún momento de tus estudios.</p> + +<ul> + <li><strong>Compatibilidad entre navegadores</strong> — es la práctica de intentar asegurarte de que tu página web funcione en tantos dispositivos como sea posible. Esto incluye el uso de tecnologías compatibles con todos los navegadores, brindando mejores experiencias a los navegadores que pueden manejarlas (mejora progresiva) y/o escribiendo código para que vuelvas a una experiencia más simple pero aún utilizable en navegadores más antiguos (degradación elegante). También implica muchas pruebas para ver si algo falla en ciertos navegadores, y luego más trabajo para corregir esas fallas.</li> + <li><strong>Diseño web receptivo</strong> — es la práctica de hacer que tu funcionalidad y diseños sean flexibles para que se puedan adaptar automáticamente a diferentes navegadores. Un ejemplo obvio es un sitio web que se presenta de una forma en un navegador de pantalla ancha en el escritorio, pero que se muestra como un diseño de una sola columna más compacto en los navegadores de teléfonos móviles. Intenta ajustar el ancho de la ventana de tu navegador ahora y ve qué sucede.</li> + <li><strong>Rendimiento</strong> — significa hacer que los sitios web se carguen lo más rápido posible, pero también hacerlos intuitivos y fáciles de usar para que los usuarios no se sientan frustrados y vayan a otro lugar.</li> + <li><strong>Accesibilidad</strong> — significa hacer que tus sitios web sean utilizables por la mayor cantidad posible de personas (los conceptos relacionados son diversidad e inclusión y diseño inclusivo). Esto incluye a personas con impedimentos visuales, auditivos, cognitivos o físicos. También va más allá de las personas con discapacidad — ¿qué pasa con los jóvenes o los ancianos, las personas de diferentes culturas, las personas que utilizan dispositivos móviles o las personas con conexiones de red lentas o poco fiables?</li> + <li><strong>Internacionalización</strong> — significa hacer que los sitios web sean utilizables por personas de diferentes culturas, que hablan diferentes idiomas al tuyo. Hay consideraciones técnicas aquí (como alterar tu diseño para que aún funcione bien para idiomas de derecha a izquierda, o incluso verticales) y humanas (tal como usar un lenguaje simple, sin jerga para que las personas que tienen tu idioma ya que su segundo o tercer idioma es más probable que entienda tu texto).</li> + <li><strong>Privacidad y seguridad</strong>. Estos dos conceptos están relacionados pero son diferentes. La privacidad se refiere a permitir que las personas realicen sus negocios de manera privada y no espiarlos o recopilar más datos de los estrictamente necesarios. La seguridad se refiere a la construcción de tu sitio web de una manera segura para que los usuarios malintencionados no puedan robar la información contenida en él o de tus usuarios.</li> +</ul> + +<h2 dir="ltr" id="Ve_también">Ve también</h2> + +<ul dir="ltr"> + <li>{{interwiki("wikipedia", "Historia de la World Wide Web")}}</li> + <li>{{web.link("/es/docs/Learn/Common_questions/How_does_the_Internet_work", "¿Cómo funciona la internet?")}}</li> +</ul> diff --git a/files/es/learn/getting_started_with_the_web/manejando_los_archivos/index.html b/files/es/learn/getting_started_with_the_web/manejando_los_archivos/index.html new file mode 100644 index 0000000000..0c7f8c4121 --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/manejando_los_archivos/index.html @@ -0,0 +1,120 @@ +--- +title: Manejo de archivos +slug: Learn/Getting_started_with_the_web/Manejando_los_archivos +tags: + - Archivos + - Guía + - HTML + - Novato + - Principiante + - Scripting + - Sitios Web + - 'l10n:priority' + - teorias +translation_of: Learn/Getting_started_with_the_web/Dealing_with_files +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Getting_started_with_the_web/What_will_your_website_look_like", "Learn/Getting_started_with_the_web/HTML_basics", "Learn/Getting_started_with_the_web")}}</div> + +<div class="summary"> +<p>Un sitio web consta de muchos archivos: texto del contenido, código, hojas de estilo, contenido multimedia, etc. Cuando estás creando un sitio web, necesitas ensamblar estos archivos en una estructura sensible en tu computadora local, asegurarte de que puedan comunicarse entre sí y hacer que todo su contenido se vea bien antes de que eventualmente {{web.link("/es/Learn/Getting_started_with_the_web/Publishing_your_website", "los cargues en un servidor")}}. El <em>manejo de archivos</em> analiza algunos problemas que debes tener en cuenta, para que puedas configurar una estructura de archivos adecuada para tu sitio web.</p> +</div> + +<h2 id="¿Dónde_debería_estar_tu_sitio_web_en_tu_computadora">¿Dónde debería estar tu sitio web en tu computadora?</h2> + +<p>Cuando estés trabajando en un sitio web localmente en tu computadora, debes mantener todos los archivos relacionados en un solo directorio que refleje la estructura de archivos del sitio web publicado en el servidor. Este directorio se puede ubicar en cualquier lugar que desees, pero debes colocarlo en algún lugar donde lo puedas encontrar fácilmente, tal vez en tu escritorio, en tu directorio de inicio o en la raíz de tu disco duro.</p> + +<ol> + <li>Elige un lugar para almacenar los proyectos de tus sitios web. Dentro del lugar elegido, crea un nuevo directorio llamado <code>proyectosweb</code> (o algo similar). Aquí es donde vivirán todos los proyectos de tus sitios web.</li> + <li>Dentro de este primer directorio, crea otro directorio para almacenar tu primer sitio web. Llámalo <code>pruebasitio</code> (o algo más imaginativo).</li> +</ol> + +<h2 id="Una_acotación_sobre_la_envoltura_y_el_espaciado">Una acotación sobre la envoltura y el espaciado</h2> + +<p>Notarás que a lo largo de este artículo, te pedimos que nombres los directorios y archivos completamente en minúsculas sin espacios. Esto es porque:</p> + +<ol> + <li>Muchas computadoras, particularmente los servidores web, distinguen entre mayúsculas y minúsculas. Entonces, por ejemplo, si colocas una imagen en tu sitio web en <code>pruebasitio/MiImagen.jpg</code> y luego, en un archivo diferente intentas invocar la imagen como <code>pruebasitio/miimagen.jpg</code>, puede que no funcione.</li> + <li>Los navegadores, servidores web y lenguajes de programación no manejan los espacios de manera consistente. Por ejemplo, si usas espacios en tu nombre de archivo, algunos sistemas pueden tratar el nombre de archivo como dos nombres de archivo. Algunos servidores reemplazarán las áreas en tus nombres de archivo con "%20" (el código de caracteres para espacios en URI), lo cual provocará que todos tus enlaces se rompan. Es mejor separar las palabras con guiones, en lugar de guiones bajos: <code>mi-archivo.html</code> vs. <code>mi_archivo.html</code>.</li> +</ol> + +<p>La respuesta corta es que debes usar un guión para los nombres de tus archivos. El motor de búsqueda de Google trata un guión como un separador de palabras, pero no considera un guión bajo de esa manera. Por estos motivos, es mejor adquirir el hábito de escribir los nombres de los directorios y archivos en minúsculas, sin espacios y con palabras separadas por guiones, al menos hasta que sepas lo que estás haciendo. De esa manera, tropezarás con menos problemas en el futuro.</p> + +<h2 id="¿Qué_estructura_debe_tener_tu_sitio_web">¿Qué estructura debe tener tu sitio web?</h2> + +<p>A continuación, veamos qué estructura debería tener tu sitio de prueba. Las cosas más comunes que tendrás en cualquier proyecto de sitio web que crees son un archivo de índice HTML y directorios para contener imágenes, archivos de estilo y archivos de script. Crea estos ahora:</p> + +<ol> + <li><code><strong>index.html</strong></code>: Este archivo generalmente tendrá el contenido de tu página de inicio, es decir, el texto y las imágenes que las personas ven cuando visitan tu sitio por primera vez. Usando tu editor de texto, crea un nuevo archivo llamado <code>index.html</code> y guárdalo dentro de tu directorio <code>pruebasitio</code>.</li> + <li>Directorio <strong><code>images</code></strong>: Este directorio contendrá todas las imágenes que utilices en tu sitio. Crea un directorio llamado <code>images</code>, dentro de tu directorio <code>pruebasitio</code>.</li> + <li>Directorio <strong><code>styles</code></strong>: Este directorio contendrá el código CSS que se utiliza para aplicar estilo al contenido (por ejemplo, configurar el texto y los colores de fondo). Crea un directorio llamado <code>styles</code>, dentro de tu directorio <code>pruebasitio</code>.</li> + <li>Directorio <strong><code>scripts</code></strong>: Este directorio contendrá todo el código JavaScript utilizado para agregar funcionalidad interactiva a tu sitio (por ejemplo, botones que cargan datos cuando se hace clic en ellos). Crea un directorio llamado <code>scripts</code>, dentro de tu directorio <code>pruebasitio</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: En las computadoras con Windows, es posible que tengas problemas para ver los nombres de los archivos, porque de manera predeterminada, Windows tiene activada una opción llamada <strong>Ocultar extensiones para tipos de archivos conocidos</strong>. Generalmente, la puedes desactivar yendo al Explorador de Windows, seleccionando la opción <strong>Opciones de directorio...</strong>, desmarcando la casilla de verificación <strong>Ocultar extensiones para tipos de archivo conocidos</strong> y luego haciendo clic en <strong>Aceptar</strong>. Para obtener información más específica sobre tu versión de Windows, puedes buscar en la web.</p> +</div> + +<h2 id="Rutas_de_archivo">Rutas de archivo</h2> + +<p>Para que los archivos se comuniquen entre sí, debes proporcionar una ruta de archivo entre ellos, básicamente una ruta, para que un archivo sepa dónde está otro. Para demostrarlo, insertaremos un poco de HTML en nuestro archivo <code>index.html</code> y haremos que muestre la imagen que elegiste en el artículo {{web.link("/es/docs/Learn/Getting_started_with_the_web/What_will_your_website_look_like#Imágenes", "¿Cómo se verá tu sitio web?")}}</p> + +<ol> + <li>Copia la imagen que elegiste anteriormente en tu directorio <code>images</code>.</li> + <li>Abre tu archivo <code>index.html</code> e inserta el siguiente código en el archivo exactamente como se muestra. Por ahora, no te preocupes por lo que significa todo esto; veremos las estructuras con más detalle más adelante en la serie. + <pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Mi página de prueba</title> + </head> + <body> + <img src="" alt="Mi imagen de prueba"> + </body> +</html></pre> + </li> + <li>La línea <code><img src="" alt="Mi imagen de prueba"></code> es el código HTML que inserta una imagen en la página. Necesitamos decirle al HTML dónde está la imagen. La imagen está dentro del directorio <em>images</em>, que está en el mismo directorio que <code>index.html</code>. Para recorrer la estructura del archivo desde <code>index.html</code> hasta nuestra imagen, la ruta del archivo que necesitamos es <code>images/nombre-archivo-imagen</code>. Por ejemplo, nuestra imagen se llama <code>firefox-icon.png</code>, por lo que la ruta del archivo es <code>images/firefox-icon.png</code>.</li> + <li>Inserta la ruta del archivo en tu código HTML entre las comillas dobles del código <code>src=""</code>.</li> + <li>Guarda tu archivo HTML, luego cárgalo en tu navegador web (haz doble clic en el archivo). ¡Deberías ver tu nueva página web mostrando tu imagen!</li> +</ol> + +<p><img alt="Una captura de pantalla del sitio web básico que muestra solo el logotipo de Firefox: un zorro en llamas envolviendo el mundo" src="https://mdn.mozillademos.org/files/9229/website-screenshot.png" style="display: block; height: 542px; margin: 0px auto; width: 690px;"></p> + +<p>Algunas reglas generales para las rutas de archivo:</p> + +<ul> + <li>Para vincular a un archivo destino en el mismo directorio que el archivo HTML de invocación, simplemente usa el nombre del archivo, p. ej. <code>mi-imagen.jpg</code>.</li> + <li>Para hacer referencia a un archivo en un subdirectorio, escribe el nombre del directorio delante de la ruta, más una barra inclinada, p. ej. <code>subdirectorio/mi-imagen.jpg</code>.</li> + <li>Para vincular a un archivo destino en el directorio <strong>arriba</strong> del archivo HTML que lo invoca, escribe dos puntos. Por ejemplo, si <code>index.html</code> estuviera dentro de un subdirectorio de <code>pruebasitio</code> y <code>mi-imagen.jpg</code> estuviera dentro de <code>pruebasitio</code>, puedes hacer referencia a <code>mi-imagen.jpg</code> desde <code>index.html</code> utilizando <code>../mi-imagen.jpg</code>.</li> + <li>Los puedes combinar tanto como desees, por ejemplo, <code>../subdirectorio/otro-subdirectorio/mi-imagen.jpg</code>.</li> +</ul> + +<p>Por ahora, esto es todo lo que necesitas saber.</p> + +<div class="note"> +<p><strong>Nota</strong>: El sistema de archivos de Windows tiende a utilizar barras invertidas, no barras diagonales, p. ej. <code>C:\windows</code>. Esto no importa en HTML, incluso si estás desarrollando tu sitio web en Windows, debes usar barras diagonales en tu código.</p> +</div> + +<h2 id="¿Qué_más_se_debería_hacer">¿Qué más se debería hacer?</h2> + +<p>Eso es todo por ahora. La estructura de tu directorio debería verse así:</p> + +<p><img alt="Una estructura de archivos en mac os x finder, que muestra un directorio de imágenes con una imagen, directorios de estilos y scripts vacíos, y un archivo index.html" src="https://mdn.mozillademos.org/files/9231/file-structure.png" style="display: block; height: 577px; margin: 0px auto; width: 929px;"></p> + +<p>{{PreviousMenuNext("Learn/Getting_started_with_the_web/What_will_your_website_look_like", "Learn/Getting_started_with_the_web/HTML_basics", "Learn/Getting_started_with_the_web")}}</p> + + + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li id="Instalacion_de_software_basico">{{web.link("/es/Learn/Getting_started_with_the_web/Instalacion_de_software_basico", "Instalación de software básico")}}</li> + <li id="Como_se_vera_tu_sitio_web">{{web.link("/es/Learn/Getting_started_with_the_web/What_will_your_website_look_like", "¿Cómo se verá tu sitio web?")}}</li> + <li id="Manejo_de_archivos">{{web.link("/es/Learn/Getting_started_with_the_web/Manejando_los_archivos", "Manejo de archivos")}}</li> + <li id="Conceptos_basicos_de_HTML">{{web.link("/es/Learn/Getting_started_with_the_web/HTML_basics", "Conceptos básicos de HTML")}}</li> + <li id="Conceptos_basicos_de_CSS">{{web.link("/es/Learn/Getting_started_with_the_web/CSS_basics", "Conceptos básicos de CSS")}}</li> + <li id="Conceptos_basicos_de_JavaScript">{{web.link("/es/Learn/Getting_started_with_the_web/JavaScript_basics", "Conceptos básicos de JavaScript")}}</li> + <li id="Publicar_tu_sitio_web">{{web.link("/es/Learn/Getting_started_with_the_web/Publishing_your_website", "Publicar tu sitio web")}}</li> + <li id="Como_funciona_la_web">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Cómo_funciona_la_Web", "Cómo funciona la Web")}}</li> +</ul> diff --git a/files/es/learn/getting_started_with_the_web/publishing_your_website/index.html b/files/es/learn/getting_started_with_the_web/publishing_your_website/index.html new file mode 100644 index 0000000000..9dbfe88d7e --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/publishing_your_website/index.html @@ -0,0 +1,195 @@ +--- +title: Publicar tu sitio web +slug: Learn/Getting_started_with_the_web/Publishing_your_website +tags: + - Aprender + - Aprendiz + - Dropbox + - FTP + - GitHub + - Publicacion + - Sitio Web + - Web + - Web Hosting + - publicar + - web server +translation_of: Learn/Getting_started_with_the_web/Publishing_your_website +--- +<p>{{LearnSidebar()}}</p> + +<p>{{PreviousMenuNext("Learn/Getting_started_with_the_web/JavaScript_basics", "Learn/Getting_started_with_the_web/How_the_Web_works","Learn/Getting_started_with_the_web")}}</p> + +<div class="summary"> +<p>Una vez que termines de escribir tu código y organizar los archivos que forman parte de tu sitio, debes ponerlo en línea para que la gente pueda consultarlo. Este artículo muestra cómo conseguir de manera sencilla que tu código esté en línea.</p> +</div> + +<h2 id="¿Cuáles_son_las_opciones">¿Cuáles son las opciones?</h2> + +<p>Publicar un sitio no es un tema sencillo, principalmente porque hay muchas maneras diferentes de hacerlo. En este artículo no se trata de ver todos los modos posibles. En su lugar, discutiremos los pros y contras de tres amplias estrategias desde el punto de vista de un principiante, y luego debes seleccionar qué método usarás.</p> + +<h3 id="Obtener_alojamiento_y_un_nombre_de_dominio">Obtener alojamiento y un nombre de dominio</h3> + +<p>Si deseas un control total sobre tu sitio web publicado, probablemente necesitarás gastar dinero para comprar:</p> + +<ul> + <li><em>Alojamiento </em>(<em>Hosting</em>) — espacio de almacenamiento alquilado en el <a href="/es/docs/Learn/Common_questions/Que_es_un_servidor_WEB">servidor web</a> de una compañia de alojamientos. Pones los archivos de tu sitio web en este espacio, y el servidor web suministra el contenido a los usuarios que lo solicitan.</li> + <li>Un <a href="/es/docs/Learn/Common_questions/What_is_a_domain_name">nombre de dominio</a> — dirección única mediante la cual la gente puede encontrar tu sitio web, como <code>https://www.mozilla.org</code>, o <code>https://es.wikipedia.org/</code>. Puedes tomar en alquiler el nombre de tu dominio durante algunos años en un <strong>registrador de dominio</strong>.</li> +</ul> + +<p>Muchos sitios web profesionales toman esta opción.</p> + +<p>Además, necesitarás un programa de <a href="/es/docs/Glossary/FTP">protocolo de transferencia de archivo</a> (<em>File Transfer Protocol</em>, FTP) para transferir los archivos que conforman tu sitio web al servidor (mira más detalles de<a href="/es/docs/Learn/Common_questions/Cuanto_cuesta#Software"> cuánto puede costar: software</a>). Los programas FTP varían ampliamente, pero en general tienes que conectarte a tu servidor web contratado mediante detalles proporcionados por tu empresa de alojamiento (por ejemplo: nombre de usuario, contraseña, nombre del <em>host</em>). Una vez conectado con el servidor web el programa te mostrará tus archivos locales y los archivos del servidor web en dos ventanas y te proporcionará una forma de transferir los archivos de un lado a otro.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9469/ftp.jpg" style="display: block; height: 487px; margin: 0px auto; width: 800px;"></p> + +<h4 id="Consejos_para_elegir_alojamienoto_y_dominio">Consejos para elegir alojamienoto y dominio</h4> + +<ul> + <li>En MDN no promovemos empresas comerciales de alojamiento o resgistradoras de nombre de dominio específicas. Para encontrarlas basta con buscar «alojamiento web» o «<em>hosting</em> web» y «nombres de dominio». A veces las empresas proporcionan ambos en un paquete único. Los registradores acostumbran a facilitar la manera de comprobar si el nombre de dominio que deseas para tu sitio está disponible.</li> + <li>El <a href="/es/docs/Glossary/ISP">proveedor de servicio de Internet</a> (ISP) de tu casa u oficina puede proporcionar algún alojamiento limitado para un pequeño sitio web. <span id="result_box" lang="es"><span class="alt-edited">El conjunto de características disponibles será limitado, pero podría ser perfecto para tus primeros experimentos; </span></span>¡ponte en contacto con ellos y pregunta!</li> + <li>Hay servicios gratiuitos disponibles como <a href="https://neocities.org/">Neocities</a>, <a href="https://www.blogger.com">Blogspot</a>, y <a href="https://es.wordpress.com/">Wordpress</a>. <span id="result_box" lang="es"><span>Una vez más, obtienes lo que pagas, pero son ideales para tus experimentos iniciales.</span> <span>Los servicios gratuitos en su mayoría no requieren software de FTP para transferencias de archivos pues permiten arrastrar y soltar archivos justo dentro de su interfaz web.</span></span></li> + <li><span lang="es"><span>Muchas compañías proporcionan alojamiento y dominio simultáneamente.</span></span></li> +</ul> + +<h3 id="Utilizar_una_herramienta_en_línea_como_GitHub_o_Dropbox">Utilizar una herramienta en línea como GitHub o Dropbox</h3> + +<p>Algunas herramientas te permiten publicar tu sitio en línea:</p> + +<ul> + <li><a href="https://github.com/">GitHub</a> es un sitio de «codificación social». Te permite cargar repositorios de código para almacenarlos en el <strong>sistema de control de versiónes</strong> de <a href="http://git-scm.com/">Git</a>. De esta manera puedes colaborar en proyectos de código pues por defecto el sistema es de código abierto, lo que significa que cualquier persona en el mundo puede encontrar tu código en GitHub, usarlo, aprender de él y mejorarlo. ¡Puedes hacer esto con el código de otra persona también! Git es un <a href="https://git-scm.com/book/es/v2/Inicio---Sobre-el-Control-de-Versiones-Acerca-del-Control-de-Versiones">sistema de control de versiones</a> muy popular y GitHub es una comunidad muy importante y útil por lo que la mayor parte de empresas de tecnología ahora lo usan en su proceso laboral. GitHub tiene una característica muy útil llamada <a href="https://pages.github.com">GitHub Pages</a>, que te permite exponer el código de tu sitio web en vivo en la web.</li> + <li><a href="https://www.dropbox.com/">Dropbox</a> es un sistema de almacenamiento de archivos que te permite guardar los archivos en la web y tenerlos disponibles desde cualquier ordenador. Cualquier persona con una conexión a Internet puede acceder a cualquier carpeta de Dropbox que esté accesible al público. Si esa carpeta contiene los archivos del sitio web, estos serán visualizados como un sitio web de forma automática.</li> + <li><a href="https://cloud.google.com/appengine/">Google App Engine</a> es una poderosa plataforma que permite construir y ejecutar aplicaciones en la infraestructura de Google, ya sea que necesites construir una aplicación web de varios niveles desde cero o alojar un sitio web estático. Para obtener más información consulta <a href="/en-US/docs/Learn/Common_questions/How_do_you_host_your_website_on_Google_App_Engine">¿Cómo se aloja un sitio web en Google App Engine?</a> (en inglés).</li> +</ul> + +<p>A diferencia de la mayoría de alojamientos (servicios de <em>hosting</em>), tales herramientas son por lo general libres de utilizar, pero solo permiten un conjunto de funciones limitadas.</p> + +<h3 id="Utilizar_un_entorno_basado_en_web_como_CodePen">Utilizar un entorno basado en web como CodePen</h3> + +<p>Existe un número de aplicaciones web que emulan un entorno de desarrollo de sitios web, permitiendo que ingreses tu código HTML, CSS y Javascript y luego muestran los resultados de dicho código como un sitio web, ¡todo en una pestaña del navegador! En términos generales, estas herramientas son bastante sencillas, geniales para aprender, buenas para compartir código (por ejemplo, si quieres compartir con alguien una técnica o pedir ayuda en la depuración del código) y gratuitas para las funciones básicas. Además, mantienen tu página renderizada en una única dirección web. Sin embargo, las características básicas son muy limitadas y estas aplicaciones usualmente no proveen espacio de almacenamiento para recursos (como imágenes).</p> + +<p>Prueba con algunos de estos ejemplos y observa cuál es el que mejor se adapta a tu gusto:</p> + +<ul> + <li><a href="http://jsfiddle.net/">JSFiddle</a></li> + <li><a href="https://glitch.com/">Glitch</a></li> + <li><a href="http://jsbin.com/">JS Bin</a></li> + <li><a href="https://codepen.io/">CodePen</a></li> +</ul> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9471/jsbin-screen.png" style="display: block; height: 849px; margin: 0px auto; width: 1392px;"></p> + +<h2 id="Publicar_a_través_de_GitHub">Publicar a través de GitHub</h2> + +<p>Explicados estos tres métodos veamos ahora cómo publicar fácilmente, de forma muy visual e intuitiva, o bien por medio de comandos, tu sitio a través de <a href="https://pages.github.com/">GitHub Pages</a> (en inglés).</p> + +<h3 id="De_manera_visual_y_sin_necesidad_de_más_herramientas">De manera visual y sin necesidad de más herramientas</h3> + +<p>Esta no es la única manera, pero sí la que te permite poner manos a la obra inmediatamente.</p> + +<ol> + <li>Si aún no lo has hecho<a href="https://github.com/join"> da de alta una cuenta en GitHub</a>. Es simple y sencillo, solo debes verificar tu dirección de correo electrónico.</li> + <li>Una vez registrado, ingresa a tu cuenta en GitHub.com con tu usuario y contraseña suministrados al crear tu cuenta.</li> + <li>A continuación, necesitas crear un nuevo repositorio para tus archivos. Haz clic en el signo más (+) en la parte superior derecha de la página inicial de GitHub y selecciona <em>New Repository</em> (Nuevo repositorio).</li> + <li>En esta página, en la casilla <em>Repository name</em> (Nombre del repositorio), ingresa <kbd><em>usuario</em>.github.io</kbd>,<em> </em>donde <em>usuario</em> es tu nombre de usuario. Así por ejemplo, nuestro amigo Bob Smith ingresaría <kbd><em>bobsmith.github.io</em></kbd>. <img alt="" src="https://mdn.mozillademos.org/files/9479/github-create-repo.png" style="display: block; height: 849px; margin: 0px auto; width: 1392px;"></li> + <li>Opcionalmente escribe una corta descripción de tu sitio web en el campo <em>Description</em> para que recuerdes cuál es la temática que tratarás en él y selecciona la casilla de verificación <em>Public</em> (Público) si quieres que cualquier persona pueda ver los resultados de las ediciones que haces al sitio web que estás creando.</li> + <li>Marca la casilla de verificación <em>Initialize this repository with a README</em> (Inicializar este repositorio con un README (LÉAME)). Esto te permitirá clonar inmediatamente el repositorio a tu equipo. ¡Si vas a transferir tus archivos desde tu equipo al servidor de GitHub a través de un cliente de FTP (como se explica en la sección <em><a href="/es/docs/Learn/Getting_started_with_the_web/Publishing_your_website#Subir_tus_archivos_a_Github_a_través_de_la_línea_de_comandos">Subir tus archivos a GitHub a través de la línea de comandos</a></em>, a continuación), <u>no debes realizar este paso</u>!</li> + <li>Da clic en <em>Create repository</em> (Crear repositorio).</li> + <li>Arrastra y suelta el contenido de la carpeta de tu sitio web en tu repositorio. Cuando termines de pasar el contenido haz clic en <em>Commit changes</em> (Confirmar cambios). + <div class="blockIndicator note"> + <p><strong>Nota</strong>: cerciórate que tu carpeta tiene un archivo de nombre <kbd>index.html</kbd></p> + </div> + </li> + <li>En tu navegador desplázate a <kbd>username.github.io</kbd> para ver tu sitio web en línea. Por ejemplo, para el nombre de usuario Bob Smith, escribe <kbd>bobsmith.github.io</kbd>. + + + <div class="blockIndicator note"> + <p><strong>Nota</strong>: puede que tu página web tarde unos minutos en entrar en funcionamiento. Si tu sitio web no se muestra inmediatamente, espera unos minutos e inténtalo de nuevo.</p> + </div> + </li> +</ol> + +<h3 id="Subir_tus_archivos_a_GitHub_a_través_de_la_línea_de_comandos">Subir tus archivos a GitHub a través de la línea de comandos</h3> + +<p>No estamos diciendo que esta es la única manera, o la mejor, de publicar tu sitio, pero es gratis, decentemente simple y abarca algunas nuevas habilidades que encontrarás útiles en adelante.</p> + +<p>Antes que nada, <a href="http://git-scm.com/downloads">descarga e instala Git</a> en tu equipo. Este paso es necesario si vas a trabajar con los archivos de tu página web en él y luego los transferirás al servidor de GitHub.</p> + +<p>Sigue los pasos <strong>1 a 5</strong> y el <strong>7</strong> (recuerda omitir el 6) detallados en la anterior sección <em><a href="/es/docs/Learn/Getting_started_with_the_web/Publishing_your_website#De_manera_visual_y_sin_necesidad_de_m%C3%A1s_herramientas">De manera visual y sin necesidad de más herramientas</a></em>. Una vez hayas dado clic en <em>Create repository</em> (Crear repositorio) verás la siguiente ventana (¡no la cierres, más adelante necesitarás copiar información de allí!):</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9481/github-populate-repo.png" style="display: block; height: 849px; margin: 0px auto; width: 1392px;"></p> + +<p>En este punto ya estarás listo para poder utilizar la línea de comandos para subir los archivos de tu repositorio a GitHub. Una <em>línea de órdenes o de comandos</em> es una ventana donde escribes comandos que realizarán tareas como crear archivos y ejecutar programas, en lugar de utiizar la interfaz gráfica de usuario. Se debe parecer a algo como esto:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9483/command-line.png" style="display: block; height: 478px; margin: 0px auto; width: 697px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: si no te sientes cómodo utilizando la línea de comandos, podrías considerar usar <a href="http://git-scm.com/downloads/guis">Git graphical user interface</a> para realizar la misma tarea.</p> +</div> + +<p><span id="command-line">Todos los sistemas operativos vienen con una herramienta de línea de comandos:</span></p> + +<ul> + <li><strong>Windows</strong>: se puede acceder al <strong>Intérprete de comandos</strong> desde el menú que se presenta al pulsar <em>Win + X </em>(o abre el menú pulsando el botón secundario del ratón sobre el botón Inicio de Windows en la parte inferior izquierda del escritorio). Advierte que Windows tiene sus propias sintaxis de comandos diferente a las de Linux y MacOS X, así que los siguientes comandos pueden variar para tu máquina.</li> + <li><strong>MacOS X</strong>: <strong>Terminal</strong> puede ser hallada en Aplicaciones<em> > Utilidades</em>.</li> + <li><strong>Linux</strong>: usualmente puedes abrir una terminal con <em>Ctrl + Alt + T</em>. Si esto no funciona, busca <strong>Terminal </strong>en la barra de aplicaciones o en el menú.</li> +</ul> + +<p>Aunque este procedimiento pueda parecer un poco aterrador al principio no te preocupes, pronto te darás cuenta de lo básico. Darás órdenes al equipo en el terminal escribiendo un comando y presionando <kbd>Intro</kbd>.</p> + +<ol> + <li>Apunta la línea de comandos a tu directorio <code>sitio-prueba</code> (o como quiera que hayas llamado al directorio que contiene tu sitio web). Para esto utiliza el comando <code>cd</code> (es decir, <em>«change directory»</em>, «<em>cambiar de directorio»</em>). Aquí viene lo que deberías teclear si has ubicado tu sitio web en un directorio llamado <code>sitio-prueba</code> en tu escritorio: + + <pre class="brush: bash notranslate">cd Desktop/sitio-prueba</pre> + + <p>En Windows sería:</p> + + <pre class="notranslate">cd %USERPROFILE%\Desktop\sitio-prueba</pre> + </li> + <li>Cuando la línea de comandos esté apuntando dentro del directorio de tu sitio web, teclea el siguiente comando, que indica a la herramienta de <code>git</code> que transforme el directorio en un repositorio de Git: + <pre class="brush: bash notranslate">git init</pre> + </li> + <li class="syntaxbox"> + <p>A continuación, regresa a la ventana del sitio de GitHub que dejaste abierta. En esa página, la sección que interesa es <em>…or push an existing repository from the command line</em>. Deberías ver dos líneas de código listadas en esa sección. Copia toda la primera línea, pégala en la línea de comandos y presiona <kbd>Intro</kbd>. El comando debería verse similar a:</p> + + <pre class="brush: bash notranslate">git remote add origin https://github.com/bobsmith/bobsmith.github.io.gi</pre> + </li> + <li>A continuación, ingresa los siguientes dos comandos, presionando <kbd>Intro</kbd> después de cada uno. Estos preparan el código para cargar a GitHub y pedir a Git administrar estos archivos. + <pre class="brush: bash notranslate">git add --all <kbd>Intro</kbd> +git commit -m 'agregando archivos a mi repositorio' <kbd>Intro</kbd></pre> + </li> + <li>Finalmente, envía el codigo a GitHub tomando de la página web de GitHub en la que estás el segundo de los dos comandos del paso 3 e introdúcelo en el terminal: + <pre class="brush: bash notranslate">git push -u origin master</pre> + </li> + <li>Ahora cuando vayas a la direccion de red de tu página GitHub (<em>usuario.github.io</em>) en una nueva pestaña del navegador ¡deberías ver tu sitio en línea! Envíala por correo-e a tus amigos y presume de tu maestría.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: has tocado apenas la superficie de Git. Si te quedas atascado la <a href="https://help.github.com/es/github/working-with-github-pages/getting-started-with-github-pages">ayuda de GitHub en español</a> te será de gran apoyo.</p> +</div> + +<h3 id="Conocer_más_de_GitHub">Conocer más de GitHub</h3> + +<p>Si deseas hacer más cambios a tu sitio y enviarlos a GitHub, <span id="result_box" lang="es"><span>luego de modificar los archivos, debes ingresar los siguientes comandos (presionando <kbd>Intro</kbd> después de cada uno) para enviar esos cambios a GitHub:</span></span></p> + +<pre class="notranslate">git add --all <kbd>Intro</kbd> +git commit -m '<em>otro commit</em>' <kbd>Intro</kbd> +git push <kbd>Intro</kbd></pre> + +<p>Puedes reemplazar el texto <em>otro commit</em> con un mensaje más descriptivo respecto a los cambios que hiciste.</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>En este punto, deberías tener tu página web de ejemplo disponible en una dirección web única. ¡Bien hecho!</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9485/hosted-final-site.png" style="display: block; height: 1049px; margin: 0px auto; width: 878px;"></p> + +<h3 id="Ver_también">Ver también</h3> + +<ul> + <li><a href="/es/docs/Learn/Common_questions/Que_es_un_servidor_WEB">¿Qué es un servidor web?</a></li> + <li><a href="/es/docs/Learn/Common_questions/What_is_a_domain_name">¿Qué es un nombre de dominio?</a></li> + <li><a href="/es/docs/Learn/Common_questions/Cuanto_cuesta">¿Cuánto cuesta hacer algo en la web?</a></li> + <li><a href="http://alignedleft.com/resources/cheap-web-hosting">Cheap or free static web hosting </a>(Alojamiento web estático barato o gratuito) <em>de Scott Murray</em> tiene algunas ideas útiles sobre servicios disponibles aunque el sitio ya está algo desactualizado (en inglés).</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Getting_started_with_the_web/JavaScript_basics", "Learn/Getting_started_with_the_web/How_the_Web_works","Learn/Getting_started_with_the_web")}}</p> diff --git a/files/es/learn/getting_started_with_the_web/what_will_your_website_look_like/index.html b/files/es/learn/getting_started_with_the_web/what_will_your_website_look_like/index.html new file mode 100644 index 0000000000..fb6ced116f --- /dev/null +++ b/files/es/learn/getting_started_with_the_web/what_will_your_website_look_like/index.html @@ -0,0 +1,113 @@ +--- +title: ¿Cuál será la apariencia de tu sitio Web? +slug: Learn/Getting_started_with_the_web/What_will_your_website_look_like +tags: + - Activos + - Aprender + - Composición + - Contenido + - Desaprobado + - Diseño + - Fuentes + - Imagenes + - Novato + - Planificar + - Principiante + - Tipos de Letra + - paso a paso +translation_of: Learn/Getting_started_with_the_web/What_will_your_website_look_like +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Getting_started_with_the_web/Installing_basic_software", "Learn/Getting_started_with_the_web/Dealing_with_files", "Learn/Getting_started_with_the_web")}}</div> + +<div class="summary"> +<p><em>¿Cómo se verá tu sitio web?</em>, analiza el trabajo de planificación y diseño que debes realizar para tu sitio web antes de escribir el código, incluyendo: "¿qué información ofrece mi sitio web?", "¿qué tipos de letra y colores quiero?" y "¿qué hace mi sitio?".</p> +</div> + +<h2 id="Lo_primero_es_lo_primero_planificación">Lo primero es lo primero: planificación</h2> + +<p>Antes de hacer nada, necesitas algunas ideas. ¿Qué debería hacer realmente tu sitio web?; Un sitio web puede hacer básicamente cualquier cosa, pero, en tu primer intento, debes mantener las cosas simples. Comenzarás creando una página web simple con un encabezado, una imagen y algunos párrafos.</p> + +<p>Para comenzar, deberás responder estas preguntas:</p> + +<ol> + <li><strong>¿De qué trata tu sitio web?</strong>, ¿te gustan los perros, Nueva York o Pac-Man?</li> + <li><strong>¿Qué información presentas sobre el tema?</strong>; Escribe un título y algunos párrafos y piensa en una imagen que te gustaría mostrar en tu página.</li> + <li><strong>¿Cómo se ve tu sitio web</strong>, en términos simples de alto nivel?, ¿cuál es el color de fondo?, ¿qué tipo de letra es apropiado: formal, caricaturesca, atrevida y fuerte, sutil?</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Los proyectos complejos necesitan pautas detalladas que incluyan todos los detalles de los colores, los tipos de letra, el espacio entre los elementos de una página, el estilo de escritura adecuado, etc. Esto, a veces, se denomina guía de diseño, sistema de diseño o libro de marcas, y puedes ver un ejemplo en el <a href="https://design.firefox.com/photon/">Sistema de diseño de fotones de Firefox</a>.</p> +</div> + +<h2 id="Haz_un_bosquejo_de_tu_diseño">Haz un bosquejo de tu diseño</h2> + +<p>A continuación, toma papel y lápiz y dibuja aproximadamente cómo deseas que se vea tu sitio. Para tu primera página web simple, no hay mucho que esbozar, pero deberías adquirir el hábito de hacerlo ahora. Realmente ayuda, ¡no tienes que ser Van Gogh!</p> + +<p><img alt="Bosquejo" src="https://mdn.mozillademos.org/files/9239/website-drawing-scan.png" style="display: block; height: 460px; margin: 0px auto; width: 640px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Incluso en sitios web reales y complejos, los equipos de diseño suelen comenzar con bocetos en papel y luego crean maquetas digitales utilizando un editor de gráficos o tecnologías web.</p> + +<p>Los equipos web suelen incluir tanto un diseñador gráfico como un diseñador de {{Glossary("UX", "experiencia de usuario")}} (UX). Los diseñadores gráficos ensamblan las imágenes del sitio web. Los diseñadores de experiencia de usuario tienen un papel algo más abstracto al abordar cómo los usuarios experimentarán e interactuarán con el sitio web.</p> +</div> + +<h2 id="Elige_tus_activos">Elige tus activos</h2> + +<p>En este punto, es bueno comenzar a reunir el contenido que eventualmente aparecerá en tu página web.</p> + +<h3 id="Texto">Texto</h3> + +<p>Aún debes tener los párrafos y el título de antes. Mantenlos cerca.</p> + +<h3 id="Color_del_tema">Color del tema</h3> + +<p>Para elegir un color, ve al <a href="https://developer.mozilla.org/es/docs/Web/CSS/CSS_Colors/Color_picker_tool">Selector de color</a> y busca un color que te guste . Al hacer clic en un color, verás un extraño código de seis caracteres como <code>#660066</code>. Eso se llama <em>código hexadecimal</em> (abreviatura de hexadecimal) y representa tu color. Copia el código en un lugar seguro por ahora.</p> + +<p><img alt="Color del tema" src="https://mdn.mozillademos.org/files/8975/Screenshot%20from%202014-11-03%2017:40:49.png" style="border-style: solid; border-width: 1px; height: 262px; width: 448px;"></p> + +<h3 id="Imágenes">Imágenes</h3> + +<p>Para elegir una imagen, ve a <a href="https://www.google.com/imghp?gws_rd=ssl">Imágenes Google</a> y busca algo adecuado.</p> + +<ol> + <li>Cuando encuentres la imagen que deseas, haz clic en la imagen para obtener una vista ampliada de la misma.</li> + <li>Haz clic con el botón derecho en la imagen (Ctrl+clic en una Mac), elige <em>Guardar imagen como...</em> y elige un lugar seguro para guardar tu imagen. Alternativamente, copia la dirección web de la imagen de la barra de direcciones de tu navegador para su posterior uso.</li> +</ol> + +<p><img alt="Imágenes" src="https://mdn.mozillademos.org/files/16599/updated-google-images.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Ten en cuenta que la mayoría de las imágenes en la web, incluidas las de Imágenes Google, están protegidas por derechos de autor. Para reducir tu probabilidad de violar los derechos de autor, puedes utilizar el filtro de licencias de Google. Haz clic en el botón <em>Herramientas</em> y luego en la opción <em>Derechos de uso</em> resultante que aparece a continuación. Debes elegir una opción como <em>Etiquetado para reutilización</em>.</p> + +<p><img alt="Etiquetado para reutilización" src="https://mdn.mozillademos.org/files/16598/updated-google-images-licensing.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<h3 id="Tipos_de_letra">Tipos de letra</h3> + +<p>Para elegir un tipo de letra:</p> + +<ol> + <li>Ve a <a href="http://www.google.com/fonts">Google Fonts</a> y desplázate hacia abajo en la lista hasta que encuentres una que te guste. También puedes utilizar los controles de la derecha para filtrar aún más los resultados.</li> + <li>Haz clic en el icono "más" (Agregar a) junto al tipo de letra que desees.</li> + <li>Haz clic en el botón "<em>*Familia seleccionada</em>" en el panel en la parte inferior de la página ("*" depende de cuántos tipos de letra hayas seleccionado).</li> + <li>En el cuadro emergente, puedes ver y copiar las líneas de código que Google te brinda en tu editor de texto para guardarlas para más adelante.</li> +</ol> + +<p><img alt="Archivos de tipo de letra" src="https://mdn.mozillademos.org/files/13871/font1.png" style="border-style: solid; border-width: 1px; height: 359px; width: 600px;"></p> + +<p><img alt="Tipos de letra" src="https://mdn.mozillademos.org/files/13873/font2.png" style="border-style: solid; border-width: 1px; height: 608px; width: 600px;"></p> + +<p>{{PreviousMenuNext("Learn/Getting_started_with_the_web/Installing_basic_software", "Learn/Getting_started_with_the_web/Dealing_with_files", "Learn/Getting_started_with_the_web")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li id="Instalacion_de_software_basico">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico", "Instalación de software básico")}}</li> + <li id="Cual_sera_la_apariencia_de_tu_sitio_web">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Cual_sera_la_apariencia_de_tu_sitio_web", "Cuál será la apariencia de tu sitio web")}}</li> + <li id="Manejo de archivos">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Dealing_with_files", "Manejo de archivos")}}</li> + <li id="Conceptos_basicos_de_HTML">{{web.link("/es/docs/Learn/Getting_started_with_the_web/HTML_basics", "Conceptos básicos de HTML")}}</li> + <li id="Conceptos_basicos_de_CSS">{{web.link("/es/docs/Learn/Getting_started_with_the_web/CSS_basics", "Conceptos básicos de CSS")}}</li> + <li id="Conceptos_basicos_de_JavaScript">{{web.link("/es/docs/Learn/Getting_started_with_the_web/JavaScript_basics", "Conceptos básicos de JavaScript")}}</li> + <li id="Publicar_tu_sitio_web">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Publishing_your_website", "Publicar tu sitio web")}}</li> + <li id="Como_funciona_la_web">{{web.link("/es/docs/Learn/Getting_started_with_the_web/Cómo_funciona_la_Web", "Cómo funciona la Web")}}</li> +</ul> diff --git a/files/es/learn/herramientas_y_pruebas/cross_browser_testing/index.html b/files/es/learn/herramientas_y_pruebas/cross_browser_testing/index.html new file mode 100644 index 0000000000..73bd6299a1 --- /dev/null +++ b/files/es/learn/herramientas_y_pruebas/cross_browser_testing/index.html @@ -0,0 +1,39 @@ +--- +title: Cross browser testing +slug: Learn/Herramientas_y_pruebas/Cross_browser_testing +translation_of: Learn/Tools_and_testing/Cross_browser_testing +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Este módulo se centra en probar proyectos web en diferentes navegadores. Nos fijamos en la identificación de su público objetivo (por ejemplo, qué usuarios, navegadores y dispositivos son los que más le preocupan?), cómo realizar las pruebas, los principales problemas a los que se enfrentará con los diferentes tipos de código y cómo mitigarlos, qué herramientas son las más útiles para ayudarle a probar y solucionar problemas, y cómo utilizar la automatización para acelerar las pruebas.</p> + +<h2 id="Prerequisitos">Prerequisitos</h2> + +<p>Debería aprender los conceptos básicos de los lenguajes <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a> y <a href="/en-US/docs/Learn/JavaScript">JavaScript</a> básicos antes de intentar utilizar las herramientas que se detallan aquí.</p> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Introduction">Introducción a la prueba de navegadores cruzados</a></dt> + <dd>Este artículo comienza el módulo proporcionando una visión general del tema de la prueba de navegadores cruzados, respondiendo a preguntas como "¿qué es la prueba de navegadores cruzados? y "¿cuáles son los tipos de problemas más comunes que se encuentran?</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Testing_strategies">Estrategias para la realización de las pruebas</a></dt> + <dd> + <p>A continuación, profundizamos en la realización de pruebas, la identificación de un público objetivo (por ejemplo, qué navegadores, dispositivos y otros segmentos deben ser probados), estrategias de pruebas de baja fiabilidad (obtenga una gama de dispositivos y algunas máquinas virtuales y realice pruebas ad-hoc cuando sea necesario), estrategias de alta tecnología (automatización, uso de aplicaciones de pruebas dedicadas), y pruebas con grupos de usuarios.</p> + </dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/HTML_and_CSS">Manejo de problemas comunes de HTML y CSS</a></dt> + <dd> + <p>Con el conjunto de escenas, ahora veremos específicamente los problemas comunes entre navegadores que encontrará en código HTML y CSS, y qué herramientas se pueden usar para evitar que ocurran problemas o para solucionarlos. Esto incluye el código de hilado, la entrega de prefijos CSS, el uso de herramientas de desarrollo de navegadores para localizar problemas, el uso de polifiltros para añadir soporte a los navegadores, la solución de problemas de diseño con capacidad de respuesta, y mucho más.</p> + </dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/JavaScript">Manejo de problemas comunes de JavaScript</a></dt> + <dd> + <p>Ahora veremos los problemas comunes de JavaScript en todos los navegadores y cómo solucionarlos. Esto incluye información sobre el uso de herramientas de desarrollo del navegador para localizar y solucionar problemas, el uso de polifondos y bibliotecas para solucionar los problemas, el funcionamiento de las funciones modernas de JavaScript en navegadores antiguos, y mucho más.</p> + </dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility">Manejo de problemas comunes de accesibilidad</a></dt> + <dd>A continuación, nos centramos en la accesibilidad, proporcionando información sobre problemas comunes, cómo realizar pruebas sencillas y cómo utilizar las herramientas de auditoría/automatización para encontrar problemas de accesibilidad.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Feature_detection">Implementación de la detección de características</a></dt> + <dd>La detección de funciones implica determinar si un navegador soporta un determinado bloque de código, y ejecutar un código diferente dependiendo de si lo hace (o no), de modo que el navegador siempre puede proporcionar una experiencia de trabajo en lugar de bloquearse/error en algunos navegadores. Este artículo detalla cómo escribir su propia detección de características simples, cómo usar una biblioteca para acelerar la implementación y características nativas para la detección de características como <code>@supports</code>.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Automated_testing">Introducción a las pruebas automatizadas</a></dt> + <dd>La realización manual de pruebas en varios navegadores y dispositivos, varias veces al día, puede resultar tediosa y consumir mucho tiempo. Para manejar esto eficientemente, debe familiarizarse con las herramientas de automatización. En este artículo, analizamos lo que está disponible, cómo utilizar los corredores de tareas y los conceptos básicos de cómo utilizar las aplicaciones de automatización de pruebas de navegadores comerciales, como Sauce Labs y Browser Stack.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment">Configuración de su propio entorno de automatización de pruebas</a></dt> + <dd>En este artículo, le enseñaremos cómo instalar su propio entorno de automatización y ejecutar sus propias pruebas utilizando Selenium/WebDriver y una biblioteca de pruebas como Selenium-webdriver for Node. También veremos cómo integrar su entorno de pruebas local con aplicaciones comerciales como las que se comentaron en el artículo anterior.</dd> +</dl> diff --git a/files/es/learn/herramientas_y_pruebas/github/index.html b/files/es/learn/herramientas_y_pruebas/github/index.html new file mode 100644 index 0000000000..62646f1cc4 --- /dev/null +++ b/files/es/learn/herramientas_y_pruebas/github/index.html @@ -0,0 +1,92 @@ +--- +title: Git y GitHub +slug: Learn/Herramientas_y_pruebas/GitHub +tags: + - Aprender + - GitHub + - Principiante + - Web + - git +translation_of: Learn/Tools_and_testing/GitHub +--- +<div>{{LearnSidebar}}</div> + +<p><font><font>Todos los desarrolladores utilizarán algún tipo de </font></font><strong><font><font>sistema de control de versiones</font></font></strong><font><font> ( </font></font><strong><font><font>VCS</font></font></strong><font><font> ), una herramienta que les permita colaborar con otros desarrolladores en un proyecto sin peligro de que sobrescriban el trabajo de los demás, y volver a las versiones anteriores de la base de código si existe un problema descubierto más tarde. </font><font>El VCS más popular (al menos entre los desarrolladores web) es </font></font><strong><font><font>Git</font></font></strong><font><font>, junto con </font></font><strong><font><font>GitHub</font></font></strong><font><font>, un sitio que proporciona alojamiento para tus repositorios y varias herramientas para trabajar con ellos. </font><font>Este módulo tiene como objetivo enseñarte lo que necesitas saber sobre ambos.</font></font></p> + +<h2 id="Introducción"><font><font>Introducción</font></font></h2> + +<p><font><font>Los VCS son esenciales para el desarrollo de software:</font></font></p> + +<ul> + <li><font><font>Es raro que trabajes en un proyecto completamente por tu cuenta, y tan pronto como comiences a trabajar con otras personas, comenzarás a correr el riesgo de entrar en conflicto con el trabajo del otro, es decir, cuando ambos intentan actualizar simultáneamente la misma pieza de código. </font><font>Debes tener algún tipo de mecanismo para administrar las ocurrencias y, como resultado, evitar la pérdida de trabajo.</font></font></li> + <li><font><font>Cuando trabajes en un proyecto por tu cuenta o con otros, querrás poder hacer una copia de seguridad del código en un lugar central, para que no se pierda si tu computadora se daña.</font></font></li> + <li><font><font>También querrás poder volver a versiones anteriores si más tarde descubres un problema. </font><font>Es posible que hayas empezado a hacer esto en tu propio trabajo mediante la creación de diferentes versiones de un mismo archivo, por ejemplo </font></font><code>myCode.js</code><font><font>, </font></font><code>myCode_v2.js</code><font><font>, </font></font><code>myCode_v3.js</code><font><font>, </font></font><code>myCode_final.js</code><font><font>, </font></font><code>myCode_really_really_final.js</code><font><font>, etc, pero esto es muy propenso a errores y poco fiable.</font></font></li> + <li><font><font>Los diferentes miembros del equipo generalmente querrán crear sus propias versiones separadas del código (llamadas </font></font><strong><font><font>ramas</font></font></strong><font><font> en Git), trabajar en una nueva característica en esa versión y luego fusionarla de manera controlada (en GitHub usamos </font></font><strong><font><font>solicitudes de extracción</font></font></strong><font><font>) con la versión maestra cuando hayan terminado con ella.</font></font></li> +</ul> + +<p><font><font>Los VCS proporcionan herramientas para satisfacer las necesidades anteriores. </font></font><a href="https://git-scm.com/" rel="noopener"><font><font>Git</font></font></a><font><font> es un ejemplo de VCS, y </font></font><a href="https://github.com/" rel="noopener"><font><font>GitHub</font></font></a><font><font> es un sitio web + infraestructura que proporciona un servidor Git más una serie de herramientas realmente útiles para trabajar con repositorios git individuales o en equipo, como informar problemas con el código, herramientas de revisión, características de administración de proyectos tal como asignación de tareas, estados de tareas, y más.</font></font></p> + +<div class="blockIndicator note"> +<p><strong><font><font>Nota</font></font></strong><font><font>: Git en realidad es un </font><font>sistema de control de versiones </font></font><em><font><font>distribuido</font></font></em><font><font>, lo cual significa que se realiza una copia completa del repositorio que contiene la base de código en tu computadora (y en la de todos los demás). </font><font>Realizas cambios en tu propia copia, y luego empujas esos cambios nuevamente al servidor, donde un administrador decidirá si fusiona tus cambios con la copia maestra.</font></font></p> +</div> + +<h3 id="¿Quieres_convertirte_en_un_desarrollador_web_front-end"><font><font>¿Quieres convertirte en un desarrollador web front-end?</font></font></h3> + +<p><font><font>Hemos preparado un curso que incluye toda la información esencial que necesitas para alcanzar tu objetivo.</font></font></p> + +<div class="in-page-callout webdev"> +<p><a class="cta primary" href="/docs/Learn/Front-end_web_developer">Comenzar</a></p> +</div> + +<h2 id="Prerequisitos"><font><font>Prerequisitos</font></font></h2> + +<p><font><font>Para usar Git y GitHub, necesitas:</font></font></p> + +<ul> + <li><font><font>Una computadora de escritorio con Git instalado (consulta la </font></font><a href="https://git-scm.com/downloads" rel="noopener"><font><font>página de descargas de Git</font></font></a><font><font>).</font></font></li> + <li><font><font>Una herramienta para usar Git. </font><font>Dependiendo de cómo te guste trabajar, puedes usar un </font></font><a href="https://git-scm.com/downloads/guis/" rel="noopener"><font><font>cliente Git con GUI</font></font></a><font><font> (te recomendamos GitHub Desktop, SourceTree o Git Kraken) o simplemente usar una ventana de la terminal. </font><font>De hecho, probablemente sea útil que conozcas al menos los conceptos básicos de los comandos de la terminal git, incluso si tienes la intención de usar una GUI.</font></font></li> + <li><font><font>Una </font></font><a href="https://github.com/join" rel="noopener"><font><font>cuenta de GitHub</font></font></a><font><font>. </font><font>Si aún no tienes una, regístrate ahora usando el enlace provisto.</font></font></li> +</ul> + +<p><font><font>En términos de conocimiento previo, no necesitas saber nada sobre desarrollo web, Git/GitHub o VCS para iniciar este módulo. </font><font>Sin embargo, se recomienda que conozcas algo de codificación para que tengas conocimientos informáticos razonables y algún código para almacenar en tus repositorios.</font></font></p> + +<p><font><font>También es preferible que tengas algunos conocimientos básicos de la terminal, por ejemplo, moverte entre directorios, crear archivos y modificar la variable del sistema </font></font><code>PATH</code><font><font>.</font></font></p> + +<div class="blockIndicator note"> +<p><strong><font><font>Nota</font></font></strong><font><font>: Github no es el único sitio/conjunto de herramientas que puedes usar con Git. </font><font>Hay otras alternativas, como </font></font><a href="https://about.gitlab.com/" rel="noopener"><font><font>GitLab,</font></font></a><font><font> que podrías probar, y también podrías intentar configurar tu propio servidor Git y usarlo en lugar de GitHub. </font><font>Solo nos hemos quedado con GitHub en este curso para proporcionar una forma única que funciona.</font></font></p> +</div> + +<h2 id="Guías"><font><font>Guías</font></font></h2> + +<p><font><font>Ten en cuenta que los enlaces a continuación te llevan a recursos en sitios externos. </font><font>Eventualmente intentaremos tener nuestro propio curso Git/GitHub dedicado, pero por ahora, esto te ayudará a familiarizarte con el tema en cuestión.</font></font></p> + +<dl> + <dt><a href="https://guides.github.com/activities/hello-world/" rel="noopener"><font><font>Hola mundo (de GitHub)</font></font></a></dt> + <dd><font><font>Este es un buen lugar para comenzar: esta guía práctica te permite comenzar a usar GitHub, aprender los conceptos básicos de Git, como crear repositorios y ramas, realizar confirmaciones, abrir y fusionar solicitudes de extracción.</font></font></dd> + <dt><a href="https://guides.github.com/introduction/git-handbook/" rel="noopener"><font><font>Manual de Git (en GitHub)</font></font></a></dt> + <dd><font><font>Este Manual de Git profundiza un poco más, explicando qué es un VCS, qué es un repositorio, cómo funciona el modelo básico de GitHub, comandos y ejemplos de Git, y más.</font></font></dd> + <dt><a href="https://guides.github.com/activities/forking/" rel="noopener"><font><font>Bifurcación de proyectos (de GitHub)</font></font></a></dt> + <dd><font><font>Bifurcar proyectos es esencial cuando deseas contribuir al código de otra persona. </font><font>Esta guía explica cómo.</font></font></dd> + <dt><a href="https://help.github.com/en/articles/about-pull-requests" rel="noopener"><font><font>Acerca de las solicitudes de extracción (de GitHub)</font></font></a></dt> + <dd><font><font>Una útil guía para administrar las solicitudes de extracción, la forma en que los cambios de código sugeridos se entregan a los repositorios de las personas para su consideración.</font></font></dd> + <dt><a href="https://guides.github.com/features/issues/" rel="noopener"><font><font>Dominando las incidencias (de GitHub)</font></font></a></dt> + <dd><font><font>Las incidencias son como un foro para tu proyecto GitHub, donde las personas pueden hacer preguntas e informar problemas, y tú puede administrar las actualizaciones (por ejemplo, asignar personas para solucionar problemas, aclarar el problema, informar a las personas que las cosas están solucionadas). </font><font>Este artículo te brinda lo que necesitas saber sobre las incidencias.</font></font></dd> +</dl> + +<div class="blockIndicator note"> +<p><strong><font><font>Nota</font></font></strong><font><font>: Hay </font></font><strong><font><font>mucho más</font></font></strong><font><font> que puedes hacer con Git y GitHub, pero creemos que lo anterior representa lo mínimo que necesitas saber para comenzar a usar Git de manera efectiva. </font><font>A medida que profundices en Git, comenzarás a darte cuenta de que es fácil equivocarse cuando comienzas a usar comandos más complicados. </font><font>No te preocupes, incluso los desarrolladores web profesionales encuentran a Git confuso a veces, y a menudo resuelven problemas buscando soluciones en la web, o consultando sitios como </font></font><a href="https://github.com/k88hudson/git-flight-rules/blob/master/README_es.md" rel="noopener"><font><font>Reglas de vuelo para Git</font></font></a><font><font> y </font></font><a href="https://dangitgit.com/es" rel="noopener"><font><font>Dangit, ¡git!</font></font></a></p> +</div> + +<h2 id="Ve_también"><font><font>Ve también</font></font></h2> + +<ul> + <li><a href="https://guides.github.com/introduction/flow/" rel="noopener"><font><font>Comprender el flujo de GitHub</font></font></a></li> + <li><a href="https://git-scm.com/docs" rel="noopener"><font><font>Lista de comandos de Git</font></font></a></li> + <li><a href="https://guides.github.com/features/mastering-markdown/" rel="noopener"><font><font>Reducción de dominio</font></font></a><font><font> (el formato de texto en el que escribe en relaciones públicas, comentarios de insidencias y archivos </font></font><code>.md</code><font><font>).</font></font></li> + <li><a href="https://guides.github.com/features/pages/" rel="noopener"><font><font>Introducción a las páginas de GitHub</font></font></a><font><font> (cómo publicar demostraciones y sitios web en GitHub).</font></font></li> + <li><a href="https://learngitbranching.js.org/" rel="noopener"><font><font>Aprende la ramificación de Git</font></font></a></li> + <li><a href="https://github.com/k88hudson/git-flight-rules" rel="noopener"><font><font>Reglas de vuelo para Git</font></font></a><font><font> (un compendio muy útil de formas de lograr cosas específicas en Git, incluida la forma de corregir las cosas cuando te equivocaste).</font></font></li> + <li> + <p><a href="https://dangitgit.com/" rel="noopener"><font><font>Dangit, git! </font></font></a><font><font>(otro compendio útil, específicamente de formas de corregir las cosas cuando te equivocaste).</font></font></p> + </li> +</ul> diff --git a/files/es/learn/herramientas_y_pruebas/index.html b/files/es/learn/herramientas_y_pruebas/index.html new file mode 100644 index 0000000000..a147c98f65 --- /dev/null +++ b/files/es/learn/herramientas_y_pruebas/index.html @@ -0,0 +1,58 @@ +--- +title: Herramientas y pruebas +slug: Learn/Herramientas_y_pruebas +tags: + - Accesibilidad + - Aprender + - Aterrizaje + - CSS + - CodificaciónDeSecuenciasDeComandos + - HTML + - Herramientas + - JavaScript + - Navegador cruzado + - Principiante + - Pruebas de usuario + - Tema + - Testing + - automatización +translation_of: Learn/Tools_and_testing +--- +<div> +<p>{{LearnSidebar}}</p> + +<p>Una vez que haya comenzado a sentirse cómodo programando con tecnologías web básicas (como HTML, CSS y JavaScript), y comience a adquirir más experiencia, leer más recursos y aprender más trucos y consejos, comenzará a encontrar todos tipo de herramientas, desde CSS y JavaScript ya enrollados, aplicaciones de prueba y automatización, y muchas más. A medida que sus proyectos web se vuelvan más grandes y complejos, querrá comenzar a aprovechar algunas de estas herramientas y elaborar planes de prueba confiables para su código. Esta parte del área de aprendizaje tiene como objetivo brindarle lo que necesita para comenzar y tomar decisiones informadas.</p> +</div> + +<p class="summary"> </p> + +<p>{{LearnSidebar}}</p> + +<p>La industria de la web es un lugar emocionante para trabajar, pero no está exenta de complicaciones. Las tecnologías principales que utilizamos para crear sitios web son bastante estables ahora, pero se están agregando nuevas características todo el tiempo, y nuevas herramientas, que facilitan el trabajo con estas tecnologías y están construidas sobre estas tecnologías, aparecen constantemente. Además de eso, todavía tenemos que mantener la compatibilidad entre navegadores en la parte superior de nuestras mentes y asegurarnos de que nuestro código sigue las mejores prácticas que permiten que nuestros proyectos funcionen en diferentes navegadores y dispositivos que nuestros usuarios utilizan para navegar por la Web, y ser utilizable por personas con discapacidad.</p> + +<p>Determinar qué herramientas debería usar puede ser un proceso difícil, por lo que hemos escrito este conjunto de artículos para informarle qué tipos de herramientas están disponibles, qué pueden hacer por usted y cómo hacer uso de los favoritos actuales de la industria.</p> + +<p> </p> + +<div class="note"> +<p>Nota: Debido a que aparecen nuevas herramientas y las antiguas pasan de moda todo el tiempo, hemos redactado deliberadamente este material para que sea lo más neutral posible. Queremos enfocarnos ante todo en los tipos generales de tareas que estas herramientas lo ayudarán a lograr. y seguir prescribiendo herramientas específicas al mínimo. Obviamente, necesitamos mostrar el uso de las herramientas para demostrar técnicas específicas, pero ten en cuenta que no necesariamente recomendamos estas herramientas como la mejor o la única forma de hacer las cosas; en la mayoría de los casos, existen otras formas, pero queremos brindarte una idea clara. Metodología que funciona.</p> +</div> + +<h2 id="Camino_de_aprendizaje">Camino de aprendizaje</h2> + +<p> </p> + +<p>Debería aprender los conceptos básicos de los lenguajes <a href="https://developer.mozilla.org/en-US/docs/Learn/HTML">HTML</a>, <a href="https://developer.mozilla.org/en-US/docs/Learn/CSS">CSS</a>, y <a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript">JavaScript</a> antes de intentar usar las herramientas que se detallan aquí. Por ejemplo, deberá conocer los fundamentos de estos idiomas antes de comenzar a depurar problemas en códigos web complejos, o hacer un uso efectivo de las bibliotecas de JavaScript, o escribir pruebas y ejecutarlas en su código utilizando corredores de prueba, etc.</p> + +<p>Primero necesitas una base sólida.</p> + +<p> </p> + +<h2 id="Módulos">Módulos</h2> + +<dl> + <dt><span class="tlid-translation translation"><span title="">Herramientas de desarrollo web en el mundo real (TBD)</span></span></dt> + <dd>En este módulo, exploramos los diferentes tipos de herramientas de desarrollo web disponibles. Esto incluye la revisión de los tipos de tareas más comunes a las que se le puede pedir que resuelva, cómo pueden encajar en un flujo de trabajo y las mejores herramientas disponibles actualmente para llevar a cabo esas tareas.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing">Pruebas de navegadores cruzados</a></dt> + <dd>Este módulo analiza específicamente el área de prueba de proyectos web en diferentes navegadores. Aquí vemos cómo identificar a su público objetivo (por ejemplo, qué usuarios, navegadores y dispositivos necesita preocuparse más), cómo realizar las pruebas, los principales problemas que enfrentará con los diferentes tipos de código y cómo solucionar o mitigue esos problemas, qué herramientas son más útiles para ayudarlo a probar y solucionar problemas, y cómo utilizar la automatización para acelerar las pruebas.</dd> +</dl> diff --git a/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/index.html b/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/index.html new file mode 100644 index 0000000000..e9bdd36eca --- /dev/null +++ b/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/index.html @@ -0,0 +1,133 @@ +--- +title: Entendiendo los frameworks de JavaScript del lado del cliente +slug: Learn/Herramientas_y_pruebas/Lado-del-cliente_JavaScript_frameworks +tags: + - Aprender + - Principiante +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Los frameworks de JavaScript son una parte esencial del desarrollo web front-end moderno, los cuales proveen a los desarrolladores herramientas probadas y testeadas para la creación de aplicaciones web interactivas y escalables. Muchas empresas modernas utilizan frameworks como parte estándar de sus herramientas, por lo que muchos trabajos de desarrollo front-end en la actualidad requieren experiencia en frameworks.</p> + +<p class="summary">Como aspirante a desarrollador front-end, puede resultar difícil saber por dónde empezar cuando se trata de aprender sobre frameworks; hay muchos frameworks diferentes para elegir, nuevas opciones surgen todo el tiempo. En su mayoría funcionan de forma similar, pero hacen algunas cosas de manera diferente, y hay algunas cosas específicas con las que se debe tener cuidado a la hora de usar frameworks.</p> + +<p class="summary">En esta serie de artículos, tenemos como objetivo brindarte un punto de partida cómodo que te sirva de ayuda para comenzar a aprender sobre frameworks. Nuestra intención no es enseñarte, de manera exhaustiva, todo lo que se necesita saber sobre React/ReactDOM, o Vue, o algún otro framework en específico; la documetación de los equipos de los frameworks (entre otros recursos) ya cumplen esta función. En su lugar, queremos brindarte respaldo y responder primero a preguntas más fundamentales como:</p> + +<ul> + <li class="summary">¿Por qué debería hacer uso de un framework? ¿Qué problemas me resuelven estos?</li> + <li class="summary">¿Qué preguntar a la hora de escoger un framework? ¿En verdad necesito usar un framework?</li> + <li class="summary">¿Qué características tienen los frameworks? ¿Cómo funcionan en general y cómo se diferencian las maneras en que los frameworks implementan estas características?</li> + <li class="summary">¿Cómo se relacionan con JavaScript "puro" o HTML?</li> +</ul> + +<p class="summary">Después de esto, proveeremos algunos tutoriales que cubren los aspectos básicos de algunos de los diferentes frameworks que existen, de manera que puedas tener el contexto y la familiaridad suficientes para poder empezar a profundizar por tu propia cuenta. Queremos que avances y aprendas sobre los frameworks de manera pragmática, de forma tal que se tengan presente las buenas prácticas esenciales de la plataforma web, como lo es la accesibilidad.</p> + +<p class="summary"><strong><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">Empieza ahora con "Introducción a los frameworks del lado del cliente"</a></strong></p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Antes de intentar aprender sobre los frameworks del lado del cliente, es recomendable que conozcamos los conceptos básicos de los principales lenguajes de la web: <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, y —especialmente— <a href="/en-US/docs/Learn/JavaScript">JavaScript</a>.</p> + +<p>Como resultado, tu código será más consistente y profesional, por lo que podrás solucionar problemas con mayor confianza si comprende las características fundamentales de la plataforma web sobre las que se basan los frameworks.</p> + +<h2 id="Guías_introductorias">Guías introductorias</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">1. Introducción a los frameworks del lado del cliente</a></dt> + <dd>Comenzamos nuestro estudio sobre los frameworks con una descripción general del área, repasando un poco de historia sobre JavaScript y los frameworks, por qué estos existen, y qué nos brindan; por donde empezar al momento de escoger un framework por aprender y qué alternativas existen a los frameworks del lado del cliente.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features">2. Características principales de los frameworks</a></dt> + <dd>Cada framework destacado de JavaScript tiene un enfoque diferente para actualizar el DOM, manejar los eventos del navegador, y brindarte una experiencia de desarrollo satisfactoria. En este artículo, exploraremos las características principales de "los cuatro grandes" frameworks, observando cómo estos tienden a operar desde un nivel alto, al igual que las diferencias entre ellos.</dd> +</dl> + +<h2 id="Tutoriales_de_React">Tutoriales de React</h2> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Los tutoriales de React se probaron por última vez en mayo de 2020, con React/ReactDOM 16.13.1 y create-react-app 3.4.1.</p> + +<p>Si necesitas comparar tu código con nuestra versión, puedes encontrar una versión terminada de la muestra del código de la aplicación React en nuestro <a href="https://github.com/mdn/todo-react">repositorio todo-react</a>. Para una versión en vivo, consulta <a href="https://mdn.github.io/todo-react-build/">https://mdn.github.io/todo-react-build/</a>.</p> +</div> + +<dl> + <dt><a href="/es/docs/Learn/Herramientas_y_pruebas/Lado-del-cliente_JavaScript_frameworks/React_getting_started">1. Primeros pasos en React</a></dt> + <dd>En este artículo conoceremos React. Descubriremos algunos detalles sobre su trasfondo y casos de uso, configuraremos una cadena básica de herramientas para React en nuestra computadora local, crearemos y jugaremos con una aplicación inicial sencilla, mientras aprendemos —durante el proceso— un poco acerca de cómo funciona React.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">2. Comenzando con nuestra lista de tareas de React</a></dt> + <dd>Digamos que se nos ha encomendado la tarea de crear una prueba de concepto (Proof of Concept — PoC) en React: una aplicación que permita a los usuarios agregar, editar y eliminar tareas en las que se quiera trabajar, pero que también permita marcar las tareas como completadas sin eliminarlas. Este artículo te guiará en la organización de la estructura y los estilos básicos del componente <code>App</code>, de manera que esté listo para la definición e interactividad de componentes individuales, los cuales agregaremos más adelante.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">3. Basando nuestra aplicación React en componentes</a></dt> + <dd>Hasta este momento, nuestra aplicación no hace gran cosa. Antes de que podamos hacerla funcionar, tenemos que dividirla en componentes descriptivos y manejables. React no tiene reglas estrictas para lo que, se considera o no, un componente, ¡eso depende de ti! En este artículo, te mostraremos una forma raznoable de dividir nuestra aplicación en componentes.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">4. Interactividad en React: eventos y estado</a></dt> + <dd>Habiendo elaborado nuestro plan de componentes, es hora de comenzar a actualizar nuestra aplicación, para que pase de ser una interfaz de usuario completamente estática a una que nos permita, realmente, interactuar y cambiar las cosas. Es eso mismo lo que haremos en este artículo, profundizando en los eventos y el estado a medida que avancemos.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">5. Interactividad en React: edición, filtrado, renderizado condicional</a></dt> + <dd>A medida que nos acercamos al final de nuestro viaje en React (al menos por ahora), agregaremos los toques finales a las áreas principales de funcionalidad en nuestra aplicación de lista de tareas. Esto incluye permitir la edición de tareas existentes y el filtrado de la lista de tareas entre todas las tareas, las completadas, y las incompletas. A lo largo del capítulo, veremos la renderización condicional de la interfaz de usuario.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">6. Accesibilidad en React</a></dt> + <dd>En el artículo final de nuestro tutorial, nos enfocaremos en la accesibilidad (broma intencional), incluyendo la gestión del enfoque en React, la cual puede mejorar la usabilidad y reducir la confusión para usuarios que navegan tanto, a través de lectores de pantalla, como solo del teclado.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">7. Recursos sobre React</a></dt> + <dd>En nuestro artículo final, te brindamos una lista de recursos sobre React, los cuales podrás utilizar para avanzar más en tu aprendizaje.</dd> +</dl> + +<h2 id="Tutoriales_de_Ember">Tutoriales de Ember</h2> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Los tutoriales de Ember se probaron por última vez en mayo de 2020, con Ember/Ember CLI versión 3.18.0.</p> + +<p>Si necesitas comparar tu código con nuestra versión, puedes encontrar una versión terminada de la muestra del código de la aplicación Ember en nuestro <a href="https://github.com/NullVoxPopuli/ember-todomvc-tutorial/tree/master/steps/00-finished-todomvc/todomvc">repositorio ember-todomvc-tutorial</a>. Para una versión en vivo, consulta <a href="https://nullvoxpopuli.github.io/ember-todomvc-tutorial/">https://nullvoxpopuli.github.io/ember-todomvc-tutorial/</a> (esto también incluye algunas características adicionales que no se cubren en este tutorial).</p> +</div> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started">1. Primeros pasos en Ember</a></dt> + <dd>En nuestro primer artículo de Ember veremos cómo funciona Ember y para qué resulta útil, instalaremos la cadena de herramientas de Ember de manera local, crearemos una aplicación de muestra, y luego realizaremos una configuración inicial para prepararla para el desarrollo.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization">2. Estructura de una aplicación Ember y cómo se basa en componentes</a></dt> + <dd>En este artículo, continuaremos planificando la estructura de nuestra aplicación Ember TodoMVC, agregando el HTML necesario y luego dividiendo esa estructura HTML en componentes.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state">3. Interactividad de Ember: eventos, clases, y estado</a></dt> + <dd>En este punto, comenzaremos a agregar un poco de interactividad a nuestra aplicación, dándole la capacidad de agregar y mostrar nuevos elementos de tareas por hacer. A medida que avanzamos, veremos el uso de eventos en Ember, la creación de clases de componentes para contener código JavaScript que controle las funciones interactivas, y la configuración de un servicio para hacer seguimiento del estado de los datos de nuestra aplicación.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer">4. Interactividad de Ember: funcionalidad del footer, renderizado condicional</a></dt> + <dd>Ahora es momento de comenzar a abordar la funcionalidad del footer en nuestra aplicación. Aquí haremos que el contador de tareas pendientes se actualice de manera que muestre el número correcto de tareas pendientes por completar, y aplicaremos correctamente los estilos a las tareas completadas (es decir, aquellos donde la casilla de verificación ha sido marcada). También conectaremos nuestro botón "Borrar completados". A lo largo del capítulo, aprenderemos sobre el uso de la renderización condicional en nuestras plantillas.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing">5. Enrutamiento en Ember</a></dt> + <dd>En este artículo aprendemos sobre enrutamiento o el filtrado basado en URL, como a veces se lo denomina. Lo usaremos para proporcionar una URL única para cada una de las tres vistas de tareas: "Todas", "Activas" y "Completadas".</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources">6. Recursos sobre y solución de problemas</a></dt> + <dd>En nuestro artículo final sobre Ember, te proporcionamos una lista de recursos que puedes utilizar para avanzar más en tu aprendizaje, además de información útil para la solución problemas y otra información.</dd> +</dl> + +<h2 id="Tutoriales_de_Vue">Tutoriales de Vue</h2> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Los tutoriales de Vue se probaron por última vez en mayo de 2020, con Vue 2.6.11.</p> + +<p>Si necesitas comparar tu código con nuestra versión, puedes encontrar una versión terminada de la muestra del código de la aplicación Vue en nuestro <a href="https://github.com/mdn/todo-vue">repositorio todo-vue</a>. Para una verisón en vivo, consulta <a href="https://mdn.github.io/todo-vue/dist/">https://mdn.github.io/todo-vue/dist/</a>.</p> +</div> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started">1. Primeros pasos en Vue</a></dt> + <dd>A continuación, presentamos Vue, el tercero de nuestros frameworks. En este artículo, veremos un poco sobre el origen de Vue, aprenderemos cómo instalarlo y crear un nuevo proyecto, estudiaremos la estructura de alto nivel de todo el proyecto y de un componente individual, veremos cómo ejecutar el proyecto localmente y prepararlo para comenzar a construir nuestro ejemplo.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component">2. Creando nuestro primer componente de Vue</a></dt> + <dd>Ahora es momento de profundizar en Vue y crear nuestro propio componente personalizado: comenzaremos creando un componente para representar cada elemento en la lista de tareas. Durante el artículo, aprenderemos sobre algunos conceptos importantes, como llamar a componentes dentro de otros componentes, pasarles datos a través de props y guardar el estado de los datos.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists">3. Renderizando una lista de componentes de Vue</a></dt> + <dd><span class="author-d-1gg9uz65z1iz85zgdz68zmqkz84zo2qoxwoxz78zz83zz84zz69z2z80zgwxsgnz83zfkt5e5tz70zz68zmsnjz122zz71z">En este punto, tenemos un componente completamente funcional; ahora estamos listos para agregar varios componentes <code>ToDoItem</code> a nuestra aplicación. En este artículo, veremos cómo agregar un conjunto de datos de elementos de tareas a nuestro componente <code>App.vue</code>, el cual luego repasaremos en bucle, mostrando dentro de los componentes de <code>ToDoItem</code> mediante el uso de la directiva <code>v-for</code>. </span></dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models">4. Agregar una nueva forma de tareas pendientes: eventos, métodos y modelos de Vue</a></dt> + <dd>Ahora tenemos datos de muestra listos y un ciclo que toma cada bit de datos y lo renderiza dentro de un <code>ToDoItem</code> en nuestra aplicación. Lo que realmente necesitamos a continuación es la capacidad de permitirle a nuestros usuarios que introuduzcan sus propios elementos de tareas pendientes en la aplicación, y para ello, necesitaremos un <code><input></code> de texto, un evento para efectuar una vez se envíen los datos, un método por accionar al momento del envío para agregar los datos y volver a renderizar la lista, y un modelo para controlar los datos. Esto es lo que cubriremos en este artículo.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling">5. Agregando estilos a los componentes de Vue con CSS</a></dt> + <dd>Por fin ha llegado el momento de hacer que nuestra aplicación luzca un poco mejor. En este artículo, exploraremos las diferentes formas de agregar estilos a los componentes de Vue con CSS.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties">6. Usando propiedades calculadas de Vue</a></dt> + <dd>En este artículo, agregaremos un contador que muestre el número de tareas completadas, utilizando una función de Vue llamada propiedades calculadas. Estos funcionan de manera similar a los métodos, pero solo se vuelven a ejecutar cuando cambia una de sus dependencias.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering">7. Renderización condicional en Vue: editando tareas existentes</a></dt> + <dd>Ahora es momento de agregar una de las principales piezas de la funcionalidad que aún nos falta: la capacidad de editar tareas existentes. Para hacer esto, aprovecharemos las capacidades de renderizado condicional de Vue, es decir, <code>v-if</code> y <code>v-else</code>, los cuales nos permiten alternar entre la vista de una tarea existente y una vista de edición donde podremos actualizar las etiquetas de las tareas. También veremos cómo agregar funcionalidad para eliminar tareas.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management">8. Gestión de enfoque con Vue refs</a></dt> + <dd>Ya estamos cerca de terminar con Vue. La última funcionalidad a considerar es la gestión del enfoque, o dicho de otra manera, cómo podemos mejorar la accesibilidad de nuestra aplicación desde el teclado. Veremos el uso de Vue refs para manejar esto, una característica avanzada que nos permite tener acceso directo a los nodos DOM subyacentes debajo del DOM virtual, o acceso directo desde un componente a la estructura DOM interna de un componente interno.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources">9. Recursos sobre Vue</a></dt> + <dd>Ahora, completaremos nuestro estudio de Vue brindándote una lista de recursos que podrás utilizar para avanzar en tu aprendizaje, además de algunos otros consejos útiles.</dd> +</dl> + +<h2 id="¿Cuales_frameworks_hemos_escogido">¿Cuales frameworks hemos escogido?</h2> + +<p>Hacemos pública nuestra serie inicial de artículos con guías enfocadas en tres de los principales frameworks que existen: React/ReactDOM, Ember, y Vue. Esto se debe a varias un razones:</p> + +<ul> + <li>Son opciones populares que estarán disponibles por un largo tiempo. Al igual que con cualquier otra herramienta de software, es bueno apegarse a opciones que son desarrolladas de manera activa, lo que indica que, probablemente, no serán descontinuadas dentro de poco, lo que las convierte en complementos atractivos para mostrar como habilidades a la hora de buscar un trabajo.</li> + <li>Tienen comunidades sólidas y una buena documentación. Es muy importante poder obtener ayuda al aprender un tema complejo, especialmente cuando recién se está comenzando.</li> + <li>No contamos con los recursos para cubrir todos los frameworks modernos. Una lista así resultaría muy difícil de mantener actualizada, ya que todo el tiempo están surgiendo nuevos frameworks.</li> + <li>Como principiante, tratar de escoger en qué concentrarte entre la gran cantidad de opciones disponibles es un gran problema. Por lo tanto, resulta útil mantener una lista corta.</li> +</ul> + +<p>Queremos decir esto desde un principio: <strong>no</strong> hemos escogido los frameworks en los que nos estamos enfocando porque pensamos que son los mejores o porque los respaldamos de alguna manera. Simplemente, consideramos que obtienen una puntuación alta de acuerdo a los criterios anteriores.</p> + +<p>Ten en cuenta que esperábamos poder incluir más frameworks en la publicación inicial, pero que decidimos publicar el contenido y agregar, más adelante, otras guías, en lugar de retrasarlo más. Si tu framework favorito no se encuentra listado en este contenido y te gustaría ayudar a cambiar esto, ¡no dudes en discutirlo con nosotros! Puedes contactarnos a través de <a href="https://wiki.mozilla.org/Matrix">Matrix</a>, o <a href="https://discourse.mozilla.org/c/mdn">Discourse</a>, o enviarnos un correo electrónico a la <a href="mailto:mdn-admins@mozilla.org">lista mdn-admins</a>.</p> diff --git a/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/react_getting_started/index.html b/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/react_getting_started/index.html new file mode 100644 index 0000000000..09c28f11a9 --- /dev/null +++ b/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/react_getting_started/index.html @@ -0,0 +1,476 @@ +--- +title: Primeros pasos en React +slug: >- + Learn/Herramientas_y_pruebas/Lado-del-cliente_JavaScript_frameworks/React_getting_started +tags: + - Aprender + - Aprendiz + - Principiante +translation_of: >- + Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</div> + +<p class="summary">En este artículo conoceremos React. Descubriremos algunos detalles sobre su trasfondo y casos de uso, configuraremos una cadena básica de herramientas para React en nuestra computadora local, crearemos y jugaremos con una aplicación inicial sencilla, mientras aprendemos —durante el proceso— un poco acerca de cómo funciona React.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td> + <p>Familiaridad con los lenguajes <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, y <a href="/en-US/docs/Learn/JavaScript">JavaScript</a>, conocimiento del <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">terminal/línea de comandos</a>.</p> + + <p>React usa una sintaxis HTML-en-JavaScript llamada JSX (JavaScript y XML). Estar familiarizado con HTML y JavaScript te ayudará a aprender JSX, y a identificar —en una mejor manera— si los errores en tu aplicación están relacionados con JavaScript o con el más específico dominio de React.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Configurar un entorno de desarrollo local para React, crear una aplicación inicial, y entender los aspectos básicos de su funcionamiento.</td> + </tr> + </tbody> +</table> + +<h2 id="Hola_React">Hola, React</h2> + +<p>Como su eslogan oficial señala, <a href="https://es.reactjs.org/">React</a> es una biblioteca para construir interfaces de usuario. React no es un <em>framework</em> — ni siquiera se limita a la web. React es utilizado con otras bibliotecas para renderizar en ciertos entornos. Por ejemplo, <a href="https://reactnative.dev/">React Native</a> puede usarse para desarrollar aplicaciones móviles; <a href="https://facebook.github.io/react-360/">React 360</a> permite crear aplicaciones de realidad virtual; además de otras posibilidades.</p> + +<p>Al desarrollar para la web, los desarrolladores usan React en conjunto con <a href="https://reactjs.org/docs/react-dom.html">ReactDOM</a>. React y ReactDOM son, a menudo, considerados al igual que —y utilizados para resolver los mismo problemas que— otros verdaderos frameworks de desarrollo web. Cuando nos referimos a React como un "framework", estamos trabajando con este significado coloquial.</p> + +<p>El objetivo principal de React es minimizar los errores que ocurren cuando los desarrolladores construyen interfaces de usuario. Esto lo hace mediante el uso de componentes — piezas de código lógicas y auto-contenidas que describen una parte de la interfaz del usuario. Estos componentes se pueden juntar para crear una interfaz de usuario completa, y React abstrae la mayor parte del trabajo de renderizado, permitiéndote enfocarte en el diseño de la interfaz.</p> + +<h2 id="Casos_de_uso">Casos de uso</h2> + +<p>A diferencia de los otros frameworks vistos en este módulo, React no impone reglas estrictas sobre convenciones de código u organización de archivos. Esto le permite a los equipos establecer las convenciones que funcionen mejor para ellos y adoptar React de la manera en que deseen. React puede manejar un solo botón, algunas piezas de una interfaz o la interfaz de usuario completa de una aplicación.</p> + +<p>Si bien React <em>puede</em> usarse para <a href="https://es.reactjs.org/docs/add-react-to-a-website.html">pequeñas piezas de una interfaz</a>, no resulta tan sencillo "introducirlo" en una aplicación como sería el caso de una biblioteca como jQuery —o incluso de un framework, como Vue—, por lo que viene a ser más abordable cuando construimos una aplicación completamente con React.</p> + +<p>Además, muchos de los beneficios de la experiencia del desarrollador de una aplicación React, como codificar interfaces con JSX, requieren un proceso de compilación. Agregar un compilador como Babel a un sitio web hace que el código se ejecute de manera lenta, por lo que los desarrolladores a menudo configuran dichas herramientas con un paso de compilación. Podrá decirse que React tiene un gran requisito de herramientas, pero se puede aprender.</p> + +<p>Este artículo se enfocará en el caso de uso de usar React para renderizar la interfaz de usuario completa de una aplicación, usando herramientas proporcionadas por la propia herramienta de Facebook <a href="https://create-react-app.dev/">create-react-app</a>.</p> + +<h2 id="¿Cómo_React_usa_JavaScript">¿Cómo React usa JavaScript?</h2> + +<p>React utiliza características modernas de JavaScript para muchos de sus patrones. El punto donde más se aleja de JavaScript se refleja en el uso de la sintaxis <a href="https://es.reactjs.org/docs/introducing-jsx.html">JSX</a>, la que, a su vez, amplía la sintaxis de JavaScript para que código similar a HTML pueda formar parte del mismo. Por ejemplo:</p> + +<pre class="brush: js notranslate">const heading = <h1>Mozilla Developer Network</h1>;</pre> + +<p>Esta constante "heading" se conoce como una <strong>expresión JSX</strong>. React puede usarla para representar la etiqueta <code><a href="/en-US/docs/Web/HTML/Element/Heading_Elements"><h1></a></code> en nuestra aplicación.</p> + +<p>Supongamos que, por razones semánticas, queremos envolver nuestro encabezado en una etiqueta <code><a href="/en-US/docs/Web/HTML/Element/header"><header></a></code>. El enfoque JSX nos permite anidar nuestros elementos entre sí, tal como lo hacemos con HTML:</p> + +<pre class="brush: js notranslate">const header = ( + <header> + <h1>Mozilla Developer Network</h1> + </header> +);</pre> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Los paréntesis en el fragmento anterior no son exclusivos de JSX y no tienen ningún efecto en la aplicación. Son una señal para ti (y tu computadora) de que las múltiples líneas de código que contiene forman parte de una misma expresión. También podríamos escribir la expresión del encabezado de esta manera:</p> + +<pre class="brush: js notranslate">const header = <header> + <h1>Mozilla Developer Network</h1> +</header></pre> + +<p>Sin embargo, esto luce un poco raro, ya que la etiqueta <code><a href="/en-US/docs/Web/HTML/Element/header"><header></a></code> que inicia la expresión no tiene sangría en la misma posición que su correspondiente etiqueta de cierre.</p> +</div> + +<p>Por supuesto, tu navegador no puede leer JSX sin ayuda. Al compilarla (usando una herramienta como <a href="https://babeljs.io/">Babel</a> o <a href="https://parceljs.org/">Parcel</a>), nuestra expresión de encabezado se vería así:</p> + +<pre class="brush: js notranslate">const header = React.createElement("header", null, + React.createElement("h1", null, "Mozilla Developer Network") +);</pre> + +<p>Es <em>posible</em> omitir el paso de la compilación y usar <code><a href="https://reactjs.org/docs/react-api.html#createelement">React.createElement()</a></code> para codificar la interfaz de usuario tú mismo. Sin embargo, al hacer esto, perderías el beneficio declarativo de JSX y tu código resultaría más difícil de leer. La compilación es un paso adicional en el proceso de desarrollo, pero muchos desarrolladores de la comunidad React piensan que la legibilidad de JSX vale la pena. Además, las herramientas populares hacen que la compilación de JSX a JavaScript sea parte de su proceso de configuración. No tendrás que configurar la compilación tú mismo, a menos que así lo quieras.</p> + +<p>Dado que JSX es una combinación de HTML y JavaScript, algunos desarrolladores lo encuentran intuitivo. Otros dicen que su naturaleza combinada lo hace confuso. Sin embargo, una vez que te sientas cómodo con JSX, te permitirá crear interfaces de usuario de forma más rápida e intuitiva, y permitirá que otros comprendan mejor tu base de código de un vistazo.</p> + +<p>Para leer más sobre JSX, consulta el artículo <a href="https://es.reactjs.org/docs/jsx-in-depth.html">JSX en profundidad</a> del equipo de React.</p> + +<h2 id="Configurando_tu_primera_aplicación_React">Configurando tu primera aplicación React</h2> + +<p>Hay muchas maneras de usar React, pero usaremos la herramienta create-react-app de la interfaz de línea de comandos (CLI, por sus siglas en inglés), como se mencionó anteriormente, la cual acelera el proceso de desarrollo de una aplicación React al instalar algunos paquetes y crear algunos archivos por ti, manejando las herramientas descritas anteriormente.</p> + +<p>Es posible <a href="https://es.reactjs.org/docs/add-react-to-a-website.html">agregar React a un sitio website sin usar create-react-app</a> copiando algunos elementos <code><a href="/en-US/docs/Web/HTML/Element/script"><script></a></code> en un archivo HTML, pero la CLI de create-react-app es un punto de partida común para las aplicaciones React. Su uso te permitirá dedicar más tiempo a crear tu aplicación y menos a preocuparte por la configuración.</p> + +<h3 id="Requerimientos">Requerimientos</h3> + +<p>Para usar create-react-app, necesitas tener instalado <a href="https://nodejs.org/en/">Node.js</a>. Se recomienda utilizar la versión de soporte a largo plazo (LTS, por sus siglas en inglés). Node incluye npm (el administrador de paquetes de nodos), y npx (el ejecutor de paquetes de nodos).</p> + +<p>También puedes usar el administrador de paquetes Yarn como alternativa, pero asumiremos que estarás usando npm en estos tutoriales. Consulta <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management">Conceptos básicos de administración de paquetes</a> para obtener más información sobre npm y yarn.</p> + +<p>Si estás usando Windows, necesitarás instalar algún software para darle paridad con el terminal Unix/macOS, y así poder usar los comandos del terminal mencionados en este tutorial. <strong>Gitbash</strong> (el cual viene como parte del <a href="https://gitforwindows.org/">conjunto de herramientas git para Windows</a>) o el <strong><a href="https://docs.microsoft.com/en-us/windows/wsl/about">Subsistema de Windows para Linux</a></strong> (<strong>WSL</strong>, por sus siglas en inglés) son ambos adecuados. Consulte el <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">Curso intensivo de línea de comandos</a> para obtener más información sobre estos y sobre los comandos de terminal en general.</p> + +<p>También ten en cuenta que React y ReactDOM producen aplicaciones que solo funcionan en un conjunto bastante moderno de navegadores (IE9+ a través de algunos polyfills). Se recomienda el uso de un navegador moderno como Firefox, Safari o Chrome cuando trabajes con estos tutoriales.</p> + +<p>Además, consulta lo siguiente para obtener más información:</p> + +<ul> + <li><a href="https://nodejs.org/en/knowledge/getting-started/npm/what-is-npm/">"¿Qué es npm?" en nodejs.org</a></li> + <li><a href="https://blog.npmjs.org/post/162869356040/introducing-npx-an-npm-package-runner">"Introducing npx" en el blog de npm</a></li> + <li><a href="https://create-react-app.dev/">La documentación de create-react-app</a></li> +</ul> + +<h3 id="Inicializando_tu_aplicación">Inicializando tu aplicación</h3> + +<p>create-react-app recibe un argumento: el nombre que te gustaría darle a tu aplicación. create-react-app usa este nombre para crear una nueva carpeta, luego crea los archivos necesarios dentro de la misma. Asegúrate de <code>cd</code> al lugar donde te gustaría que se guarde tu aplicación en tu disco duro, luego ejecuta lo siguiente en tu terminal:</p> + +<pre class="brush: bash notranslate">npx create-react-app moz-todo-react</pre> + +<p>Esto crea una carpeta <code>moz-todo-react</code>, y hace varias cosas dentro de la misma:</p> + +<ul> + <li>Instala algunos paquetes npm esenciales para la funcionalidad de la aplicación.</li> + <li>Escribe scripts para iniciar y servir la aplicación.</li> + <li>Crea una estructura de archivos y carpetas que definen la arquitectura básica de la aplicación.</li> + <li>Inicializa la carpeta como un repositorio de git, si tienes git instalado en tu computadora.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: si tienes instalado el administrador de paquetes yarn, create-react-app lo usará por defecto en lugar de npm. Si tienes ambos administradores de paquetes instalados y quieres, explícitamente, usar npm, puedes agregar el indicador <code>--use-npm</code> cuando ejecutes create-react-app:</p> + +<pre class="brush: bash notranslate">npx create-react-app moz-todo-react --use-npm</pre> +</div> + +<p>create-react-app mostrará una serie de mensajes en tu terminal mientras opera, ¡lo cual es normal! Esto puede tardar unos minutos, por lo que ahora podría ser un buen momento para preparar una taza de té.</p> + +<p>Una vez completado el proceso, <code>cd</code> a la carpeta <code>moz-todo-react</code> y ejecuta el comando <code>npm start</code>. Los scripts instalados por create-react-app comenzarán a servirse en un servidor local en <code>localhost:3000</code> y abrirán la aplicación en una nueva pestaña del navegador. Tu navegador mostrará algo como esto:</p> + +<p><img alt="Screenshot of Firefox MacOS, open to localhost:3000, showing the default create-react-app application" src="https://mdn.mozillademos.org/files/17203/default-create-react-app.png" style="border-style: solid; border-width: 1px; height: 980px; width: 1600px;"></p> + +<h3 id="Estructura_de_la_aplicación">Estructura de la aplicación</h3> + +<p>create-react-app nos provee todo lo que necesitamos para desarrollar una aplicación React. Su estructura inicial de archivos luce así:</p> + +<pre class="notranslate">moz-todo-react +├── README.md +├── node_modules +├── package.json +├── package-lock.json +├── .gitignore +├── public +│ ├── favicon.ico +│ ├── index.html +│ └── manifest.json +└── src + ├── App.css + ├── App.js + ├── App.test.js + ├── index.css + ├── index.js + ├── logo.svg + └── serviceWorker.js</pre> + +<p>La carpeta <strong><code>src</code></strong> es donde pasaremos la mayor parte de nuestro tiempo, ya que es donde reside el código fuente de nuestra aplicación.</p> + +<p>La carpeta <strong><code>public</code></strong> contiene archivos que serán leidos por tu navegador mientras desarrollas la aplicación; el más importante de ellos es <code>index.html</code>. React introduce tu código en este archivo de manera que tu navegador pueda ejecutarlo. Hay alguno que otro marcado que ayuda a create-react-app a funcionar, así que ten cuidado de no editarlo a menos que sepas lo que estás haciendo. Deberías cambiar el texto dentro del elemento <code><a href="/en-US/docs/Web/HTML/Element/title"><title></a></code> en este archivo para reflejar el título de tu aplicación. ¡Los títulos de página precisos son importantes para la accesibilidad!</p> + +<p>La carpeta <code>public</code> también será publicada cuando crees y despliegues una versión para producción de tu aplicación. No cubriremos el despliegue en este tutorial, pero deberías poder usar una solución similar a la descrita en nuestro tutorial <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Deployment">Despliegue de nuestra aplicación</a>.</p> + +<p>El archivo <code>package.json</code> contiene información sobre nuestro proyecto que Node.js/npm usa para mantenerlo organizado. Este archivo no es exclusivo de las aplicaciones React; create-react-app simplemente lo completa. No es necesario que entiendas este archivo en lo absoluto para completar este tutorial, sin embargo, si deseas obtener más información al respecto, puedes leer <a href="https://nodejs.org/en/knowledge/getting-started/npm/what-is-the-file-package-json/">What is the file `package.json`? en NodeJS.org</a>; también hablamos de ello en nuestro tutorial <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management">Conceptos básicos de administración de paquetes</a>.</p> + +<h2 id="Explorando_nuestro_primer_componente_React_—_<App>">Explorando nuestro primer componente React — <code><App/></code></h2> + +<p>En React, un <strong>componente</strong> es un módulo reutilizable que representa una parte de nuestra aplicación. Estas partes pueden ser grandes o pequeñas, pero, generalmente, están bien definidas: tienen un propósito único y obvio.</p> + +<p>Abramos <code>src/App.js</code>, ya que nuestro navegador nos pide que lo editemos. Este archivo contiene nuestro primer componente —<code>App</code>—, y algunas otras líneas de código:</p> + +<pre class="brush: js notranslate">import React from 'react'; +import logo from './logo.svg'; +import './App.css'; + +function App() { + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + Edit <code>src/App.js</code> and save to reload. + </p> + <a + className="App-link" + href="https://reactjs.org" + target="_blank" + rel="noopener noreferrer" + > + Learn React + </a> + </header> + </div> + ); +} +export default App;</pre> + +<p>El archivo <code>App.js</code> se compone de tres partes principales: algunas declaraciones <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/import">import</a></code> en la parte superior, el componente <code>App</code> en el medio, y una declaración <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/export">export</a></code> en la parte inferior. La mayoría de los componentes de React siguen este patrón.</p> + +<h3 id="Declaraciones_import">Declaraciones <code>import</code></h3> + +<p>Las declaraciones <code>import</code> en la parte superior del archivo le permiten a <code>App.js</code> utilizar código que ha sido definido en otra parte. Revisemos estas declaraciones más detalladamente.</p> + +<pre class="brush: js notranslate">import React from 'react'; +import logo from './logo.svg'; +import './App.css';</pre> + +<p>La primera declaración importa la biblioteca React como tal. Dado que React convierte el JSX que escribimos en <code>React.createElement()</code>, todos los componentes de React deben importar el módulo <code>React</code>. Si omites este paso, tu aplicación producirá un error.</p> + +<p>La segunda declaración importa un logotipo de <code>'./logo.svg'</code>. Observa el uso de <code>./</code> al principio de la ruta y la extensión <code>.svg</code> al final — estos nos indican que el archivo es local y que no es un archivo JavaScript. De hecho, el archivo <code>logo.svg</code> reside en nuestra carpeta raíz.</p> + +<p>No hace falta proveer una ruta o extensión al importar el módulo <code>React</code>, ya que este no es un archivo local. En cambio, aparece como una dependencia en nuestro archivo <code>package.json</code>. ¡Ten cuidado con esta distinción mientras trabajas en esta lección!</p> + +<p>La tercera declaración importa el CSS relacionado con nuestro componente <code>App</code>. Observa que no hay nombre de variable ni de directiva <code>from</code>. Esta sintaxis de importación en particular no es propia de la sintaxis de módulos de JavaScript. Esta proviene de Webpack, la herramienta que create-react-app usa para agrupar todos nuestros archivos JavaScript y enviarlos al navegador.</p> + +<h3 id="El_componente_App">El componente <code>App</code></h3> + +<p>Después de las importaciones, tenemos una función llamada <code>App</code>. Mientras que una mayor parte de la comunidad JavaScript prefiere nombres tipo <em>camel-case</em> como <code>helloWorld</code>, los componentes de React usan nombres de variables tipo <em>pascal-case</em>, como <code>HelloWorld</code>, para dejar en claro que un determinado elemento JSX es un componente de React y no una etiqueta HTML normal. Si llegaras a cambiar el nombre de la función <code>App</code> por <code>app</code>, tu navegador te mostraría un error.</p> + +<p>Vamos a darle un vistazo más detallado a <code>App</code>.</p> + +<pre class="brush: js notranslate">function App() { + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + Edit <code>src/App.js</code> and save to reload. + </p> + <a + className="App-link" + href="https://reactjs.org" + target="_blank" + rel="noopener noreferrer" + > + Learn React + </a> + </header> + </div> + ); +}</pre> + +<p>La función <code>App</code> devuelve una expresión JSX. Esta expresión define lo que tu navegador presenta en última instancia al DOM.</p> + +<p>Algunos elementos de la expresión tienen atributos, los cuales se escriben igual que en HTML, siguiendo un patrón de <code>atributo="valor"</code>. En la línea 3, la etiqueta de apertura <code><a href="/en-US/docs/Web/HTML/Element/div"><div></a></code> tiene un atributo <code>className</code>. Este es equivalente al atributo <code><a href="/en-US/docs/Web/HTML/Global_attributes/class">class</a></code> de HTML, pues dado que JSX es JavaScript, no podemos usar la palabra <code>class</code> —la cual está reservada—, lo que significa que JavaScript ya la usa para un propósito específico y causaría problemas en nuestro código. Algunos otros atributos HTML también se escriben de manera diferente en JSX (de como se escriben en HTML), por el mismo tipo de razón. Los revisaremos a medida que nos crucemos con estos.</p> + +<p>Tómate un momento para cambiar la etiqueta <code><a href="/en-US/docs/Web/HTML/Element/p"><p></a></code> en la línea 6 para que diga "¡Hola, mundo!", luego guarda los cambios. Notarás que este cambio se procesa inmediatamente en el servidor de desarrollo que se ejecuta en <code>http://localhost:3000</code> en tu navegador. Ahora elimina la etiqueta <code><a href="/en-US/docs/Web/HTML/Element/a"><a></a></code> y guarda los cambios; el enlace "Learn React" habrá desaparecido.</p> + +<p>Ahora, tu componente <code>App</code> debería lucir así:</p> + +<pre class="brush: js notranslate">function App() { + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + ¡Hola, mundo! + </p> + </header> + </div> + ); +}</pre> + +<h3 id="Declaraciones_export">Declaraciones <code>export</code></h3> + +<p>En la parte inferior del archivo <code>App.js</code>, la declaración <code>export default App</code> hace que nuestro componente <code>App</code> esté disponible para otros módulos.</p> + +<h2 id="Explorando_el_index">Explorando el index</h2> + +<p>Vamos a abrir el archivo <code>src/index.js</code>, ya que es en este donde el componente <code>App</code> está siendo utilizado. Este archivo es el punto de entrada para nuestra aplicación, e inicialmente luce así:</p> + +<pre class="brush: js notranslate">import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; +import * as serviceWorker from './serviceWorker'; + +ReactDOM.render(<App />, document.getElementById('root')); + +// If you want your app to work offline and load faster, you can change +// unregister() to register() below. Note this comes with some pitfalls. +// Learn more about service workers: https://bit.ly/CRA-PWA +serviceWorker.unregister();</pre> + +<p>Al gual que <code>App.js</code>, el archivo comienza importando todos los módulos JS y otros activos que necesita para ejecutarse. <code>src/index.css</code> contiene estilos globales que se aplican a toda nuestra aplicación. Podemos ver que nuestro componente <code>App</code> también es importado acá; su importación es posible gracias a la declaración <code>export</code> en la parte inferior de <code>App.js</code>.</p> + +<p>En la línea 7, se invoca la función <code>ReactDOM.render()</code> de React con dos argumentos:</p> + +<ul> + <li>El componente que queremos renderizar, <code><App /></code> en este caso.</li> + <li>El elemento DOM dentro del cual queremos que se renderice el componente, en este caso, el elemento con un ID de <code>root</code>. Si miras dentro de <code>public/index.html</code>, verás que este es un elemento <code><div></code> justo dentro de <code><body></code>.</li> +</ul> + +<p>Todo esto le indica a React que queremos renderizar nuestra aplicación React con el componente <code>App</code> como raíz, o primer componente.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: En JSX, los componentes de React y los elementos HTML deben tener, obligatoriamente, barras diagonales de cierre. Escribir solo <code><App></code> o solo <code><img></code> provocará un error.</p> +</div> + +<p>Los <a href="/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers">Service workers</a> son interesantes piezas de código que ayudan al rendimiento de las aplicaciones y permiten que las funciones de tus aplicaciones web funcionen sin conexión, pero estas no están dentro del alcance de este artículo. Puedes eliminar la línea 5, así como las líneas 9 a 12.</p> + +<p>Finalmente, tu archivo <code>index.js</code> debería verse así:</p> + +<pre class="brush: js notranslate">import React from 'react'; +import ReactDOM from 'react-dom'; +import './index.css'; +import App from './App'; + +ReactDOM.render(<App />, document.getElementById('root'));</pre> + +<h2 id="Variables_y_props">Variables y props</h2> + +<p>A continuación, usaremos algunas de nuestras habilidades de JavaScript para lograr sentirnos un poco más cómodos editando componentes y trabajando con datos en React. Hablaremos sobre cómo se usan las variables dentro de JSX, e introduciremos props, que son una forma de pasar datos a un componente (al que luego se puede acceder usando variables).</p> + +<h3 id="Variables_en_JSX">Variables en JSX</h3> + +<p>De vuelta en <code>App.js</code>, enfoquémonos en la línea 9:</p> + +<pre class="brush: js notranslate"><img src={logo} className="App-logo" alt="logo" /></pre> + +<p>Aquí, el valor del atributo <code>src</code> de la etiqueta <code><img /></code> está entre llaves. Así es como JSX reconoce las variables. Al encontrarse con <code>{logo}</code>, React sabrá que nos referimos a la importación del logotipo en la línea 2 de nuestra aplicación, y luego recuperará el archivo del logo y lo renderizará.</p> + +<p>Vamos a intentar crear una variable propia. Antes de la declaración return de <code>App</code>, agrega <code>const subject = "React";</code>. Tu componente <code>App</code> ahora debería verse así:</p> + +<pre class="brush: js notranslate">function App() { + const subject = "React"; + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + ¡Hola, mundo! + </p> + </header> + </div> + ); +}</pre> + +<p>Cambia la línea 8, de manera que se use la variable <code>subject</code> en vez de la palabra "mundo", así:</p> + +<pre class="brush: js notranslate">function App() { + const subject = "React"; + return ( + <div className="App"> + <header className="App-header"> + <img src={logo} className="App-logo" alt="logo" /> + <p> + ¡Hola, {subject}! + </p> + </header> + </div> + ); +}</pre> + +<p>Al guardar, tu navegador debería mostrar "¡Hola, React!" en vez de "¡Hola, mundo!"</p> + +<p>Las variables son convenientes, pero la que acabamos de configurar no hace gran uso de las funciones de React. Es allí donde entran los props.</p> + +<h3 id="Props_de_componentes">Props de componentes</h3> + +<p>Un <strong>prop</strong> es cualquier dato que se pasa a un componente de React. Los props se escriben dentro de las llamadas a los componentes y utilizan la misma sintaxis que los atributos HTML: <code>prop="value"</code>. Abramos <code>index.js</code> y démosle a la llamada de nuestro <code><App/></code> su primer prop.</p> + +<p>Agrega un prop de <code>subject</code> a la llamada del componente <code><App /></code>, con un valor de <code>Clarice</code>. Al terminar, tu código debería verse similar a este:</p> + +<pre class="brush: js notranslate">ReactDOM.render(<App subject="Clarice" />, document.getElementById('root'));</pre> + +<p>Volviendo a <code>App.js</code>, vamos a revisar nuevamente la función <code>App</code> como tal, la cual se lee así (acortando la declaración <code>return</code> por razones de brevedad):</p> + +<pre class="brush: js notranslate">function App() { + const subject = "React"; + return ( + // return statement + ); +}</pre> + +<p>Cambia la declaración de la función <code>App</code> de manera que tome <code>props</code> como un parámetro, y elimina la constante <code>subject</code>. Al igual que cualquier otro parámetro de una función, puedes pasar <code>props</code> a <code>console.log()</code> para imprimirlos en la consola de tu navegador. Continúa, haciendo esto antes de la declaración <code>return</code>, así:</p> + +<pre class="brush: js notranslate">function App(props) { + console.log(props); + return ( + // return statement + ); +}</pre> + +<p>Guarda tu archivo y revisa la consola JavaScript de tu navegador. Deberías ver registrado algo como esto:</p> + +<pre class="brush: js notranslate">Object { subject: "Clarice" }</pre> + +<p>La propiedad <code>subject</code> del objeto corresponde al prop <code>subject</code> que agregamos a la llamada de nuestro componente <code><App /></code>, y la cadena <code>Clarice</code> corresponde a su valor. Los props de componentes en React siempre se recopilan en objetos de esta manera.</p> + +<p>Ahora que <code>subject</code> es uno de nuestros props, usémoslo en <code>App.js</code>. Cambia la constante <code>subject</code> de manera que, en vez de definirla como la cadena <code>React</code>, estés leyendo el valor de <code>props.subject</code>. También puedes eliminar <code>console.log()</code>, si así lo quieres.</p> + +<pre class="brush: js notranslate">function App(props) { + const subject = props.subject; + return ( + // return statement + ); +}</pre> + +<p>Una vez guardes, la aplicación debería darte la bienvenida con un "¡Hola, Clarice!". Si regresas a <code>index.js</code>, editas el valor de <code>subject</code>, y guardas, el texto cambiará.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Esto nos lleva al final de nuestra introducción a React, la cual incluye cómo instalarlo de manera local, cómo crear una aplicación inicial, y cómo funcionan los conceptos básicos. En el próximo artículo comenzaremos a construir nuestra primera aplicación como tal: una lista de tareas pendientes. Sin embargo, antes de ello, recapitulemos algunas de las cosas que hemos aprendido.</p> + +<p>En React:</p> + +<ul> + <li>Los componentes pueden importar los módulos que necesitan y deben exportarse a sí mismos al final de sus archivos.</li> + <li>Las funciones de componentes se nombran con <code>PascalCase</code>.</li> + <li>Puedes leer las variables JSX poniéndolas entre llaves, <code>{así}</code>.</li> + <li>Algunos atributos JSX son diferentes a los atributos HTML, para evitar conflictos con las palabras reservadas de JavaScript. Por ejemplo, el atributo <code>class</code> de HTML se convierte en <code>className</code> en JSX. Ten en cuenta que los atributos de varias palabras se nombran con <code>camelCase</code>.</li> + <li>Los props se escriben como atributos dentro de las llamadas de componentes y se pasan a los componentes.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">Introducción a los frameworks del lado del cliente</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features">Características principales de los frameworks</a></li> + <li>React + <ul> + <li><a href="/es/docs/Learn/Herramientas_y_pruebas/Lado-del-cliente_JavaScript_frameworks/React_getting_started">Primeros pasos en React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">Comenzando con nuestra lista de tareas de React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">Basando nuestra aplicación React en componentes</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">Interactividad de React: eventos y estado</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">Interactividad de React: edición, filtrado, renderizado condicional</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">Accesibilidad en React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">Recursos sobre React</a></li> + </ul> + </li> + <li>Ember + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started">Primeros pasos en Ember</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization">Estructura de una aplicación Ember y cómo se basa en componentes</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state">Interactividad de Ember: eventos, clases, y estado</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer">Interactividad de Ember: funcionalidad del footer, renderizado condicional</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing">Enrutamiento en Ember</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources">Recursos sobre y solución de problemas</a></li> + </ul> + </li> + <li>Vue + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started">Primeros pasos en Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component">Creando nuestro primer componente de Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists">Renderizando una lista de componentes de Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models">Agregar una nueva forma de tareas pendientes: eventos, métodos y modelos de Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling">Agregando estilos a los componentes de Vue con CSS</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties">Usando propiedades calculadas de Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering">Renderización condicional en Vue: editando tareas existentes</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management">Gestión de enfoque con Vue refs</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources">Recursos sobre Vue</a></li> + </ul> + </li> + <li>Svelte + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started">Primeros pasos en Svelte</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_Todo_list_beginning">Comenzando con nuestra aplicación Svelte de lista de tareas</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_variables_props">Comportamiento dinámico en Svelte: trabajando con variables y props</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_components">Basando nuestra aplicación Svelte en componentes</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_reactivity_lifecycle_accessibility">Svelte avanzado: reactividad, ciclo de vida, accesibilidad</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_stores">Trabajando con Svelte stores</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_TypeScript">Compatibilidad con TypeScript en Svelte</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_deployment_next">Implementación y próximos pasos</a></li> + </ul> + </li> +</ul> diff --git a/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/vue_primeros_pasos/index.html b/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/vue_primeros_pasos/index.html new file mode 100644 index 0000000000..ea24ac2a81 --- /dev/null +++ b/files/es/learn/herramientas_y_pruebas/lado-del-cliente_javascript_frameworks/vue_primeros_pasos/index.html @@ -0,0 +1,294 @@ +--- +title: Primeros pasos con Vue +slug: >- + Learn/Herramientas_y_pruebas/Lado-del-cliente_JavaScript_frameworks/Vue_primeros_pasos +translation_of: Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</div> + +<p class="summary">Ahora vamos a introducir Vue, el tercero de nuestros frameworks. En este articulo vamos a ver un poco del background de Vue, aprenderemos cómo instalarlo y a crear un nuevo proyecto, estudiar la estructura de alto nivel de todo el proyecto y un componente individual, sabremos como correr el proyecto localmente, y tenerlo preparado para empezar a construir nuestro ejemplo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td> + <p>Familiaridad con los motores de los lenguajes <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, y <a href="/en-US/docs/Learn/JavaScript">JavaScript</a> languages, conocimiento del <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">terminal/command line</a>.</p> + + <p>Los componentes Vue son escritos como una combinacion de objectos Javascript que administran los datos de la app y una sintaxis de plantilla basada en HTML que se enlaza con la estructura DOM subyacente. Para la instalación, y para usar algunas de las caracteristicas mas avanzadas de Vue (como Componentes de archivos simples o renderizado de funciones), vas a necesitar un terminar con node + npm instalados.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Configurar un entorno de desarrollo local de Vue, crear una app de inicio y entender los principios de su funcionamiento.</td> + </tr> + </tbody> +</table> + +<h2 id="Un_Vue_más_claro">Un Vue más claro</h2> + +<p>Vue es un framework moderno de Javascript que proveé facilidades muy utiles para el mejoramiento progresivo- al contrario de otros frameworks, puedes usar Vue para mejorar un HTML exstente. Esto permite usar Vue como un remplazo agregado para una libreria como <a href="https://wiki.developer.mozilla.org/en-US/docs/Glossary/jQuery">JQuery</a>.</p> + +<p>Habiendo dicho esto, tambien puedes usar Vue para escribir completamente una aplicación de una sola página(SPAs).This allows you to create markup managed entirely by Vue, which can improve developer experience and performance when dealing with complex applications. It also allows you to take advantage of libraries for client-side routing and state management when you need to. Additionally, Vue takes a "middle ground" approach to tooling like client-side routing and state management. While the Vue core team maintains suggested libraries for these functions, they are not directly bundled into Vue. This allows you to select a different routing/state management library if they better fit your application.</p> + +<p>In addition to allowing you to progressively integrate Vue into your applications, Vue also provides a progressive approach to writing markup. Like most frameworks, Vue lets you create reusable blocks of markup via components. Most of the time, Vue components are written using a special HTML template syntax. When you need more control than the HTML syntax allows, you can write JSX or plain JavaScript functions to define your components.</p> + +<p>As you work through this tutorial, you might want to keep the <a href="https://vuejs.org/v2/guide/">Vue guide</a> and <a href="https://vuejs.org/v2/api/">API documentation</a> open in other tabs, so you can refer to them if you want more information on any sub topic.<br> + For a good (but potentially biased) comparison between Vue and many of the other frameworks, see <a href="https://vuejs.org/v2/guide/comparison.html">Vue Docs: Comparison with Other Frameworks</a>.</p> + +<h2 id="Installation">Installation</h2> + +<p>To use Vue in an existing site, you can drop one of the following <code><a href="/en-US/docs/Web/HTML/Element/script"><script></a></code> elements onto a page. This allows you to start using Vue on existing sites, which is why Vue prides itself on being a progressive framework. This is a great option when migrating an existing project using a library like JQuery to Vue. With this method, you can use a lot of the core features of Vue, such as the attributes, custom components, and data-management.</p> + +<ul> + <li> + <p>Development Script (Unoptimized, but includes console warnings. Great for development</p> + + <pre class="brush: html notranslate"><script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script></pre> + </li> + <li> + <p>Production Script (Optimized version, minimal console warnings. It is recommended that you specify a version number when including Vue on your site so that any framework updates do not break your live site without you knowing.)</p> + + <pre class="brush: html notranslate"><script src="https://cdn.jsdelivr.net/npm/vue@2"></script></pre> + </li> +</ul> + +<p>However, this approach has some limitations. To build more complex apps, you’ll want to use the <a href="https://www.npmjs.com/package/vue">Vue NPM package</a>. This will let you use advanced features of Vue and take advantage of bundlers like WebPack. To make building apps with Vue easier, there is a CLI to streamline the development process. To use the npm package & the CLI you will need:</p> + +<ol> + <li>Node.js 8.11+ installed.</li> + <li>npm or yarn.</li> +</ol> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you don't have the above installed, find out <a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line#Adding_powerups">more about installing npm and Node.js</a> here.</p> +</div> + +<p>To install the CLI, run the following command in your terminal:</p> + +<pre class="brush: bash notranslate">npm install --global @vue/cli</pre> + +<p>Or if you'd prefer to use yarn:</p> + +<pre class="brush: bash notranslate">yarn global add @vue/cli</pre> + +<p>Once installed, to initialize a new project you can then open a terminal in the directory you want to create the project in, and run <code>vue create <project-name></code>. The CLI will then give you a list of project configurations you can use. There are a few preset ones, and you can make your own. These options let you configure things like TypeScript, linting, vue-router, testing, and more.</p> + +<p>We’ll look at using this below.</p> + +<h2 id="Initializing_a_new_project">Initializing a new project</h2> + +<p>To explore various features of Vue, we will be building up a sample todo list app. We'll begin by using the Vue CLI to create a new app framework to build our app into. Follow the steps below:</p> + +<ol> + <li>In terminal, <code>cd</code> to where you'd like to create your sample app, then run <code>vue create moz-todo-vue</code>.</li> + <li>Use the arrow keys and <kbd>Enter</kbd> to select the "Manually select features" option.</li> + <li>The first menu you’ll be presented with allows you to choose which features you want to include in your project. Make sure that "Babel" and "Linter / Formatter" are selected. If they are not, use the arrow keys and the space bar to toggle them on. Once they are selected, press <kbd>Enter</kbd> to proceed.</li> + <li>Next you’ll select a config for the linter / formatter. Navigate to "Eslint with error prevention only" and hit <kbd>Enter</kbd> again. This will help us catch common errors, but not be overly opinionated.</li> + <li>Next you are asked to configure what kind of automated linting we want. Select "Lint on save". This will check for errors when we save a file inside the project. Hit <kbd>Enter</kbd> to continue.</li> + <li>Now, you will select how we want your config files to be managed. "In dedicated config files" will put your config settings for things like ESLint into their own, dedicated files. The other option, "In package.json", will put all of your config settings into the app's <code>package.json</code> file. Select "In dedicated config files" and push <kbd>Enter</kbd>.</li> + <li>Finally, you are asked if you want to save this as a preset for future options. This is entirely up to you. If you like these settings over the existing presets and want to use them again, type <kbd>y</kbd> , otherwise type <kbd>n</kbd>.</li> +</ol> + +<p>The CLI will now begin scaffolding out your project, and installing all of your dependencies.</p> + +<p>If you've never run the Vue CLI before, you'll get one more question — you'll be asked to choose a package manager. You can use the arrow keys to select which one you prefer. The Vue CLI will default to this package manager from now on. If you need to use a different package manager after this, you can pass in a flag <code>--packageManager=<package-manager></code>, when you run <code>vue create</code>. So if you wanted to create the <code>moz-todo-vue</code> project with npm and you'd previously chosen yarn, you’d run <code>vue create moz-todo-vue --packageManager=npm</code>.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: We've not gone over all of the options here, but you can <a href="https://cli.vuejs.org">find more information on the CLI</a> in the Vue docs.</p> +</div> + +<h2 id="Project_structure">Project structure</h2> + +<p>If everything went successfully, the CLI should have created a series of files and directories for your project. The most significant ones are as follows:</p> + +<ul> + <li><code>.eslintrc.js</code>: This is a config file for <a href="https://eslint.org/">eslint</a>. You can use this to manage your linting rules.</li> + <li><code>babel.config.js</code>: This is the config file for <a href="https://babeljs.io/">Babel</a>, which transforms modern JavaScript features being used in development code into older syntax that is more cross-browser compatible in production code. You can register additional babel plugins in this file.</li> + <li><code>.browserslistrc</code>: This is a config for <a href="https://github.com/browserslist/browserslist">Browserslist</a>. You can use this to control which browsers your tooling optimizes for.</li> + <li><code>public</code>: This directory contains static assets that are published, but not processed by <a href="https://webpack.js.org/">Webpack</a> during build (with one exception; <code>index.html</code> gets some processing). + <ul> + <li><code>favicon.ico</code>: This is the favicon for your app. Currently, it's the Vue logo.</li> + <li><code>index.html</code>: This is the template for your app. Your Vue app is run from this HTML page, and you can use lodash template syntax to interpolate values into it. + <div class="note"><strong>Note</strong>: this is not the template for managing the layout of your application — this template is for managing static HTML that sits outside of your Vue app. Editing this file typically only occurs in advanced use cases.</div> + </li> + </ul> + </li> + <li><code>src</code>: This directory contains the core of your Vue app. + <ul> + <li><code>main.js</code>: this is the entry point to your application. Currently, this file initializes your Vue application and signifies which HTML element in the <code>index.html</code> file your app should be attached to. This file is often where you register global components or additional Vue libraries.</li> + <li><code>App.vue</code>: this is the top-level component in your Vue app. See below for more explanation of Vue components.</li> + <li><code>components</code>: this directory is where you keep your components. Currently it just has one example component.</li> + <li><code>assets</code>: This directory is for storing static assets like CSS and images. Because these files are in the source directory, they can be processed by Webpack. This means you can use pre-processors like <a href="https://sass-lang.com/">Sass/SCSS</a> or <a href="https://stylus-lang.com/">Stylus</a>.</li> + </ul> + </li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: Depending on the options you select when creating a new project, there might be other directories present (for example, if you choose a router, you will also have a <code>views</code> directory).</p> +</div> + +<h2 id=".vue_files_single_file_components">.vue files (single file components)</h2> + +<p>Like in many front-end frameworks, components are a central part of building apps in Vue. These components let you break a large application into discrete building blocks that can be created and managed separately, and transfer data between each other as required. These small blocks can help you reason about and test your code.</p> + +<p>While some frameworks encourage you to separate your template, logic, and styling code into separate files, Vue takes the opposite approach. Using <a href="https://vuejs.org/v2/guide/single-file-components.html">Single File Components</a>, Vue lets you group your templates, corresponding script, and CSS all together in a single file ending in <code>.vue</code>. These files are processed by a JS build tool (such as Webpack), which means you can take advantage of build-time tooling in your project. This allows you to use tools like Babel, TypeScript, SCSS and more to create more sophisticated components.</p> + +<p>As a bonus, projects created with the Vue CLI are configured to use <code>.vue</code> files with Webpack out of the box. In fact, if you look inside the <code>src</code> folder in the project we created with the CLI, you'll see your first <code>.vue</code> file: <code>App.vue</code>.</p> + +<p>Let's explore this now.</p> + +<h3 id="App.vue">App.vue</h3> + +<p>Open your <code>App.vue</code> file — you’ll see that it has three parts: <code><template></code>, <code><script></code>, and <code><style></code>, which contain the component’s template, scripting, and styling information. All Single File Components share this same basic structure.</p> + +<p><code><template></code> contains all the markup structure and display logic of your component. Your template can contain any valid HTML, as well as some Vue-specific syntax that we'll cover later.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: By setting the <code>lang</code> attribute on the <code><template></code> tag, you can use Pug template syntax instead of standard HTML — <code><template lang="pug"></code>. We'll stick to standard HTML through this tutorial, but it is worth knowing that this is possible.</p> +</div> + +<p><code><script></code> contains all of the non-display logic of your component. Most importantly, your <code><script></code> tag needs to have a default exported JS object. This object is where you locally register components, define component inputs (props), handle local state, define methods, and more. Your build step will process this object and transform it (with your template) into a Vue component with a <code>render()</code> function.</p> + +<p>In the case of <code>App.vue</code>, our default export sets the name of the component to <code>app</code> and registers the <code>HelloWorld</code> component by adding it into the <code>components</code> property. When you register a component in this way, you're registering it locally. Locally registered components can only be used inside the components that register them, so you need to import and register them in every component file that uses them. This can be useful for bundle splitting/tree shaking since not every page in your app necessarily needs every component.</p> + +<pre class="brush: js notranslate">import HelloWorld from './components/HelloWorld.vue'; + +export default { + name: 'app', + components: { + //You can register components locally here. + HelloWorld + } +};</pre> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you want to use <a href="https://www.typescriptlang.org/">TypeScript</a> syntax, you need to set the <code>lang</code> attribute on the <code><script></code> tag to signify to the compiler that you're using TypeScript — <code><script lang="ts"></code>.</p> +</div> + +<p><code><style></code> is where you write your CSS for the component. If you add a <code>scoped</code> attribute — <code><style scoped></code> — Vue will scope the styles to the contents of your SFC. This works similar to CSS-in-JS solutions, but allows you to just write plain CSS.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: If you select a CSS pre-processor when creating the project via the CLI, you can add a <code>lang</code> attribute to the <code><style></code> tag so that the contents can be processed by Webpack at build time. For example, <code><style lang="scss"></code> will allow you to use SCSS syntax in your styling information.</p> +</div> + +<h2 id="Running_the_app_locally">Running the app locally</h2> + +<p>The Vue CLI comes with a built-in development server. This allows you to run your app locally so you can test it easily without needing to configure a server yourself. The CLI adds a <code>serve</code> command to the project’s <code>package.json</code> file as an npm script, so you can easily run it.</p> + +<p>In your terminal, try running <code>npm run serve</code> (or <code>yarn serve</code> if you prefer yarn). Your terminal should output something like the following:</p> + +<pre class="notranslate">INFO Starting development server... +98% after emitting CopyPlugin + + DONE Compiled successfully in 18121ms + + App running at: + - Local: <http://localhost:8080/> + - Network: <http://192.168.1.9:8080/> + + Note that the development build is not optimized. + To create a production build, run npm run build.</pre> + +<p>If you navigate to the “local” address in a new browser tab (this should be something like <code>http://localhost:8080</code> as stated above, but may vary based on your setup), you should see your app. Right now, it should contain a welcome message, a link to the Vue documentation, links to the plugins you added when you initialized the app with your CLI, and some other useful links to the Vue community and ecosystem.</p> + +<p><img alt="default vue app render, with vue logo, welcome message, and some documentation links" src="https://mdn.mozillademos.org/files/17240/vue-default-app.png" style="border-style: solid; border-width: 1px; height: 779px; width: 1600px;"></p> + +<h2 id="Making_a_couple_of_changes">Making a couple of changes</h2> + +<p>Let's make our first change to the app — we’ll delete the Vue logo. Open the <code>App.vue</code> file, and delete the <code><a href="/en-US/docs/Web/HTML/Element/img"><img></a></code> element from the template section:</p> + +<pre class="brush: html notranslate"><span class="author-d-iz88z86z86za0dz67zz78zz78zz74zz68zjz80zz71z9iz90z8h7gz67ziz76zcz77zz80zz71zncfz69zz69ziaz82zz71zz72zhz77zz122zz90z14mcyd"><img alt="Vue logo" src="./assets/logo.png"></span></pre> + +<p>If your server is still running, you should see the logo removed from the rendered site almost instantly. Let’s also remove the <code>HelloWorld</code> component from our template.</p> + +<p>First of all delete this line:</p> + +<pre class="brush: html notranslate"><HelloWorld msg="Welcome to Your Vue.js App"/></pre> + +<p>If you save your <code>App.vue</code> file now, the rendered app will throw an error because we’ve registered the component but are not using it. We also need to remove the lines from inside the <code><script></code> element that import and register the component:</p> + +<p>Delete these lines now:</p> + +<pre class="brush: js notranslate">import HelloWorld from './components/HelloWorld.vue'</pre> + +<pre class="brush: js notranslate">components: { + HelloWorld +}</pre> + +<p>Your rendered app should no longer show an error, just a blank page, as we currently have no visible content inside <code><template></code>.</p> + +<p>Let’s add a new <code><h1></code> inside <code><div id="app"></code>. Since we’re going to be creating a todo list app below, let's set our header text to "To-Do List". Add it like so:</p> + +<pre class="brush: html notranslate"><template> + <div id="app"> + <h1>To-Do List</h1> + </div> +</template></pre> + +<p><code>App.vue</code> will now show our heading, as you'd expect.</p> + +<h2 id="Summary">Summary</h2> + +<p>Let's leave this here for now. We've learnt about some of the ideas behind Vue, created some scaffolding for our example app to live inside, inspected it, and made a few preliminary changes.</p> + +<p>With a basic introduction out of the way, we'll now go further and build up our sample app, a basic Todo list application that allows us to store a list of items, check them off when done, and filter the list by all, complete, and incomplete todos.</p> + +<p>In the next article we'll build our first custom component, and look at some important concepts such as passing props into it and saving its data state.</p> + +<p>{{PreviousMenuNext("Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources","Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component", "Learn/Tools_and_testing/Client-side_JavaScript_frameworks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Introduction">Introduction to client-side frameworks</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Main_features">Framework main features</a></li> + <li>React + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_getting_started">Getting started with React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_todo_list_beginning">Beginning our React todo list</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_components">Componentizing our React app</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_events_state">React interactivity: Events and state</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_interactivity_filtering_conditional_rendering">React interactivity: Editing, filtering, conditional rendering</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_accessibility">Accessibility in React</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/React_resources">React resources</a></li> + </ul> + </li> + <li>Ember + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_getting_started">Getting started with Ember</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_structure_componentization">Ember app structure and componentization</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_interactivity_events_state">Ember interactivity: Events, classes and state</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_conditional_footer">Ember Interactivity: Footer functionality, conditional rendering</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_routing">Routing in Ember</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Ember_resources">Ember resources and troubleshooting</a></li> + </ul> + </li> + <li>Vue + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_getting_started">Getting started with Vue</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_first_component">Creating our first Vue component</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_rendering_lists">Rendering a list of Vue components</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_methods_events_models">Adding a new todo form: Vue events, methods, and models</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_styling">Styling Vue components with CSS</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_computed_properties">Using Vue computed properties</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_conditional_rendering">Vue conditional rendering: editing existing todos</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_refs_focus_management">Focus management with Vue refs</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Vue_resources">Vue resources</a></li> + </ul> + </li> + <li>Svelte + <ul> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_getting_started">Getting started with Svelte</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_Todo_list_beginning">Starting our Svelte Todo list app</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_variables_props">Dynamic behavior in Svelte: working with variables and props</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_components">Componentizing our Svelte app</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_reactivity_lifecycle_accessibility">Advanced Svelte: Reactivity, lifecycle, accessibility</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_stores">Working with Svelte stores</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_TypeScript">TypeScript support in Svelte</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks/Svelte_deployment_next">Deployment and next steps</a></li> + </ul> + </li> +</ul> diff --git a/files/es/learn/herramientas_y_pruebas/understanding_client-side_tools/index.html b/files/es/learn/herramientas_y_pruebas/understanding_client-side_tools/index.html new file mode 100644 index 0000000000..6221b0382f --- /dev/null +++ b/files/es/learn/herramientas_y_pruebas/understanding_client-side_tools/index.html @@ -0,0 +1,46 @@ +--- +title: Understanding client-side web development tools +slug: Learn/Herramientas_y_pruebas/Understanding_client-side_tools +tags: + - Aprender + - CSS + - Despliegue + - HTML + - Herramientas + - JavaScript + - Novatos + - Transformación + - client-side + - lado del cliente +translation_of: Learn/Tools_and_testing/Understanding_client-side_tools +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Las herramientas del lado del cliente (<em>client-side</em> en inglés) pueden ser intimidantes, pero esta serie de artículos tiene como propósito ilustrar el propósito de algunos de los tipos de herramientas <em>client-side</em>, explicar las herramientas que puedes integrar, cómo instalarlas usando administradores de paquetes y cómo controlarlas usando la línea de comandos. Terminanos esta sección dando un ejemplo de cadena de herramientas para mostrarte cómo puedes ser más productivo</p> + +<p class="summary"><strong><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Overview">Inicia ahora con nuestra "Introducción a las herraminetas <em>client-side</em>"</a></strong></p> + +<h2 id="Requisitos_previos">Requisitos previos</h2> + +<p>Debes aprender el núcleo básico de los lenguajes <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a> y <a href="/en-US/docs/Learn/JavaScript">JavaScript</a>, antes de intentar usar las herramientas aquí descritas.</p> + +<div class="in-page-callout webdev"> +<h3 id="¿Quieres_convertirte_en_un_desarrollador_front-end">¿Quieres convertirte en un desarrollador <em>front-end</em>?</h3> + +<p>Tenemos un curso que incluye toda la información esencial que necesitas para lograr tu objetivo.</p> +<a class="cta primary" href="/docs/Learn/Front-end_web_developer">Inicia ahora</a></div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Overview">1. Introducción a las herramientas <em>client-side</em></a></dt> + <dd>En este artículo damos una introducción a las herramientas modernas de la web, los tipos de herramientas disponibles, donde te las puedes encontrar en el cliclo de desarrollo de aplicaciones web y como buscar ayuda con las herramientas individuales.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Command_line">2. Introducción a la linea de comandos</a></dt> + <dd>En tu proceso de desarrollo seguramente vas a requeria correr algunos comandos en la terminal (o "línea de comandos"). Este artículo da una introducción a la terminal, los comandos básicos que vas a necesitar para utilizarla, cómo integrar diferentes comandos y cómo agregar tu propia interfaz de línea de comandos (<em>command line interface</em> - CLI en inglés).</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Package_management">3. Introducción al manejo de paquetes</a></dt> + <dd>En este artículo exploramos los sistemas de administración de paquetes en detalle para entender cómo los podemos usar en nuestros proyectos, ya sea para instalar dependencias a nuestro proyecto, descargar actualizaciones y mucho más.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Introducing_complete_toolchain">4. Introduciendo una cadena de herramientas completa</a></dt> + <dd>En los últimos dos artículos en esta serie vamos a solidificar tu conocimiento de las herramientas para el desarrollo web construyendo una cadena de herramients. Iniciaremos configurando un ambiente de desarrollo y colocando herramentas de transformación para desplegar nuestra aplicación en Netlify. En este artículo introducimos un estudio de caso, configuramos nuestro ambiente de desarrollo y configuramos herramientas de transformación de código.</dd> + <dt><a href="/en-US/docs/Learn/Tools_and_testing/Understanding_client-side_tools/Deployment">5. Desplegando nuestra aplicación</a></dt> + <dd>En el artículo final de esta serie, utilizamos nuestra cadena de herramientas que construimos en el artículo previo y la extendemos para desplegar nuestra aplicación muestra. Subimos nuestro código a GitHub, desplegamos usando Netlify e incluso te enseñamos a realizar una prueba en el proceso.</dd> +</dl> diff --git a/files/es/learn/html/como/index.html b/files/es/learn/html/como/index.html new file mode 100644 index 0000000000..095e5bc54e --- /dev/null +++ b/files/es/learn/html/como/index.html @@ -0,0 +1,141 @@ +--- +title: Solución de problemas comunes de HTML +slug: Learn/HTML/como +tags: + - CodificacióndeSecuenciadeComandos + - HTML +translation_of: Learn/HTML/Howto +--- +<p>{{LearnSidebar}}</p> + +<p class="summary">Los siguientes enlaces brindan soluciones puntuales a los problemas más comunes a los que te enfrentarás a diario en HTML.</p> + +<div class="column-container"> +<div class="column-half"> +<h3 id="Estructura_básica">Estructura básica</h3> + +<p>La principal aplicación de HTML es la estructuración del documento. Si eres nuevo en HTML debes empezar aquí.</p> + +<ul> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Getting_started#Anatomy_of_an_HTML_document">Cómo crear un documento HTML básico</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Divide_a_webpage_into_logical_sections">Cómo dividir una página web en secciones lógicas</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#The_basics_headings_and_paragraphs">Cómo establecer una estructura adecuada de encabezados y párrafos</a></li> +</ul> + +<h3 id="Semántica_básica_textos">Semántica básica textos</h3> + +<p>HTML se especializa en suministrar información semántica del documento, así que HTML soluciona muchas dudas que puede tener sobre como transmitir su mensaje a través de un documento.</p> + +<ul> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Lists">Cómo crear una lista de elementos con HTML</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Emphasis_and_importance">Cómo enfatizar o acentuar contenido</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Emphasis_and_importance">Cómo indicar qué texto es importante</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting#Representing_computer_code">Cómo muestra el ordenador el codigo HTML</a></li> + <li><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Images_in_HTML#Annotating_images_with_figures_and_figure_captions">Cómo comentar imagenes y gráficas</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting#Abbreviations">Cómo marcar abreviaturas y hacerlas entendibles</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting#Quotations">Cómo añadir citas y referencias a sitios web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Define_terms_with_HTML">Cómo definir términos con HTML</a></li> +</ul> +</div> + +<div class="column-half"> +<h3 id="Hipervínculos">Hipervínculos</h3> + +<p>Uno de las principales razones por las que HTML hace más fácil la navegación son los {{Glossary("hyperlink", "hipervínculos")}}, que pueden ser usados de diferentes formas:</p> + +<ul> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#Active_learning_creating_a_navigation_menu">Cómo crear un hipervínculo</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#Active_learning_creating_a_navigation_menu">Cómo crear una tabla de contenidos con HTML</a></li> +</ul> + +<h3 id="Imágenes_y_multimedia">Imágenes y multimedia</h3> + +<ul> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#Active_learning_creating_a_navigation_menu">Cómo</a><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Images_in_HTML#How_do_we_put_an_image_on_a_webpage"> añadir imagenes al sitio web</a></li> + <li><a href="/en-US/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks#Active_learning_creating_a_navigation_menu">Cómo</a><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content"> añadir contenidos de video al sitio web</a></li> +</ul> + +<h3 id="Scripts_y_estilización">Scripts y estilización</h3> + +<p>HTML únicamente define la estructura del documento. Para solucionar los problemas de presentación usamos {{glossary("CSS")}}, o usamos scripts para hacer la página interactiva.</p> + +<ul> + <li><a href="/en-US/Learn/CSS/Introduction_to_CSS/How_CSS_works#How_to_apply_your_CSS_to_your_HTML">Cómo usar CSS dentro de un sitio web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Use_JavaScript_within_a_webpage">Cómo usar JavaScript dentro de un sitio web</a></li> +</ul> + +<h3 id="Contenido_integrado">Contenido integrado</h3> + +<ul> + <li><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">Cómo integrar una página web dentro de otra</a></li> + <li><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies#The_%3Cembed%3E_and_%3Cobject%3E_elements">Cómo integrar contenido Flash </a><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">dentro de </a><a href="/en-US/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies#The_%3Cembed%3E_and_%3Cobject%3E_elements">una página web</a></li> +</ul> +</div> +</div> + +<h2 id="Problemas_avanzados_o_raros">Problemas avanzados o raros</h2> + +<p>Más allá de lo basico, HTML es muy rico y ofrece características avanzadas para solucionar problemas complejos. Estos artículos te ayudarán a abordar estos casos menos comunes:</p> + +<div class="column-container"> +<div class="column-half"> +<h3 id="Formularios">Formularios</h3> + +<p>Los formularios son una estructura compleja en HTML para enviar datos desde una pagina web al servidor. Te animamos a que revises la <a href="/en-US/docs/Web/Guide/HTML/Forms">guia completa</a>. Aquí es por donde deberías empezar:</p> + +<ul> + <li><a href="/en-US/docs/Web/Guide/HTML/Forms/My_first_HTML_form">Cómo crear un formulario Web simple</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Forms/How_to_structure_an_HTML_form">Cómo estructurar un formulario Web</a></li> +</ul> + +<h3 id="Información_tabular">Información tabular</h3> + +<p>Alguna información, llamada datos tabulares, necesita ser organizada en tablas mediante filas y columnas. Siendo ésta una de las estructuras más complejas de HTML, no es fácil dominarla:</p> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Create_a_data_spreadsheet">Cómo crear una tabla de datos</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Make_HTML_tables_accessible">Cómo hacer tablas HTML accesibles</a></li> +</ul> + +<h3 id="Representación_de_datos">Representación de datos</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTMLHowto/Represent_numeric_values_with_HTML">Cómo representar valores numericos y de código con HTML -</a> <span class="tlid-translation translation" lang="es"><span title="">ver </span></span> <span class="tlid-translation translation" lang="es"><span title="">Superíndice y Subíndice, y Representación del código de la computadora.</span></span></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Associate_human_readable_content_with_arbitrary_computer_data_structures">Cómo usar atributos de datos</a></li> +</ul> + +<h3 id="Rendimiento">Rendimiento</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Create_collapsible_content_with_HTML">Cómo crear páginas HTML de carga rápida</a></li> +</ul> +</div> + +<div class="column-half"> +<h3 id="Semántica_avanzada_de_texto">Semántica avanzada de texto</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Take_control_of_HTML_line_breaking">Cómo controlar el salto de línea en HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Mark_text_insertion_and_deletion">Cómo marcar cambios (agregar y remover textos)</a> -ver los elementos {{htmlelement("ins")}} y {{htmlelement("del")}}</li> +</ul> + +<h3 id="Imágenes_y_multimedia_avanzada">Imágenes y multimedia avanzada</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Cómo agregar una imagen receptiva a una página web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Cómo agregar una imagen vectorial a una página web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Add_a_hit_map_on_top_of_an_image">Cómo agregar un mapa de visitas sobre una imagen</a></li> +</ul> + +<h3 id="Internacionalización">Internacionalización</h3> + +<p>HTML no es monolingüe. Éste <span class="tlid-translation translation" lang="es"><span title="">proporciona herramientas para manejar problemas comunes de internacionalización.</span></span></p> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Howto/Add_multiple_languages_into_a_single_webpage">Cómo agregar multiples lenguajes en una misma página web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Howto/Display_time_and_date_with_HTML">Cómo mostrar hora y fecha con HTML </a></li> +</ul> +</div> +</div> + +<p><span style="display: none;"> </span><span style="display: none;"> </span><span style="display: none;"> </span><span style="display: none;"> </span> </p> diff --git a/files/es/learn/html/como/usando_atributos_de_datos/index.html b/files/es/learn/html/como/usando_atributos_de_datos/index.html new file mode 100644 index 0000000000..7629974833 --- /dev/null +++ b/files/es/learn/html/como/usando_atributos_de_datos/index.html @@ -0,0 +1,75 @@ +--- +title: Uso de atributos de datos +slug: Learn/HTML/como/Usando_atributos_de_datos +translation_of: Learn/HTML/Howto/Use_data_attributes +--- +<div>{{LearnSidebar}}</div> + +<p><a href="/en-US/docs/Web/Guide/HTML/HTML5">HTML5</a> está diseñado de forma tal que sea fácil extender los datos asociados a un elemento en particular sin necesidad de que tengan un significado definido. Los atributos <a href="/en-US/docs/Web/HTML/Global_attributes#attr-dataset"><code>data-* </code></a> permiten almacenar información adicional sobre un elemento HTML cualquiera sin tener que recurrir a artilugios tales como la utilización de atributos no estándar, propiedades adicionales en el DOM o {{domxref("Node.setUserData()")}}.</p> + +<h2 id="Sintaxis_HTML">Sintaxis HTML</h2> + +<p>La sintáxis es simple. Un atributo cualquiera cuyo nombre comience con <code>data-</code>es un atributo de datos. Supongamos que tenemos un artículo y deseamos almacenar información adicional que no tiene ninguna representación visual. En ese caso, alcanza con que hagamos uso de los atributos <code>data</code>:</p> + +<pre class="brush: html notranslate"><article + id="electriccars" + data-columns="3" + data-index-number="12314" + data-parent="cars"> +... +</article></pre> + +<h2 id="Acceso_a_través_de_JavaScript">Acceso a través de JavaScript</h2> + +<p>Leer los valores de estos atributos en <a href="/en-US/docs/Web/JavaScript">JavaScript</a> también es muy sencillo. Puede usar {{domxref("Element.getAttribute", "getAttribute()")}} con su nombre HTML completo para leerlos, pero el estándar define una forma más simple: un {{domxref("DOMStringMap")}} puede leer a través de una propiedad {{domxref("HTMLElement.dataset", "dataset")}}.</p> + +<p>Para obtener un atributo <code>data</code> a través del <code>dataset</code> del objeto, obtenga la propiedad por la parte del nombre del atributo despues de <code>data-</code> (tenga en cuenta que los guiones son convertidos en camelCase).</p> + +<pre class="brush: js notranslate">var article = document.getElementById('electriccars'); + +article.dataset.columns // "3" +article.dataset.indexNumber // "12314" +article.dataset.parent // "cars"</pre> + +<p>Cada propiedad es una cadena y se puede leer y escribir. En el caso anterior, establecer <code>article.dataset.columns = 5</code> cambiaría ese atributo a <code>"5"</code>.</p> + +<h2 id="Acceso_a_través_de_CSS">Acceso a través de CSS</h2> + +<p>Tenga en cuenta que, debido a que los atributos de datos son atributos simples de HTML, incluso puede acceder a ellos desde <a href="/en-US/docs/Web/CSS">CSS</a>. Por ejemplo, para mostrar los <code>data-parent</code> en el artículo, puede usar el <a href="/en-US/docs/Web/CSS/content">contenido generado</a> en CSS con la función {{cssxref("attr")}}:</p> + +<pre class="brush: css notranslate">article::before { + content: attr(data-parent); +}</pre> + +<p>También puede usar los <a href="/en-US/docs/Web/CSS/Attribute_selectors">selectores de atributos</a> en CSS para cambiar los estilos de acuerdo a las priopiedades de datos:</p> + +<pre class="brush: css notranslate">article[data-columns='3'] { + width: 400px; +} +article[data-columns='4'] { + width: 600px; +}</pre> + +<p>Puede ver todo esto trabajando junto <a href="http://jsbin.com/ujiday/2/edit">en este ejemplo de JSBin</a>.</p> + +<p>Los atributos de datos también se pueden almacenar para que contengan información que cambia constantemente, como los puntajes en un juego. Usando los selectores de CSS y el acceso a JavaScript aquí, esto le permite crear algunos efectos ingeniosos sin tener que escribir sus propias rutinas de visualización. Consulte <a href="http://www.youtube.com/watch?v=On_WyUB1gOk">este screencast</a> para ver un ejemplo utilizando contenido generado y transacciones CSS (<a href="http://jsbin.com/atawaz/3/edit">Ejemplo JSBin</a>).</p> + +<p>Los valores de datos son cadenas de caracteres. Los valores numéricos deben ser citados en el selector para que el estilo surta efecto.</p> + +<h2 id="Problemas">Problemas</h2> + +<p>No almacene el contenido que debería ser visible y accesible en los atributos de datos, ya que las tecnologías de asistencia, no pueden acceder a ellos. Ademas, los rastreadores de búsqueda no pueden indexar los valores de los atributos de datos.</p> + +<p>Los principales problemas a considerar son el soporte y rendimiento en Internet Explorer. Internet Explorer 11 y superiores, proporcionan soporte para el estándar, pero todas las versiones anteriores <a href="http://caniuse.com/#feat=dataset">no son compatibles con <code>dataset</code></a>. Para admitir IE 10 e inferiores, debe acceder a los atributos de datos con {{domxref("Element.getAttribute", "getAttribute()")}} en su lugar. Ademas, el <a href="http://jsperf.com/data-dataset">rendimiento de lectura de los atributos de datos</a> en comparación con el almacenamiento de estos datos en un objeto JS normal es deficiente.</p> + +<p>Dicho esto, sin embargo, para metadatos asociados a elementos personalizados, son una gran solución.</p> + +<p>En Firefox 49.0.2 (y quizás versiones anteriores), los atributos de datos que exceden los 1022 caracteres no serán leídos por Javascript (EcmaScript 4).</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li>Este artículo es una adaptación de <a href="https://hacks.mozilla.org/2012/10/using-data-attributes-in-javascript-and-css/" title="https://hacks.mozilla.org/2012/10/using-data-attributes-in-javascript-and-css/">Usando atributos de datos en JavaScript y CSS en hacks.mozilla.org</a>.</li> + <li>Los atributos personalizados también son compatibles en SVG 2; vea {{domxref("SVGElement.dataset")}} y {{SVGAttr("data-*")}} para más información.</li> + <li><a href="http://www.sitepoint.com/use-html5-data-attributes/">Cómo utilizar atributos de datos HTML5</a></li> +</ul> diff --git a/files/es/learn/html/forms/como_crear_widgets_de_formularios_personalizados/index.html b/files/es/learn/html/forms/como_crear_widgets_de_formularios_personalizados/index.html new file mode 100644 index 0000000000..73ae6e6590 --- /dev/null +++ b/files/es/learn/html/forms/como_crear_widgets_de_formularios_personalizados/index.html @@ -0,0 +1,786 @@ +--- +title: Cómo crear widgets de formularios personalizados +slug: Learn/HTML/Forms/como_crear_widgets_de_formularios_personalizados +translation_of: Learn/Forms/How_to_build_custom_form_controls +--- +<div>{{LearnSidebar}}{{PreviousMenuNext("Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms")}}</div> + +<p class="summary">Hay muchos casos donde los <a href="/en-US/docs/HTML/Forms/The_native_form_widgets" title="/en-US/docs/HTML/Forms/The_native_form_widgets">widgets de formularios HTML disponibles</a> simplemente no son suficientes. si desea <a href="/en-US/docs/Advanced_styling_for_HTML_forms" title="/en-US/docs/Advanced_styling_for_HTML_forms">establecer un estilo avanzado</a> en algunos widgets como el elemento {{HTMLElement("select")}} o si desea proporcionar comportamientos personalizados, no tiene más opción que crear sus propios widgets.</p> + +<p>En este aartículo, veremos cómo construir dicho widget. Para ello, trabajaremos con un ejemplo: Reconstruir el elemento {{HTMLElement("select")}}.</p> + +<div class="note"> +<p><strong>Nota:</strong> Nos enfocaremos en construir los widgets, no en cómo hacer que el código sea genérico y reutilizable; eso implicaría algún código JavaScript no trivial y manipulación del DOM en un contexto desconocido, y eso está fuera del alcance de este artículo.</p> +</div> + +<h2 id="Diseño_estructura_y_semántica">Diseño, estructura, y semántica</h2> + +<p>Antes de crear un widget personalizado, debería iniciar por averiguar exactamente qué es lo que desea. Esto le ahorarrá tiempo considerable. En particular, es importante definir claramente todos los estados de su widget. Para hacer esto, es bueno comenzar con un widget existente, cuyos estados y comportamientos son bien conocidos, por lo que simplemente puede imitarlos tanto como sea posible.</p> + +<p>En nuestro ejemplo, reconstruiremos el elemento {{HTMLElement("select")}}. Este es el resultado que queremos lograr:</p> + +<p><img alt="The three states of a select box" src="/files/4481/custom-select.png" style="height: 135px; width: 366px;"></p> + +<p>Esta captura de pantall muestra los tres estados principales de nuestro widget: el estado normal (a la izquiera); el estado activo (en el centro) y el estado abierto (a la derecha).</p> + +<p>En términos de comportamiento, queremos que nuestro widget sea utilizable tanto con un ratón como con un teclado, al igual que cualquier widget nativo. Comencemos por definir cómo el widget llega a cada estado:</p> + +<dl> + <dt>El widget está en su estado normal cuando:</dt> + <dd> + <ul> + <li>La página carga</li> + <li>El widget estaba activo y el usuario hace clic en cualquier lugar fuera del widget</li> + <li>El widget estaba activo y el usuario mueve el foco a otro widget usando el teclado</li> + </ul> + + <div class="note"> + <p><strong>Nota:</strong> Mover el foco al rededor de la página generalmente se hace presionando la tecla de tabulación, pero este no es el estándar en todas partes. Por ejemplo, el ciclo a través de enlaces en una página se realiza en Safari de forma predeterminada usando la combinación <a href="http://www.456bereastreet.com/archive/200906/enabling_keyboard_navigation_in_mac_os_x_web_browsers/" title="http://www.456bereastreet.com/archive/200906/enabling_keyboard_navigation_in_mac_os_x_web_browsers/">combinación Opction+Tab</a>.</p> + </div> + </dd> + <dt>El widget está en su estado activo cuando:</dt> + <dd> + <ul> + <li>El usuario hace clic en él</li> + <li>El usuario presiona la tecla tab y obtiene foco</li> + <li>El widget estaba en su estado abierto y el usuario hace clic en el widget.</li> + </ul> + </dd> + <dt>El widget está en su estado abierto cuando:</dt> + <dd> + <ul> + <li>El widget está en cualquier otro estado diferente a abierto y el usuario hace clic en él.</li> + </ul> + </dd> +</dl> + +<p>Una vez que sabemos cómo cambiar los estados, es importante definir cómo cambiar el valor del widget:</p> + +<dl> + <dt>El valor cambia cuando:</dt> + <dd> + <ul> + <li>El usuario hace clic en una opción cuando el widget está en estado abierto</li> + <li>El usuario pulsa las teclas de flecha hacia arriba o hacia abajocuando el widget está en estado activo</li> + </ul> + </dd> +</dl> + +<p>Finalmente, definamos cómo se comportarán las opciones del widget:</p> + +<ul> + <li>Cuando se abre el widget, se resalta la opción seleccionada</li> + <li>Cuando el ratón está sobre una opción, la opción se resalta y la opción resaltada anteriormente vuelve a su estado normal</li> +</ul> + +<p>Para los fines de nuestro ejemplo, nos detendremos con eso; sin embargo, si eres un lector cuidadoso, notarás que faltan algunos comportamientos. Por ejemplo, ¿qué crees que sucederá si el usuario pulsa la tecla de tabulación mientras el widget está en estado abierto? La respuesta es ... nada. OK, el comportamiento correcto parece obvio, pero el hecho es que, como no está definido en nuestras especificaciones, es muy fácil pasar por alto este comportamiento. Esto es especialmente cierto en un entorno de equipo cuando las personas que diseñan el comportamiento del widget son diferentes de las que lo implementan.</p> + +<p>Otro ejemplo divertido: ¿qué pasará si el usuario pulsa las teclas de flecha hacia arriba o hacia abajo mientras el widget está en estado abierto? Este es un poco más complicado. Si considera que el estado activo y el estado abierto son completamente diferentes, la respuesta es nuevamente "no pasará nada" porque no definimos ninguna interacción de teclado para el estado abierto. Por otro lado, si considera que el estado activo y el estado abierto se superponen un poco, el valor puede cambiar pero la opción definitivamente no se resaltará en consecuencia, una vez más porque no definimos ninguna interacción del teclado sobre las opciones cuando el widget es en su estado abierto (solo hemos definido lo que debería suceder cuando se abre el widget, pero nada después de eso).</p> + +<p>En nuestro ejemplo, las especificaciones faltantes son obvias, así que las manejaremos, pero puede ser un problema real en widgets nuevos y exóticos, para los cuales nadie tiene la menor idea de cuál es el comportamiento correcto. Por lo tanto, siempre es bueno pasar tiempo en esta etapa de diseño, porque si defines un comportamiento deficiente u olvidas definir uno, será muy difícil redefinirlo una vez que los usuarios se hayan acostumbrado. Si tiene dudas, solicite las opiniones de los demás y, si tiene el presupuesto para ello, no dude en realizar las pruebas de usuario. Este proceso se llama Diseño UX. Si desea obtener más información sobre este tema, debe consultar los siguientes recursos útiles:</p> + +<ul> + <li><a href="http://www.uxmatters.com/" rel="external" title="http://www.uxmatters.com/">UXMatters.com</a></li> + <li><a href="http://uxdesign.com/" rel="external" title="http://uxdesign.com/">UXDesign.com</a></li> + <li><a href="http://uxdesign.smashingmagazine.com/" rel="external" title="http://uxdesign.smashingmagazine.com/">The UX Design section of SmashingMagazine</a></li> +</ul> + +<div class="note"> +<p><strong>Nota: </strong>Ademas, en la mayoría de los sistemas hay una forma de abrir el elemento {{HTMLElement("select")}} para ver todas las opciones disponibles (esto es lo mismo que hacer clic en el elemento {{HTMLElement("select")}} con un ratón). Esto se logra con Alt+Flecha abajo en Windows y no fué implementado en nuestro ejemplo —pero sería facil hacerlo, ya que el mecanismo ya se implementó para el evento <code>clic</code>.</p> +</div> + +<h3 id="Definiendo_la_estructura_y_semántica_HTML">Definiendo la estructura y semántica HTML</h3> + +<p>Ahora que se ha decidido la funcionalidad básica del widget, es hora de comenzar a construir nuestro widget. El primer paso es definir su estructura HTML y darle una semántica básica. Esto es lo que necesitamos para reconstruir un elemento {{HTMLElement("select")}}:</p> + +<pre class="brush: html"><!-- Este es nuestro contenedor principal para nuestro widget. + El atributo tabindex es lo que permite al usuario enforcar el widget. + Veremos más adelante que es mejor configurarlo a través de JavaScript. --> +<div class="select" tabindex="0"> + + <!-- Este contenedor será usado para mostrar el valor actual del widget --> + <span class="value">Cherry</span> + + <!-- Este contenedor contedrá todas las opciones disponibles para nuestro widget. + Como es una lista, tiene sentido usar el elemento ul. --> + <ul class="optList"> + <!-- Cada opción solo contiene el valor que se mostrará, veremos más tarde + cómo manejar el valor real que será enviado con el formulario de datos --> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + +</div></pre> + +<p>Tenga en cuanta el uso de nombres de clases; estos identifican cada parte relevante independientemente de los elementos HTML subyacentes reales utilizados. Esto es importante para garantizar que no vinculamos nuestro CSS y JavaScript a una estructura HTML sólida, de modo que podamos realizar cambios despues en la implementación sin romper el código que usa el widget. Pro ejemplo, si desea implementar el equivalente del elemento {{HTMLElement("optgroup")}}.</p> + +<h3 id="Creating_the_look_and_feel_using_CSS">Creating the look and feel using CSS</h3> + +<p>Now that we have a structure, we can start designing our widget. The whole point of building this custom widget is to be able to style this widget exactly as we want. To that end, we will split our CSS work into two parts: the first part will be the CSS rules absolutely necessary to have our widget behave like a {{HTMLElement("select")}} element, and the second part will consist of the fancy styles used to make it look the way we want.</p> + +<h4 id="Required_styles">Required styles</h4> + +<p>The required styles are those necessary to handle the three states of our widget.</p> + +<pre class="brush: css">.select { + /* This will create a positioning context for the list of options */ + position: relative; + + /* This will make our widget become part of the text flow and sizable at the same time */ + display : inline-block; +}</pre> + +<p>We need an extra class <code>active</code> to define the look and feel of our widget when it is in its active state. Because our widget is focusable, we double this custom style with the {{cssxref(":focus")}} pseudo-class in order to be sure they will behave the same.</p> + +<pre class="brush: css">.select.active, +.select:focus { + outline: none; + + /* This box-shadow property is not exactly required, however it's so important to be sure + the active state is visible that we use it as a default value, feel free to override it. */ + box-shadow: 0 0 3px 1px #227755; +}</pre> + +<p>Now, let's handle the list of options:</p> + +<pre class="brush: css">/* The .select selector here is syntactic sugar to be sure the classes we define are + the ones inside our widget. */ +.select .optList { + /* This will make sure our list of options will be displayed below the value + and out of the HTML flow */ + position : absolute; + top : 100%; + left : 0; +}</pre> + +<p>We need an extra class to handle when the list of options is hidden. This is necessary in order to manage the differences between the active state and the open state that do not exactly match.</p> + +<pre class="brush: css">.select .optList.hidden { + /* This is a simple way to hide the list in an accessible way, + we will talk more about accessibility in the end */ + max-height: 0; + visibility: hidden; +}</pre> + +<h4 id="Beautification">Beautification</h4> + +<p>So now that we have the basic functionality in place, the fun can start. The following is just an example of what is possible, and will match the screenshot at the beginning of this article. However, you should feel free to experiment and see what you can come up with.</p> + +<pre class="brush: css">.select { + /* All sizes will be expressed with the em value for accessibility reasons + (to make sure the widget remains resizable if the user uses the + browser's zoom in a text-only mode). The computations are made + assuming 1em == 16px which is the default value in most browsers. + If you are lost with px to em conversion, try http://riddle.pl/emcalc/ */ + font-size : 0.625em; /* this (10px) is the new font size context for em value in this context */ + font-family : Verdana, Arial, sans-serif; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + /* We need extra room for the down arrow we will add */ + padding : .1em 2.5em .2em .5em; /* 1px 25px 2px 5px */ + width : 10em; /* 100px */ + + border : .2em solid #000; /* 2px */ + border-radius : .4em; /* 4px */ + box-shadow : 0 .1em .2em rgba(0,0,0,.45); /* 0 1px 2px */ + + /* The first declaration is for browsers that do not support linear gradients. + The second declaration is because WebKit based browsers haven't unprefixed it yet. + If you want to support legacy browsers, try http://www.colorzilla.com/gradient-editor/ */ + background : #F0F0F0; + background : -webkit-linear-gradient(90deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); + background : linear-gradient(0deg, #E3E3E3, #fcfcfc 50%, #f0f0f0); +} + +.select .value { + /* Because the value can be wider than our widget, we have to make sure it will not + change the widget's width */ + display : inline-block; + width : 100%; + overflow : hidden; + + vertical-align: top; + + /* And if the content overflows, it's better to have a nice ellipsis. */ + white-space : nowrap; + text-overflow: ellipsis; +}</pre> + +<p>We don't need an extra element to design the down arrow; instead, we're using the {{cssxref(":after")}} pseudo-element. However, it could also be implemented using a simple background image on the <code>select</code> class.</p> + +<pre class="brush: css">.select:after { + content : "▼"; /* We use the unicode caracter U+25BC; see http://www.utf8-chartable.de */ + position: absolute; + z-index : 1; /* This will be important to keep the arrow from overlapping the list of options */ + top : 0; + right : 0; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + height : 100%; + width : 2em; /* 20px */ + padding-top : .1em; /* 1px */ + + border-left : .2em solid #000; /* 2px */ + border-radius: 0 .1em .1em 0; /* 0 1px 1px 0 */ + + background-color : #000; + color : #FFF; + text-align : center; +}</pre> + +<p>Next, let's style the list of options:</p> + +<pre class="brush: css">.select .optList { + z-index : 2; /* We explicitly said the list of options will always overlap the down arrow */ + + /* this will reset the default style of the ul element */ + list-style: none; + margin : 0; + padding: 0; + + -moz-box-sizing : border-box; + box-sizing : border-box; + + /* This will ensure that even if the values are smaller than the widget, + the list of options will be as large as the widget itself */ + min-width : 100%; + + /* In case the list is too long, its content will overflow vertically + (which will add a vertical scrollbar automatically) but never horizontally + (because we haven't set a width, the list will adjust its width automatically. + If it can't, the content will be truncated) */ + max-height: 10em; /* 100px */ + overflow-y: auto; + overflow-x: hidden; + + border: .2em solid #000; /* 2px */ + border-top-width : .1em; /* 1px */ + border-radius: 0 0 .4em .4em; /* 0 0 4px 4px */ + + box-shadow: 0 .2em .4em rgba(0,0,0,.4); /* 0 2px 4px */ + background: #f0f0f0; +}</pre> + +<p>For the options, we need to add a <code>highlight</code> class to be able to identify the value the user will pick (or has picked).</p> + +<pre class="brush: css">.select .option { + padding: .2em .3em; /* 2px 3px */ +} + +.select .highlight { + background: #000; + color: #FFFFFF; +}</pre> + +<p>So here's the result with our three states:</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Basic state</th> + <th scope="col" style="text-align: center;">Active state</th> + <th scope="col" style="text-align: center;">Open state</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Basic_state",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + <td>{{EmbedLiveSample("Active_state",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + <td>{{EmbedLiveSample("Open_state",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_1")}}</td> + </tr> + <tr> + <td colspan="3" style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_1" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_1">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<h2 id="Bring_your_widget_to_life_with_JavaScript">Bring your widget to life with JavaScript</h2> + +<p>Now that our design and structure are ready, we can write the JavaScript code to make the widget actually work.</p> + +<div class="warning"> +<p><strong>Warning:</strong> The following code is educational and should not be used as-is. Among many things, as we'll see, it is not future-proof and it will not work on legacy browsers. It also has redundant parts that should be optimized in production code.</p> +</div> + +<div class="note"> +<p><strong>Note:</strong> Creating reusable widgets is something that can be a bit tricky. The <a href="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html" rel="external" title="http://dvcs.w3.org/hg/webcomponents/raw-file/tip/explainer/index.html">W3C Web Component draft</a> is one of the answers to this specific issue. <a href="http://x-tags.org/" rel="external" title="http://x-tags.org/">The X-Tag project</a> is a test implementation of this specification; we encourage you to take a look at it.</p> +</div> + +<h3 id="Why_isn't_it_working">Why isn't it working?</h3> + +<p>Before we start, it's important to remember something very important about JavaScript: inside a browser, <strong>it's an unreliable technology</strong>. When you are building custom widgets, you'll have to rely on JavaScript because it's a necessary thread to tie everything together. However, there are many cases in which JavaScript isn't able to run in the browser:</p> + +<ul> + <li>The user has turned off JavaScript: This is the most unusual case ever; very few people turn off JavaScript nowadays.</li> + <li>The script is not loading. This is one of the most common cases, especially in the mobile world where the network is not very reliable.</li> + <li>The script is buggy. You should always consider this possibility.</li> + <li>The script is in conflict with a third party script. This can happen with tracking scripts or any bookmarklets the user uses.</li> + <li>The script is in conflict with, or is affected by, a browser extension (such as Firefox's <a href="https://addons.mozilla.org/fr/firefox/addon/noscript/" rel="external" title="https://addons.mozilla.org/fr/firefox/addon/noscript/">NoScript</a> extension or Chrome's <a href="https://chrome.google.com/webstore/detail/notscripts/odjhifogjcknibkahlpidmdajjpkkcfn" rel="external" title="https://chrome.google.com/webstore/detail/notscripts/odjhifogjcknibkahlpidmdajjpkkcfn">NotScripts</a> extension).</li> + <li>The user is using a legacy browser, and one of the features you require is not supported. This will happen frequently when you make use of cutting-edge APIs.</li> +</ul> + +<p>Because of these risks, it's really important to seriously consider what will happen if JavaScript isn't working. Dealing in detail with this issue is out of the scope of this article because it's closely linked to how you want to make your script generic and reusable, but we'll consider the basics of this in our example.</p> + +<p>In our example, if our JavaScript code isn't running, we'll fall back to displaying a standard {{HTMLElement("select")}} element. To achieve this, we need two things.</p> + +<p>First, we need to add a regular {{HTMLElement("select")}} element before each use of our custom widget. This is actually also required in order to be able to send data from our custom widget along with the rest of our form data; more about this later.</p> + +<pre class="brush: html"><body class="no-widget"> + <form> + <select name="myFruit"> + <option>Cherry</option> + <option>Lemon</option> + <option>Banana</option> + <option>Strawberry</option> + <option>Apple</option> + </select> + + <div class="select"> + <span class="value">Cherry</span> + <ul class="optList hidden"> + <li class="option">Cherry</li> + <li class="option">Lemon</li> + <li class="option">Banana</li> + <li class="option">Strawberry</li> + <li class="option">Apple</li> + </ul> + </div> + </form> + +</body></pre> + +<p>Second, we need two new classes to let us hide the unneeded element (that is, the "real" {{HTMLElement("select")}} element if our script isn't running, or the custom widget if it is running). Note that by default, our HTML code hides our custom widget.</p> + +<pre class="brush: css">.widget select, +.no-widget .select { + /* This CSS selector basically says: + - either we have set the body class to "widget" and thus we hide the actual {{HTMLElement("select")}} element + - or we have not changed the body class, therefore the body class is still "no-widget", + so the elements whose class is "select" must be hidden */ + position : absolute; + left : -5000em; + height : 0; + overflow : hidden; +}</pre> + +<p>Now we just need a JavaScript switch to determine if the script is running or not. This switch is very simple: if at page load time our script is running, it will remove the <code>no-widget</code> class and add the <code>widget</code> class, thereby swapping the visibility of the {{HTMLElement("select")}} element and of the custom widget.</p> + +<pre class="brush: js">window.addEventListener("load", function () { + document.body.classList.remove("no-widget"); + document.body.classList.add("widget"); +});</pre> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Without JS</th> + <th scope="col" style="text-align: center;">With JS</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("No_JS",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_2")}}</td> + <td>{{EmbedLiveSample("JS",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_2")}}</td> + </tr> + <tr> + <td colspan="2" style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Note:</strong> If you really want to make your code generic and reusable, instead of doing a class switch it's far better to just add the widget class to hide the {{HTMLElement("select")}} elements, and to dynamically add the DOM tree representing the custom widget after every {{HTMLElement("select")}} element in the page.</p> +</div> + +<h3 id="Making_the_job_easier">Making the job easier</h3> + +<p>In the code we are about to build, we will use the standard DOM API to do all the work we need. However, although DOM API support has gotten much better in browsers, there are always issues with legacy browsers (especially with good old Internet Explorer).</p> + +<p>If you want to avoid trouble with legacy browsers, there are two ways to do so: using a dedicated framework such as <a href="http://jquery.com/" rel="external" title="http://jquery.com/">jQuery</a>, <a href="https://github.com/julienw/dollardom" rel="external" title="https://github.com/julienw/dollardom">$dom</a>, <a href="http://prototypejs.org/" rel="external" title="http://prototypejs.org/">prototype</a>, <a href="http://dojotoolkit.org/" rel="external" title="http://dojotoolkit.org/">Dojo</a>, <a href="http://yuilibrary.com/" rel="external" title="http://yuilibrary.com/">YUI</a>, or the like, or by polyfilling the missing feature you want to use (which can easily be done through conditional loading, with the <a href="http://yepnopejs.com/" rel="external" title="http://yepnopejs.com/">yepnope</a> library for example).</p> + +<p>The features we plan to use are the following (ordered from the riskiest to the safest):</p> + +<ol> + <li>{{domxref("element.classList","classList")}}</li> + <li>{{domxref("EventTarget.addEventListener","addEventListener")}}</li> + <li><code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code> (This is not DOM but modern JavaScript)</li> + <li>{{domxref("element.querySelector","querySelector")}} and {{domxref("element.querySelectorAll","querySelectorAll")}}</li> +</ol> + +<p>Beyond the availability of those specific features, there is still one issue remaining before starting. The object returned by the {{domxref("element.querySelectorAll","querySelectorAll()")}} function is a {{domxref("NodeList")}} rather than an <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array">Array</a></code>. This is important because <code>Array</code> objects support the <code><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach" title="/en-US/docs/JavaScript/Reference/Global_Objects/Array/forEach">forEach</a></code> function, but {{domxref("NodeList")}} doesn't. Because {{domxref("NodeList")}} really looks like an <code>Array</code> and because <code>forEach</code> is so convenient to use, we can easily add the support of <code>forEach</code> to {{domxref("NodeList")}} in order to make our life easier, like so:</p> + +<pre class="brush: js">NodeList.prototype.forEach = function (callback) { + Array.prototype.forEach.call(this, callback); +}</pre> + +<p>We weren't kidding when we said it's easy to do.</p> + +<h3 id="Building_event_callbacks">Building event callbacks</h3> + +<p>The ground is ready, we can now start to define all the functions that will be used each time the user interacts with our widget.</p> + +<pre class="brush: js">// This function will be used each time we want to deactivate a custom widget +// It takes one parameter +// select : the DOM node with the `select` class to deactivate +function deactivateSelect(select) { + + // If the widget is not active there is nothing to do + if (!select.classList.contains('active')) return; + + // We need to get the list of options for the custom widget + var optList = select.querySelector('.optList'); + + // We close the list of option + optList.classList.add('hidden'); + + // and we deactivate the custom widget itself + select.classList.remove('active'); +} + +// This function will be used each time the user wants to (de)activate the widget +// It takes two parameters: +// select : the DOM node with the `select` class to activate +// selectList : the list of all the DOM nodes with the `select` class +function activeSelect(select, selectList) { + + // If the widget is already active there is nothing to do + if (select.classList.contains('active')) return; + + // We have to turn off the active state on all custom widgets + // Because the deactivateSelect function fulfill all the requirement of the + // forEach callback function, we use it directly without using an intermediate + // anonymous function. + selectList.forEach(deactivateSelect); + + // And we turn on the active state for this specific widget + select.classList.add('active'); +} + +// This function will be used each time the user wants to open/closed the list of options +// It takes one parameter: +// select : the DOM node with the list to toggle +function toggleOptList(select) { + + // The list is kept from the widget + var optList = select.querySelector('.optList'); + + // We change the class of the list to show/hide it + optList.classList.toggle('hidden'); +} + +// This function will be used each time we need to highlight an option +// It takes two parameters: +// select : the DOM node with the `select` class containing the option to highlight +// option : the DOM node with the `option` class to highlight +function highlightOption(select, option) { + + // We get the list of all option available for our custom select element + var optionList = select.querySelectorAll('.option'); + + // We remove the highlight from all options + optionList.forEach(function (other) { + other.classList.remove('highlight'); + }); + + // We highlight the right option + option.classList.add('highlight'); +};</pre> + +<p>That's all you need in order to handle the various states of the custom widget.</p> + +<p>Next, we bind these functions to the appropriate events:</p> + +<pre class="brush: js">// We handle the event binding when the document is loaded. +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + // Each custom widget needs to be initialized + selectList.forEach(function (select) { + + // as well as all its `option` elements + var optionList = select.querySelectorAll('.option'); + + // Each time a user hovers their mouse over an option, we highlight the given option + optionList.forEach(function (option) { + option.addEventListener('mouseover', function () { + // Note: the `select` and `option` variable are closures + // available in the scope of our function call. + highlightOption(select, option); + }); + }); + + // Each times the user click on a custom select element + select.addEventListener('click', function (event) { + // Note: the `select` variable is a closure + // available in the scope of our function call. + + // We toggle the visibility of the list of options + toggleOptList(select); + }); + + // In case the widget gain focus + // The widget gains the focus each time the user clicks on it or each time + // they use the tabulation key to access the widget + select.addEventListener('focus', function (event) { + // Note: the `select` and `selectList` variable are closures + // available in the scope of our function call. + + // We activate the widget + activeSelect(select, selectList); + }); + + // In case the widget loose focus + select.addEventListener('blur', function (event) { + // Note: the `select` variable is a closure + // available in the scope of our function call. + + // We deactivate the widget + deactivateSelect(select); + }); + }); +});</pre> + +<p>At that point, our widget will change state according to our design, but its value doesn't get updated yet. We'll handle that next.</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Live example</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_3")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_3">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<h3 id="Handling_the_widget's_value">Handling the widget's value</h3> + +<p>Now that our widget is working, we have to add code to update its value according to user input and make it possible to send the value along with form data.</p> + +<p>The easiest way to do this is to use a native widget under the hood. Such a widget will keep track of the value with all the built-in controls provided by the browser, and the value will be sent as usual when a form is submitted. There's no point in reinventing the wheel when we can have all this done for us.</p> + +<p>As seen previously, we already use a native select widget as a fallback for accessibility reasons; we can simply synchronize its value with that of our custom widget:</p> + +<pre class="brush: js">// This function updates the displayed value and synchronizes it with the native widget. +// It takes two parameters: +// select : the DOM node with the class `select` containing the value to update +// index : the index of the value to be selected +function updateValue(select, index) { + // We need to get the native widget for the given custom widget + // In our example, that native widget is a sibling of the custom widget + var nativeWidget = select.previousElementSibling; + + // We also need to get the value placeholder of our custom widget + var value = select.querySelector('.value'); + + // And we need the whole list of options + var optionList = select.querySelectorAll('.option'); + + // We set the selected index to the index of our choice + nativeWidget.selectedIndex = index; + + // We update the value placeholder accordingly + value.innerHTML = optionList[index].innerHTML; + + // And we highlight the corresponding option of our custom widget + highlightOption(select, optionList[index]); +}; + +// This function returns the current selected index in the native widget +// It takes one parameter: +// select : the DOM node with the class `select` related to the native widget +function getIndex(select) { + // We need to access the native widget for the given custom widget + // In our example, that native widget is a sibling of the custom widget + var nativeWidget = select.previousElementSibling; + + return nativeWidget.selectedIndex; +};</pre> + +<p>With these two functions, we can bind the native widgets to the custom ones:</p> + +<pre class="brush: js">// We handle event binding when the document is loaded. +window.addEventListener('load', function () { + var selectList = document.querySelectorAll('.select'); + + // Each custom widget needs to be initialized + selectList.forEach(function (select) { + var optionList = select.querySelectorAll('.option'), + selectedIndex = getIndex(select); + + // We make our custom widget focusable + select.tabIndex = 0; + + // We make the native widget no longer focusable + select.previousElementSibling.tabIndex = -1; + + // We make sure that the default selected value is correctly displayed + updateValue(select, selectedIndex); + + // Each time a user clicks on an option, we update the value accordingly + optionList.forEach(function (option, index) { + option.addEventListener('click', function (event) { + updateValue(select, index); + }); + }); + + // Each time a user uses their keyboard on a focused widget, we update the value accordingly + select.addEventListener('keyup', function (event) { + var length = optionList.length, + index = getIndex(select); + + // When the user hits the down arrow, we jump to the next option + if (event.keyCode === 40 && index < length - 1) { index++; } + + // When the user hits the up arrow, we jump to the previous option + if (event.keyCode === 38 && index > 0) { index--; } + + updateValue(select, index); + }); + }); +});</pre> + +<p>In the code above, it's worth noting the use of the <code><a href="/en-US/docs/Web/API/HTMLElement/tabIndex" title="/en-US/docs/Web/API/HTMLElement/tabIndex">tabIndex</a></code> property. Using this property is necessary to ensure that the native widget will never gain focus, and to make sure that our custom widget gains focus when the user uses his keyboard or his mouse.</p> + +<p>With that, we're done! Here's the result:</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Live example</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_4")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_4" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_4">Check out the source code</a></td> + </tr> + </tbody> +</table> + +<p>But wait a second, are we really done?</p> + +<h2 id="Make_it_accessible">Make it accessible</h2> + +<p>We have built something that works and though we're far from a fully-featured select box, it works nicely. But what we've done is nothing more than fiddle with the DOM. It has no real semantics, and even though it looks like a select box, from the browser's point of view it isn't one, so assistive technologies won't be able to understand it's a select box. In short, this pretty new select box isn't accessible!</p> + +<p>Fortunately, there is a solution and it's called <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a>. ARIA stands for "Accessible Rich Internet Application", and it's <a href="http://www.w3.org/TR/wai-aria/" rel="external" title="http://www.w3.org/TR/wai-aria/">a W3C specification</a> specifically designed for what we are doing here: making web applications and custom widgets accessible. It's basically a set of attributes that extend HTML so that we can better describe roles, states and properties as though the element we've just devised was the native element it tries to pass for. Using these attributes is dead simple, so let's do it.</p> + +<h3 id="The_role_attribute">The <code>role</code> attribute</h3> + +<p>The key attribute used by <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> is the <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> attribute. The <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> attribute accepts a value that defines what an element is used for. Each role defines its own requirements and behaviors. In our example, we will use the <code><a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role">listbox</a></code> role. It's a "composite role", which means elements with that role expect to have children, each with a specific role (in this case, at least one child with the <code>option</code> role).</p> + +<p>It's also worth noting that ARIA defines roles that are applied by default to standard HTML markup. For example, the {{HTMLElement("table")}} element matches the role <code>grid</code>, and the {{HTMLElement("ul")}} element matches the role <code>list</code>. Because we use a {{HTMLElement("ul")}} element, we want to make sure the <code>listbox</code> role of our widget will supersede the <code>list</code> role of the {{HTMLElement("ul")}} element. To that end, we will use the role <code>presentation</code>. This role is designed to let us indicate that an element has no special meaning, and is used solely to present information. We will apply it to our {{HTMLElement("ul")}} element.</p> + +<p>To support the <code><a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques/Using_the_listbox_role">listbox</a></code> role, we just have to update our HTML like this:</p> + +<pre class="brush: html"><!-- We add the role="listbox" attribute to our top element --> +<div class="select" role="listbox"> + <span class="value">Cherry</span> + <!-- We also add the role="presentation" to the ul element --> + <ul class="optList" role="presentation"> + <!-- And we add the role="option" attribute to all the li elements --> + <li role="option" class="option">Cherry</li> + <li role="option" class="option">Lemon</li> + <li role="option" class="option">Banana</li> + <li role="option" class="option">Strawberry</li> + <li role="option" class="option">Apple</li> + </ul> +</div></pre> + +<div class="note"> +<p><strong>Note:</strong> Including both the <code>role</code> attribute and a <code>class</code> attribute is only necessary if you want to support legacy browsers that do not support the <a href="/en-US/docs/CSS/Attribute_selectors" title="/en-US/docs/CSS/Attribute_selectors">CSS attribute selectors</a>.</p> +</div> + +<h3 id="The_aria-selected_attribute">The <code>aria-selected</code> attribute</h3> + +<p>Using the <a href="/en-US/docs/Accessibility/ARIA/ARIA_Techniques" title="/en-US/docs/Accessibility/ARIA/ARIA_Techniques"><code>role</code></a> attribute is not enough. <a href="/en-US/docs/Accessibility/ARIA" title="/en-US/docs/Accessibility/ARIA">ARIA</a> also provides many states and property attributes. The more and better you use them, the better your widget will be understood by assistive technologies. In our case, we will limit our usage to one attribute: <code>aria-selected</code>.</p> + +<p>The <code>aria-selected</code> attribute is used to mark which option is currently selected; this lets assistive technologies inform the user what the current selection is. We will use it dynamically with JavaScript to mark the selected option each time the user chooses one. To that end, we need to revise our <code>updateValue()</code> function:</p> + +<pre class="brush: js">function updateValue(select, index) { + var nativeWidget = select.previousElementSibling; + var value = select.querySelector('.value'); + var optionList = select.querySelectorAll('.option'); + + // We make sure that all the options are not selected + optionList.forEach(function (other) { + other.setAttribute('aria-selected', 'false'); + }); + + // We make sure the chosen option is selected + optionList[index].setAttribute('aria-selected', 'true'); + + nativeWidget.selectedIndex = index; + value.innerHTML = optionList[index].innerHTML; + highlightOption(select, optionList[index]); +};</pre> + +<p>Here is the final result of all these changes (you'll get a better feel for this by trying it with an assistive technology such as <a href="http://www.nvda-project.org/" rel="external" title="http://www.nvda-project.org/">NVDA</a> or <a href="http://www.apple.com/accessibility/voiceover/" rel="external" title="http://www.apple.com/accessibility/voiceover/">VoiceOver</a>):</p> + +<table> + <thead> + <tr> + <th scope="col" style="text-align: center;">Live example</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{EmbedLiveSample("Change_states",120,130, "", "HTML/Forms/How_to_build_custom_form_widgets/Example_5")}}</td> + </tr> + <tr> + <td style="text-align: center;"><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_5" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets/Example_2">Check out the final source code</a></td> + </tr> + </tbody> +</table> + +<h2 id="Conclusion">Conclusion</h2> + +<p>We have seen all the basics of building a custom form widget, but as you can see it's not trivial to do, and often it's better and easier to rely on third-party libraries instead of coding them from scratch yourself (unless, of course, your goal is to build such a library).</p> + +<p>Here are a few libraries you should consider before coding your own:</p> + +<ul> + <li><a href="http://jqueryui.com/" rel="external" title="http://jqueryui.com/">jQuery UI</a></li> + <li><a href="https://github.com/marghoobsuleman/ms-Dropdown" rel="external" title="https://github.com/marghoobsuleman/ms-Dropdown">msDropDown</a></li> + <li><a href="http://www.emblematiq.com/lab/niceforms/" rel="external" title="http://www.emblematiq.com/lab/niceforms/">Nice Forms</a></li> + <li><a href="https://www.google.fr/search?q=HTML+custom+form+controls&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:fr:official&client=firefox-a" rel="external" title="https://www.google.fr/search?q=HTML+custom+form+controls&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:fr:official&client=firefox-a">And many more…</a></li> +</ul> + +<p>If you want to move forward, the code in this example needs some improvement before it becomes generic and reusable. This is an exercise you can try to perform. Two hints to help you in this: the first argument for all our functions is the same, which means those functions need the same context. Building an object to share that context would be wise. Also, you need to make it feature-proof; that is, it needs to be able to work better with a variety of browsers whose compatibility with the Web standards they use vary. Have fun!</p> + +<p>{{PreviousMenuNext("Learn/HTML/Forms/Form_validation", "Learn/HTML/Forms/Sending_forms_through_JavaScript", "Learn/HTML/Forms")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> + +<p> </p> diff --git a/files/es/learn/html/forms/how_to_structure_an_html_form/index.html b/files/es/learn/html/forms/how_to_structure_an_html_form/index.html new file mode 100644 index 0000000000..45f58520d1 --- /dev/null +++ b/files/es/learn/html/forms/how_to_structure_an_html_form/index.html @@ -0,0 +1,320 @@ +--- +title: Cómo estructurar un formulario HTML +slug: Learn/HTML/Forms/How_to_structure_an_HTML_form +translation_of: Learn/Forms/How_to_structure_a_web_form +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Forms/Your_first_form", "Learn/Forms/Basic_native_form_controls", "Learn/Forms")}}</div> + +<p class="summary">Una vez examinados los conceptos básicos, vamos a ver más en detalle los elementos que se utilizan para proporcionar estructura y significado a las diferentes partes de un formulario.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática y de <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">lenguajes HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender cómo se estructuran los formularios HTML y se les proporciona semántica para dotarlos de criterios de usabilidad y accesibilidad.</td> + </tr> + </tbody> +</table> + +<p>La flexibilidad que presentan los formularios los convierte en una de las estructuras más complejas en <a href="/es/docs/Learn/HTML" title="/en-US/docs/HTML">HTML</a>, puesto que puedes crear cualquier tipo de formulario básico a partir de los elementos y atributos destinados a esta función. El uso de una estructura correcta al crear un formulario HTML te ayudará a garantizar que el formulario presente las características de usabilidad y <a href="/es/docs/Learn/Accessibility">accesibilidad </a> adecuadas.</p> + +<h2 id="El_elemento_<form>">El elemento <form></h2> + +<p>El elemento {{HTMLElement ("form")}} define formalmente un formulario y los atributos que determinan el comportamiento del formulario. Cada vez que desees crear un formulario HTML, debes empezar utilizando este elemento y anidando todo el contenido dentro de él. Muchas tecnologías de asistencia y complementos del navegador pueden descubrir elementos {{HTMLElement ("form")}} e implementar códigos de apoyo (<em>hooks</em>) especiales para que sean más fáciles de usar.</p> + +<p>Ya lo vimos en el artículo anterior.</p> + +<div class="warning"><strong>Advertencia:</strong> Está estrictamente prohibido anidar un formulario dentro de otro formulario. Anidar formularios no es una buena idea porque puede ocasionar comportamientos impredecibles.</div> + +<p>Siempre es posible usar controles de formulario fuera de un elemento {{HTMLElement ("form")}}. Si la haces, por defecto ese control no tiene nada que ver con ningún formulario, a menos que lo asocies a algún formulario con el atributo <a href="/en-US/docs/Web/HTML/Attributes/form"><code>form</code></a>. Esto se introdujo para permitir vincular explícitamente un control a un formulario, incluso si este no está dentro de él.</p> + +<p>A continuación vamos a exponer los elementos estructurales que encontrarás en un formulario.</p> + +<h2 id="Los_elementos_<fieldset>_y_<legend>">Los elementos <fieldset> y <legend></h2> + +<p>El elemento {{HTMLElement ("fieldset")}} es una forma cómoda de crear grupos de controles de formulario (también denominados <em>widgets</em>) que comparten el mismo propósito, con fines semánticos y de aplicación de estilo. Puedes etiquetar un elemento {{HTMLElement ("fieldset")}} incluyendo un elemento {{HTMLElement ("legend")}} justo debajo de la etiqueta de apertura {{HTMLElement ("fieldset")}}. El contenido textual del elemento {{HTMLElement ("legend")}} describe formalmente el propósito del elemento {{HTMLElement ("fieldset")}} que está incluido dentro.</p> + +<p>Muchas tecnologías de asistencia utilizarán el elemento {{HTMLElement ("legend")}} como si fuera una parte de la etiqueta de cada control dentro del elemento {{HTMLElement ("fieldset")}} correspondiente. Por ejemplo, algunos lectores de pantalla como <a href="http://www.freedomscientific.com/products/software/jaws/" rel="external" title="http://www.freedomscientific.com/products/fs/jaws-product-page.asp">Jaws</a> y <a href="http://www.nvda-project.org/" rel="external" title="http://www.nvda-project.org/">NVDA</a> leerán el contenido de la leyenda antes de decir la etiqueta de cada control.</p> + +<p>Un pequeño ejemplo:</p> + +<pre class="brush:html; notranslate"><form> + <fieldset> + <legend>Tamaño del zumo de fruta</legend> + <p> + <input type="radio" name="size" id="size_1" value="small"> + <label for="size_1">Pequeño</label> + </p> + <p> + <input type="radio" name="size" id="size_2" value="medium"> + <label for="size_2">Mediano</label> + </p> + <p> + <input type="radio" name="size" id="size_3" value="large"> + <label for="size_3">Grande</label> + </p> + </fieldset> +</form></pre> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/fieldset-legend.html">fieldset-legend.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/fieldset-legend.html">consúltalo en vivo</a>).</p> +</div> + +<p>Al leer el formulario anterior, un lector de pantalla dirá «Tamaño del zumo de fruta: pequeño» para el primer control de formulario, «Tamaño del zumo de fruta: mediano» para el segundo y «Tamaño del zumo de fruta: grande» para el tercero.</p> + +<p>El caso de uso que se muestra en este ejemplo es uno de los más importantes. Cada vez que tengas un conjunto de botones de opción, debes anidarlos dentro de un elemento {{HTMLElement ("fieldset")}}. Hay otros casos de uso y el elemento {{HTMLElement ("fieldset")}} también se puede usar en general para seccionar un formulario. Idealmente, los formularios largos deberían tener una extensión de varias páginas, pero si un formulario se alarga y ha de estar contenido en una sola página, colocar las diferentes secciones relacionadas dentro de diferentes conjuntos de campos mejora su usabilidad.</p> + +<p>Debido a la influencia que tiene sobre las tecnologías de asistencia, el elemento {{HTMLElement ("fieldset")}} es uno de los elementos clave para crear formularios accesibles. Sin embargo, no hay que abusar de él. Si es posible, cada vez que crees un formulario, intenta <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Screenreaders">escuchar cómo lo interpreta un lector de pantalla</a>. Si suena raro, intenta mejorar la estructura del formulario.</p> + +<h2 id="El_elemento_<label>">El elemento <label></h2> + +<p>Como vimos en el artículo anterior, el elemento {{HTMLElement ("label")}} es la forma formal de definir una etiqueta para un control de un formulario HTML. Este es el elemento más importante si deseas crear formularios accesibles porque cuando se implementan correctamente, los lectores de pantalla leen la etiqueta de un elemento de formulario junto con las instrucciones relacionadas, y esto además resulta muy útil para los usuarios videntes. Tomemos este ejemplo que vimos en el artículo anterior:</p> + +<pre class="brush: html notranslate"><label for="name">Nombre:</label> <input type="text" id="name" name="user_name"></pre> + +<p>Con la etiqueta <code><label></code> asociada correctamente con <code><input></code> por su atributo <code>for</code> (que contiene el atributo <code>id</code> del elemento <code><input></code>), un lector de pantalla leerá algo como «Nombre, editar texto».</p> + +<p>Hay otra forma de asociar un control de formulario con una etiqueta: asociarlo implícitamente anidando el control de formulario dentro de <code><label></code>.</p> + +<pre class="brush: html notranslate"><label for="name"> + Nombre: <input type="text" id="name" name="user_name"> +</label></pre> + +<p>Incluso en estos casos, se aconseja establecer el atributo <code>for</code> para garantizar que todas las tecnologías de asistencia comprendan la relación entre la etiqueta y el control de formulario.</p> + +<p>Si no hay ninguna etiqueta, o si el control de formulario no está asociado implícita o explícitamente con alguna etiqueta, un lector de pantalla leerá algo así como «Editar texto en blanco», lo cual no es de mucha ayuda.</p> + +<h3 id="¡También_se_puede_hacer_clic_en_las_etiquetas!">¡También se puede hacer clic en las etiquetas!</h3> + +<p>Otra ventaja de configurar correctamente las etiquetas es que puedes hacer clic o pulsar en la etiqueta para activar el control de formulario correspondiente. Esto es útil para controles como entradas de texto, donde puedes hacer clic tanto en la etiqueta como en la entrada de texto para proporcionar el foco al control de formulario, pero es útil especialmente para botones de opción y casillas de verificación, porque la zona sensible de este control puede ser muy pequeña, y puede ser útil para facilitar su activación.</p> + +<p>Por ejemplo, al hacer clic en el texto de la etiqueta «Me gustan las cerezas» del ejemplo siguiente, cambiará el estado seleccionado de la casilla de verificación <em>taste_cherry</em>:</p> + +<pre class="brush:html; notranslate"><form> + <p> + <input type="checkbox" id="taste_1" name="taste_cherry" value="cherry"> + <label for="taste_1">Me gustan las cerezas</label> + </p> + <p> + <input type="checkbox" id="taste_2" name="taste_banana" value="banana"> + <label for="taste_2">Me gustan los plátanos</label> + </p> +</form></pre> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/checkbox-label.html">checkbox-label.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/checkbox-label.html">consúltalo en vivo</a>).</p> +</div> + +<h3 id="Etiquetas_múltiples">Etiquetas múltiples</h3> + +<p>Estrictamente hablando, es posible poner varias etiquetas en un solo control de formulario, pero no suele ser una buena idea porque algunas tecnologías de asistencia pueden tener problemas para manejarlas. En caso de tener varias etiquetas, hay que anidar el control de formulario y sus etiquetas dentro de un único elemento {{htmlelement ("label")}}.</p> + +<p>Consideremos este ejemplo:</p> + +<pre class="brush: html notranslate"><p>Los campos obligatorios se marcan con un <abbr title = "required">*</abbr>.</p> + +<!-- Así que esto: --> +<div> + <label for="username">Nombre:</label> + <input type="text" name="username"> + <label for="username"><abbr title="required" aria-label="required">*</abbr></label> +</div> + +<!-- sería mejor hacerlo así: --> +<div> + <label for="username"> + <span>Nombre:</span> + <input id="username" type="text" name="username"> + <abbr title="required" aria-label="required">*</abbr> + </label> +</div> + +<!-- Pero probablemente lo mejor es esto: --> +<div> + <label for="username">Nombre: <abbr title="required" aria-label="required">*</abbr></label> + <input id="username" type="text" name="username"> +</div></pre> + +<p>{{EmbedLiveSample("Etiquetas_múltiples", 120, 120)}}</p> + +<p>El párrafo de la parte superior establece una regla para los elementos que son obligatorios. La regla ha de incluirse <em>antes</em> de usarse para que tanto los usuarios videntes como los usuarios que utilizan tecnologías de asistencia y lectores de pantalla, sepan lo que significa antes de encontrar un elemento obligatorio. Pero si bien esto ayuda a informar a los usuarios de lo que significa un asterisco, no es posible confiar plenamente en ello. Cuando un lector de pantalla se encuentre con un asterisco pronunciará «estrella». Cuando un usuario vidente pase el ratón por encima, debería aparecer una etiqueta de «obligatorio», lo cual se logra con el uso del atributo <code>title</code>. Pero los títulos que se leen en voz alta dependen de la configuración del lector de pantalla, por lo que es más fiable incluir también el atributo <code><a href="/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques/Using_the_aria-label_attribute">aria-label</a></code>, que los lectores de pantalla siempre leen.</p> + +<p>Las variantes anteriores aumentan en efectividad a medida que se avanza por ellas:</p> + +<ul> + <li>En el primer ejemplo, la etiqueta no se lee en absoluto con la entrada de texto; solo se obtiene «Editar texto en blanco», y además las etiquetas se leen por separado. Los múltiples elementos <code><label></code> confunden al lector de pantalla.</li> + <li>En el segundo ejemplo, las cosas son un poco más claras: la etiqueta que se lee junto con la entrada de texto es «Editar texto nombre estrella nombre obligatorio», pero las etiquetas aún se leen por separado. Las cosas continúan siendo un poco confusas, pero esta vez funciona algo mejor porque <code><input></code> tiene una etiqueta asociada.</li> + <li>El tercer ejemplo es el mejor: la etiqueta se lee en conjunto, y la etiqueta que se lee con la entrada es «Editar texto nombre requerido».</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Es posible que obtengas resultados ligeramente diferentes dependiendo de tu lector de pantalla. Esta prueba se hizo con VoiceOver (NVDA se comporta de manera similar). Nos encantaría conocer tus experiencias.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/required-labels.html">required-labels.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/required-labels.html">o consultarlo en vivo</a>). No pruebes el ejemplo con las dos o tres versiones sin los comentarios porque los lectores de pantalla se confundirán si hay múltiples etiquetas y múltiples entradas con el mismo ID.</p> +</div> + +<h2 id="Estructuras_HTML_comunes_que_se_utilizan_en_los_formularios">Estructuras HTML comunes que se utilizan en los formularios</h2> + +<p>Más allá de las estructuras específicas de los formularios web, es bueno recordar que el marcado de los formularios es solo HTML. Esto significa que puedes usar todo el poder del HTML para estructurar un formulario web.</p> + +<p>Como puedes ver en los ejemplos, es una práctica común delimitar una etiqueta y su control de formulario con un elemento {{HTMLElement ("li")}} dentro de una lista {{HTMLElement ("ul")}} o {{HTMLElement ("ol")}}. Los elementos {{HTMLElement ("p")}} y {{HTMLElement ("div")}} también se usan con frecuencia. Se recomiendan las listas para estructurar múltiples casillas de verificación o botones de opción.</p> + +<p>Además del elemento {{HTMLElement ("fieldset")}}, también es una práctica común usar títulos HTML (por ejemplo, {{htmlelement ("h1")}}, {{htmlelement ("h2")}}), y seccionar (por ejemplo, {{htmlelement ("section")}}), para estructurar formas complejas.</p> + +<p>Depende de ti, sobre todo, encontrar un estilo de codificación cómodo que dé como resultado formas con buena accesibilidad y usabilidad. Las secciones independientes con funciones diferentes deben estar contenidas en elementos {{htmlelement ("section")}} separados, con elementos {{htmlelement ("fieldset")}} para contener botones de opción.</p> + +<h3 id="Aprendizaje_activo_construir_una_estructura_de_formulario">Aprendizaje activo: construir una estructura de formulario</h3> + +<p>Pongamos en práctica estas ideas y creemos un formulario un poco más complicado: un formulario de pago. Este formulario contendrá una serie de tipos de control que quizás aún no comprendas. No te preocupes por esto por ahora; en el artículo siguiente descubrirás cómo funcionan (<a href="/es/docs/Learn/HTML/Forms/The_native_form_widgets">Los controles básicos de formulario originales</a>). Por ahora, lee con detenimiento las descripciones y sigue las instrucciones, y empieza a formarte una idea de qué elementos de delimitación se utilizan para estructurar el formulario y por qué.</p> + +<ol> + <li>Para comenzar, haz una copia local de nuestro <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">archivo de plantilla en blanco</a> y el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/payment-form.css">CSS de nuestro formulario de pago</a> en un nuevo directorio de tu ordenador.</li> + <li>Añade dentro del elemento HTML {{htmlelement ("head")}} la línea siguiente para aplicar el CSS al HTML: + <pre class="brush: html notranslate"><link href="payment-form.css" rel="stylesheet"></pre> + </li> + <li>A continuación, añade el elemento externo {{htmlelement ("form")}} para crear tu formulario: + <pre class="brush: html notranslate"><form> + +</form></pre> + </li> + <li>Añade un encabezado y un párrafo dentro de las etiquetas <code><form></code>> para informar a los usuarios cómo se marcan los campos obligatorios: + <pre class="brush: html notranslate"><h1>Forma de pago</h1> +<p>Los campos obligatorios van seguidos de <strong> <abbr title = "required"> * </abbr> </strong>.</p></pre> + </li> + <li>A continuación añadimos al formulario una sección de código más grande, justo debajo de nuestra entrada anterior. Aquí verás que delimitamos con un elemento {{htmlelement ("section")}} independiente los campos con la información de contacto. Además, hay un conjunto de dos botones de opción, cada uno de los cuales colocamos dentro de su elemento de lista ({{htmlelement ("li")}}) propio. También hay dos entradas de texto estándar {{htmlelement ("input")}} y sus elementos {{htmlelement ("label")}} asociados, cada uno anidado dentro de un elemento {{htmlelement ("p")}} y una entrada de texto para introducir una contraseña. Añade este código a tu formulario: + <pre class="brush: html notranslate"><section> + <h2>Información de contacto</h2> + <fieldset> + <legend>Título</legend> + <ul> + <li> + <label for="title_1"> + <input type="radio" id="title_1" name="title" value="K" > + Rey + </label> + </li> + <li> + <label for="title_2"> + <input type="radio" id="title_2" name="title" value="Q"> + Reina + </label> + </li> + <li> + <label for="title_3"> + <input type="radio" id="title_3" name="title" value="J"> + Bufón + </label> + </li> + </ul> + </fieldset> + <p> + <label for="name"> + <span>Nombre:</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="text" id="name" name="username"> + </p> + <p> + <label for="mail"> + <Span>Correo electrónico:</ span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="email" id="mail" name="usermail"> + </p> + <p> + <label for="pwd"> + <span>Contraseña:</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="password" id="pwd" name="password"> + </p> +</section></pre> + </li> + <li>La segunda <code><section></code> de nuestro formulario es la información de pago. Hay tres controles diferentes, junto con sus etiquetas, cada uno contenido dentro de un elemento <code><p></code>. El primero es un menú desplegable ({{htmlelement ("select")}}) para seleccionar el tipo de tarjeta de crédito. El segundo es un elemento <code><input></code> de tipo <code>tel</code>, para introducir un número de tarjeta de crédito. Si bien podríamos haber usado el tipo <code>number</code>, no queremos una interfaz de usuario con control de número. El último es un elemento <code><input></code> de tipo <code>date</code>, para introducir la fecha de caducidad de la tarjeta; aparecerá como un control de selección de fecha en navegadores compatibles, y como una entrada de texto normal en navegadores no compatibles. Estos tipos de entrada más nuevos volverán a aparecer en el artículo <a href="/en-US/docs/Learn/Forms/HTML5_input_types">Tipos de entrada HTML5</a>.<br> + <br> + Introduce los datos siguientes a continuación de la sección anterior: + <pre class="brush: html notranslate"><section> + <h2>Información de pago</h2> + <p> + <label for="card"> + <span>Tipo de tarjeta:</span> + </label> + <select id="card" name="usercard"> + <option value="visa">Visa</option> + <option value="mc">Mastercard</option> + <option value="amex">American Express</option> + </select> + </p> + <p> + <label for="number"> + <span>Número de tarjeta:</span> + <strong><abbr title="required">*</abbr></strong> + </label> + <input type="tel" id="number" name="cardnumber"> + </p> + <p> + <label for="date"> + <span>Fecha de caducidad:</span> + <strong><abbr title="required">*</abbr></strong> + <em>el formato mm/aa</em> + </label> + <input type="date" id="date" name="expiration"> + </p> +</section></pre> + </li> + <li>La última sección que añadimos es mucho más simple y contiene solo un {{htmlelement ("button")}} de tipo <code>submit</code>, para enviar los datos del formulario. Añádelo al final de tu formulario: + <pre class="brush: html notranslate"><p> <button type="submit">Validar el pago</button> </p></pre> + </li> +</ol> + +<p>Debajo puedes ver en acción el formulario terminado (también lo encontrarás en GitHub; consulta el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/html-form-structure/payment-form.html">código fuente</a> de nuestro payment-form.html y <a href="https://mdn.github.io/learning-area/html/forms/html-form-structure/payment-form.html">ejecútalo en vivo</a>):</p> + +<p>{{EmbedLiveSample("A_payment_form","100%",620, "", "/en-US/Learn/Forms/How_to_structure_a_web_form/Example")}}</p> + +<h2 id="¡Prueba_tus_habilidades!">¡Prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo pero ¿puedes recordar la información más importante? Puedes encontrar pruebas adicionales para comprobar que has comprendido la información antes de continuar — visita <a class="external external-icon" href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Forms/Test_your_skills:_Form_structure" rel="noopener">Prueba tus habilidades: Estructura de formularios</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahora tienes todos los conocimientos necesarios para estructurar adecuadamente tus formularios web. Expondremos muchas de las características que se presentan aquí en los artículos siguientes, y el próximo artículo analizará con más detalle el uso de todos los diferentes tipos de controles de formulario que vas a querer usar para recopilar la información de tus usuarios.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="http://www.alistapart.com/articles/sensibleforms/" rel="external" title="http://www.alistapart.com/articles/sensibleforms/">A List Apart: <em>Sensible Forms: A Form Usability Checklist</em></a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/Forms/Your_first_form", "Learn/Forms/Basic_native_form_controls", "Learn/Forms")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Tu primer formulario HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">Cómo estructurar un formulario HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">Los controles básicos de formulario originales</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML5_input_types">Tipos de entrada HTML5</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Additional_form_controls">Controles de formulario adicionales</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/UI_pseudo-classes">Pseudoclasses UI</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Aplicar estilo a formularios HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Validación de datos en un formulario</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a></li> +</ul> + +<h3 id="Temas_avanzados">Temas avanzados</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Enviar formularios con JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">Cómo crear controles de formulario personalizados</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">Formularios HTML en navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Cuestiones avanzadas de aplicación de estilo para formularios HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad de los controles de formulario</a> según su código propietario</li> +</ul> diff --git a/files/es/learn/html/forms/index.html b/files/es/learn/html/forms/index.html new file mode 100644 index 0000000000..c607c7993a --- /dev/null +++ b/files/es/learn/html/forms/index.html @@ -0,0 +1,366 @@ +--- +title: Formularios HTML +slug: Learn/HTML/Forms +tags: + - Featured + - Forms + - Formulario(2) + - Guide + - Guía + - HTML + - NeedsTranslation + - TopicStub + - Web +translation_of: Learn/Forms +--- +<p><span class="seoSummary">Esta guía está constituida por una serie de artículos que te ayudarán a dominar los formularios en HTML. </span>El formulario HTML es una herramienta cuya finalidad es interactuar con el usuario; sin embargo, debido a razones históricas y técnicas, no siempre resulta obvio como explotar su enorme potencial. En esta guía, cubriremos todos los aspectos de los formularios HTML, desde su estructura hasta su estilo, desde la manipulación de sus datos hasta los <em>widgets</em> personalizados. ¡Aprenderás a disfrutar de las grandes prestaciones que nos brindan!</p> + +<h2 id="Artículos">Artículos</h2> + +<ol> + <li><a href="/en-US/docs/HTML/Forms/My_first_HTML_form" title="/en-US/docs/HTML/Forms/My_first_HTML_form">Mi primer formulario HTML</a></li> + <li><a href="/en-US/docs/HTML/Forms/How_to_structure_an_HTML_form" title="/en-US/docs/HTML/Forms/How_to_structure_an_HTML_form"><span>Cómo estructurar un formulario HTML</span></a></li> + <li><a href="/en-US/docs/HTML/Forms/The_native_form_widgets" title="/en-US/docs/HTML/Forms/The_native_form_widgets"><span>Los <em>widgets</em> nativos de formulario</span></a></li> + <li>CSS para formularios HTML + <ol> + <li><a href="/en-US/docs/HTML/Forms/Styling_HTML_forms" title="/en-US/docs/HTML/Forms/Styling_HTML_forms"><span>Aplicando estilos a formularios HTML</span></a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Forms/Advanced_styling_for_HTML_forms" title="/en-US/docs/Advanced_styling_for_HTML_forms">Estilos avanzados para formularios HTML</a></li> + <li><a href="/en-US/docs/Property_compatibility_table_for_form_widgets" title="/en-US/docs/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad de propiedades para <em>widgets</em> de formulario</a></li> + </ol> + </li> + <li><a href="/en-US/docs/HTML/Forms/Sending_and_retrieving_form_data" title="/en-US/docs/HTML/Forms/Sending_and_retrieving_form_data"><span>Enviando y recibiendo datos</span></a></li> + <li><a href="/en-US/docs/HTML/Forms/Data_form_validation" title="/en-US/docs/HTML/Forms/Data_form_validation">Validación de los datos del formulario</a></li> + <li><a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">Cómo crear un <em>widget</em> de formulario personalizado</a></li> + <li><a href="/en-US/docs/HTML/Forms/Sending_forms_through_JavaScript" title="/en-US/docs/HTML/Forms/Sending_forms_through_JavaScript">Enviando formularios mediante JavaScript</a> + <ol> + <li><a href="/en-US/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects" title="/en-US/docs/DOM/XMLHttpRequest/FormData/Using_FormData_Objects">Usando el objeto FormData</a></li> + </ol> + </li> + <li><a href="/en-US/docs/HTML/Forms/HTML_forms_in_legacy_browsers" title="/en-US/docs/HTML/Forms/HTML_forms_in_legacy_browsers">Formularios HTML en navegadores antiguos</a></li> +</ol> + +<h2 id="Documentación_HTML">Documentación HTML</h2> + +<h3 id="HTML_Elements">HTML Elements</h3> + +<table> + <thead> + <tr> + <th scope="col">Elemento</th> + <th scope="col">Interfaz DOM relacionada</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td style="vertical-align: top;">{{HTMLElement("button")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLButtonElement")}}</td> + <td style="vertical-align: top;">El elemento <code>button</code> representa un boton clickeable.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("datalist")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLDataListElement")}}</td> + <td style="vertical-align: top;">El elemento <span style="font-family: courier new;">datalist</span> element contiene un conjunto de elementos{{ HTMLElement("option") }} que representan posibles opciones para el valor de otros elementos del formulario.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("fieldset")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLFieldSetElement")}}</td> + <td style="vertical-align: top;">El <span style="font-family: courier new;">fieldset</span> se usa para agrupar distintos elementos dentro de un formulario.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("form")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLFormElement")}}</td> + <td style="vertical-align: top;">El elemento <code>form </code>representa una seccion del documento html que contiene elementos interactivos a traves de los cuales se le permite al usuario enviar informacion hacia un servidor web.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("input")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLInputElement")}}</td> + <td style="vertical-align: top;">El elemento <code>input</code> es usado para crear controles interactivos para los formularios.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("keygen")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLKeygenElement")}}</td> + <td style="vertical-align: top;">El elemento <code>keygen</code> existe para facilitar la generación de llaves u el envío de las llaves publicas como parte de un formulario HTML.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("label")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLLabelElement")}}</td> + <td style="vertical-align: top;">El <code>label</code> determina un título para un item de la interfaz del usuario.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("legend")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLLegendElement")}}</td> + <td style="vertical-align: top;">El elemento <code>legend</code> representa una etiqueta para el contenido del elemento {{ HTMLElement("fieldset") }} que lo contiene.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("meter")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLMeterElement")}}</td> + <td style="vertical-align: top;">EL elemento <code>meter</code> representa un valor escalar dentro de un rango conocido, o un valor fraccional.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("optgroup")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLOptGroupElement")}}</td> + <td style="vertical-align: top;"> + <p>El elemento <code>optgroup</code> crea un grupo de opciones dentro de un elemento {{ HTMLElement("select") }} .</p> + </td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("option")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLOptionElement")}}</td> + <td style="vertical-align: top;">El elemento<em> </em><code>option<em> </em></code>es usado para crear un control de opcion que representa un item dentro de alguno de los elementos {{ HTMLElement("select") }}, {{ HTMLElement("optgroup") }} o {{ HTMLElement("datalist") }} .</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("output")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLOutputElement")}}</td> + <td style="vertical-align: top;">El elemento <code>output</code> representa un resultado de un calculo.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("progress")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLProgressElement")}}</td> + <td style="vertical-align: top;">El elemento <code>progress</code> es usado para mostrar el progreso de la realización de una tarea.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("select")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLSelectElement")}}</td> + <td style="vertical-align: top;">El elemento <code>select</code> representa el control que presenta un menu de opciones.</td> + </tr> + <tr> + <td style="vertical-align: top;">{{HTMLElement("textarea")}}</td> + <td style="vertical-align: top;">{{domxref("HTMLTextAreaElement")}}</td> + <td style="vertical-align: top;">EL elemento <code>textarea</code> representa un campo multi-linea de edicion de text plano.</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Nota:</strong> Todos los elementos de formulario, al igual que el resto de elementos HTML, soportan la interfaz DOM {{domxref("HTMLElement")}}.</p> +</div> + +<h3 id="HTML_Attributes">HTML Attributes</h3> + +<table class="standard-table"> + <thead> + <tr> + <th>Nombre del atributo</th> + <th>Elementos</th> + <th>Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td>accept</td> + <td>{{ HTMLElement("form") }}, {{ HTMLElement("input") }}</td> + <td>Lista de tipos que acepta el servidor, típicamente un tipo de fichero.</td> + </tr> + <tr> + <td style="white-space: nowrap;">accept-charset</td> + <td>{{ HTMLElement("form") }}</td> + <td>Lista de <em>charsets </em>(conjuntos de caracteres) aceptados.</td> + </tr> + <tr> + <td>action</td> + <td>{{ HTMLElement("form") }}</td> + <td>La URI del programa con el que procesar la información enviada a mediante el formulario.</td> + </tr> + <tr> + <td>autocomplete</td> + <td>{{ HTMLElement("form") }}, {{ HTMLElement("input") }}</td> + <td>Indica si los controles en este formulario serán o no autocompletados por el navegador</td> + </tr> + <tr> + <td>autofocus</td> + <td>{{ HTMLElement("button") }}, {{ HTMLElement("input") }}, {{ HTMLElement("keygen") }}, {{ HTMLElement("select") }}, {{ HTMLElement("textarea") }}</td> + <td>El elemento debería poseer el foco automáticamente tras cargar la página.</td> + </tr> + </tbody> + <tbody> + <tr> + <td>challenge</td> + <td>{{ HTMLElement("keygen") }}</td> + <td>Una cadena de comprobación que es enviada junto con la clave pública.</td> + </tr> + <tr> + <td>checked</td> + <td>{{ HTMLElement("input") }}</td> + <td>Indica si el elemento debe estar seleccionado (checked) tras cargar la página.</td> + </tr> + <tr> + <td>cols</td> + <td>{{ HTMLElement("textarea") }}</td> + <td>Define el número de columnas en un elemento de tipo textarea.</td> + </tr> + <tr> + <td>data</td> + <td>{{ HTMLElement("object") }}</td> + <td>Especifica la URL del recurso.</td> + </tr> + <tr> + <td>dirname</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("textarea") }}</td> + <td> </td> + </tr> + <tr> + <td>disabled</td> + <td>{{ HTMLElement("button") }}, {{ HTMLElement("fieldset") }}, {{ HTMLElement("input") }}, {{ HTMLElement("keygen") }}, {{ HTMLElement("optgroup") }}, {{ HTMLElement("option") }}, {{ HTMLElement("select") }}, {{ HTMLElement("textarea") }}</td> + <td>Indica si el usuario puede o no interactuar con el elemento.</td> + </tr> + <tr> + <td>enctype</td> + <td>{{ HTMLElement("form") }}</td> + <td>Define el tipo de contenido del formulario cuando el método de envío es POST.</td> + </tr> + <tr> + <td>for</td> + <td>{{ HTMLElement("label") }}, {{ HTMLElement("output") }}</td> + <td> + <p>Establece una asociación con otros elementos</p> + </td> + </tr> + <tr> + <td>form</td> + <td>{{ HTMLElement("button") }}, {{ HTMLElement("fieldset") }}, {{ HTMLElement("input") }}, {{ HTMLElement("keygen") }}, {{ HTMLElement("label") }}, {{ HTMLElement("meter") }}, {{ HTMLElement("object") }}, {{ HTMLElement("output") }}, {{ HTMLElement("progress") }}, {{ HTMLElement("select") }}, {{ HTMLElement("textarea") }}</td> + <td>Indica el elemento <strong>form</strong> que contiene este elemento.</td> + </tr> + </tbody> + <tbody> + <tr> + <td>high</td> + <td>{{ HTMLElement("meter") }}</td> + <td>Indicates the lower bound of the upper range.</td> + </tr> + <tr> + <td>keytype</td> + <td>{{ HTMLElement("keygen") }}</td> + <td>Especifica el tipo de clave generada.</td> + </tr> + <tr> + <td>list</td> + <td>{{ HTMLElement("input") }}</td> + <td>Determina una lista de opciones predefinidas para sugerir al usuario.</td> + </tr> + <tr> + <td>low</td> + <td>{{ HTMLElement("meter") }}</td> + <td>Indicates the upper bound of the lower range.</td> + </tr> + <tr> + <td>max</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("meter") }}, {{ HTMLElement("progress") }}</td> + <td>Indica el máximo valor permitido.</td> + </tr> + <tr> + <td>maxlength</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("textarea") }}</td> + <td>Define el máximo número de caracteres permitidos en el elemento.</td> + </tr> + <tr> + <td>method</td> + <td>{{ HTMLElement("form") }}</td> + <td> + <p>Define qué método HTTP se usará al enviar el formulario. puede ser <strong>GET</strong> (por defecto) o <strong>POST</strong></p> + </td> + </tr> + <tr> + <td>min</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("meter") }}</td> + <td>Indica el mínimo valor permitido.</td> + </tr> + <tr> + <td>multiple</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("select") }}</td> + <td>Indica si mútiples valores pueden ser introducidos en un input de tipo email o file.</td> + </tr> + <tr> + <td>name</td> + <td>{{ HTMLElement("button") }}, {{ HTMLElement("form") }}, {{ HTMLElement("fieldset") }}, {{ HTMLElement("input") }}, {{ HTMLElement("keygen") }}, {{ HTMLElement("output") }}, {{ HTMLElement("select") }}, {{ HTMLElement("textarea") }}</td> + <td>Especifica el nombre del elemento. Este nombre se usará asociado al dato que contiene al enviar al servidor el formulario.</td> + </tr> + <tr> + <td>novalidate</td> + <td>{{ HTMLElement("form") }}</td> + <td>Indica que el formulario no debería validarse al momento de ser enviado.</td> + </tr> + <tr> + <td>optimum</td> + <td>{{ HTMLElement("meter") }}</td> + <td>Indica el valor numérico óptimo.</td> + </tr> + <tr> + <td>pattern</td> + <td>{{ HTMLElement("input") }}</td> + <td>Establece la expresión regular con la que validar el valor del elemento.</td> + </tr> + <tr> + <td>placeholder</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("textarea") }}</td> + <td>Proporciona una pista al usuario de lo que el campo debe contener. Se muestra cuando el campo está vacío.</td> + </tr> + <tr> + <td>readonly</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("textarea") }}</td> + <td>Indica si el elemento se puede o no editar.</td> + </tr> + <tr> + <td>required</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("select") }}, {{ HTMLElement("textarea") }}</td> + <td>Cuando un campo del formulario es requerido, el usuario no puede dejarlo vacío.</td> + </tr> + <tr> + <td>rows</td> + <td>{{ HTMLElement("textarea") }}</td> + <td>Defines the number of rows in a textarea.</td> + </tr> + <tr> + <td>selected</td> + <td>{{ HTMLElement("option") }}</td> + <td>En una lista de selección, la opción con el atributo selected será la que está seleccionada por defecto</td> + </tr> + <tr> + <td>size</td> + <td>{{ HTMLElement("input") }}, {{ HTMLElement("select") }}</td> + <td>Defina la anchura del elemento (en píxeles). Si el elemento es de tipo <strong>text</strong> o <strong>password</strong> el ancho se referirá al número de caracteres.</td> + </tr> + <tr> + <td>src</td> + <td>{{ HTMLElement("img") }}</td> + <td>El URL del recurso</td> + </tr> + <tr> + <td>step</td> + <td>{{ HTMLElement("input") }}</td> + <td>Determina el incremento de cada paso con el que se cubre un rango desde un valor mínimo hasta un valor máximo.</td> + </tr> + <tr> + <td>target</td> + <td>{{ HTMLElement("form") }}</td> + <td> </td> + </tr> + <tr> + <td>type</td> + <td>{{ HTMLElement("button") }}, {{ HTMLElement("input") }}</td> + <td>Determina el tipo del elemento.</td> + </tr> + <tr> + <td>usemap</td> + <td>{{ HTMLElement("input") }}</td> + <td> </td> + </tr> + <tr> + <td>value</td> + <td>{{ HTMLElement("button") }}, {{ HTMLElement("option") }}, {{ HTMLElement("input") }}, {{ HTMLElement("meter") }}, {{ HTMLElement("progress") }}</td> + <td>Establece el valor actual del elemento.</td> + </tr> + <tr> + <td>wrap</td> + <td>{{ HTMLElement("textarea") }}</td> + <td>Cuando un texto tiene una longitud mayor que el ancho del elemento sobre el que se muestra, determina si el elemento debe simular saltos de línea para que todo el texto quede visible en el elemento.</td> + </tr> + </tbody> +</table> + +<h3 id="Referencia_a_la_normativa">Referencia a la normativa</h3> + +<ul> + <li><a href="http://www.w3.org/html/wg/drafts/html/master/forms.html#forms" lang="en" rel="external" title="http://www.w3.org/TR/html5/forms.html">W3C HTML 5.1 Specification (Forms)</a></li> + <li><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#forms" rel="external" title="http://www.whatwg.org/specs/web-apps/current-work/multipage/forms.html#forms">WHATWG HTML Living Standard (Forms)</a></li> +</ul> diff --git a/files/es/learn/html/forms/property_compatibility_table_for_form_controls/index.html b/files/es/learn/html/forms/property_compatibility_table_for_form_controls/index.html new file mode 100644 index 0000000000..115b5580fe --- /dev/null +++ b/files/es/learn/html/forms/property_compatibility_table_for_form_controls/index.html @@ -0,0 +1,2003 @@ +--- +title: Tabla de compatibilidad de propiedades CSS para controles de formulario +slug: Learn/HTML/Forms/Property_compatibility_table_for_form_controls +translation_of: Learn/Forms/Property_compatibility_table_for_form_controls +--- +<div>{{learnsidebar}}</div> + +<p class="summary">Las siguientes tablas de compatibilidad intentan resumir el estado del soporte de CSS para formularios HTML. Debido a la complejidad de los formularios CSS y HTML, estas tablas no se pueden considerar una referencia perfecta. Sin embargo, le darán una buena idea de lo que se puede y no se puede hacer, lo que le ayudará al aprender a hacer las cosas.</p> + +<h2 id="Cómo_leer_las_tablas">Cómo leer las tablas</h2> + +<h3 id="Valores">Valores</h3> + +<p>Para cada propiedad, hay cuatro valores posibles:</p> + +<dl> + <dt>Si</dt> + <dd>Existe un soporte razonablemente consistente para la propiedad en todos los navegadores. Es posible que aún enfrente efectos secundarios extraños en ciertos casos extremos.</dd> + <dt>Parcial</dt> + <dd>Si bien la propiedad funciona, con frecuencia puede enfrentar efectos secundarios extraños o inconsistencias. Probablemente debería evitar estas propiedades a menos que primero domine esos efectos secundarios.</dd> + <dt>No</dt> + <dd>La propiedad simplemente no funciona o es tan inconsistente que no es confiable.</dd> + <dt>n.a.</dt> + <dd>La propiedad no tiene ningún significado para este tipo de widget.</dd> +</dl> + +<h3 id="Representación">Representación</h3> + +<p>Para cada propiedad hay dos representaciones posibles:</p> + +<dl> + <dt>N (Normal)</dt> + <dd>Indica que la propiedad se aplica tal cual</dd> + <dt>T (Retocada)</dt> + <dd>Indica que la propiedad se aplica con la regla adicional como se muestra a continuación:</dd> +</dl> + +<pre class="brush: css notranslate">* { + /* Turn off the native look and feel */ + -webkit-appearance: none; + appearance: none; + +/* for Internet Explorer */ + background: none; +}</pre> + +<h2 id="Tablas_de_compatibilidad">Tablas de compatibilidad</h2> + +<h3 id="Comportamientos_globales">Comportamientos globales</h3> + +<p>Algunos comportamientos son comunes a muchos navegadores a nivel global::</p> + +<dl> + <dt>{{cssxref("border")}}, {{cssxref("background")}}, {{cssxref("border-radius")}}, {{cssxref("height")}}</dt> + <dd>El uso de una de estas propiedades puede desactivar parcial o totalmente la apariencia nativa de los widgets en algunos navegadores. Tenga cuidado cuando los use.</dd> + <dt>{{cssxref("line-height")}}</dt> + <dd>Esta propiedad se admite de forma inconsistente en todos los navegadores y debe evitarla.</dd> + <dt>{{cssxref("text-decoration")}}</dt> + <dd>Esta propiedad no es compatible con el navegador Opera en widgets de formulario.</dd> + <dt>{{cssxref("text-overflow")}}</dt> + <dd>Opera, Safari, y IE9 no admiten esta propiedad en widgets de formulario.</dd> + <dt>{{cssxref("text-shadow")}}</dt> + <dd>Opera no admite {{cssxref("text-shadow")}} en widgets de formularios e IE9 no lo admite en absoluto.</dd> +</dl> + +<h3 id="Text_fields">Text fields</h3> + +<p>See the <code>{{htmlelement("input/text", "text")}}</code>, <code>{{htmlelement("input/search", "search")}}</code>, and <code>{{htmlelement("input/password", "password")}}</code> input types.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields.</li> + <li>On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields.</li> + <li>On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields.</li> + <li>On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}<sup>[1]</sup></th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>If the {{cssxref("border-color")}} property is not set, some WebKit based browsers will apply the {{cssxref("color")}} property to the border as well as the font on <code>{{htmlelement("textarea")}}</code>s.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>See the note about {{cssxref("line-height")}}</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td>See the note about Opera</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 supports this property only on <code>{{htmlelement("textarea")}}</code>s, whereas Opera only supports it on single line text fields.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields. On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>WebKit browsers (mostly on Mac OSX and iOS) use the native look & feel for the search fields. Therefore, it's required to use <code>-webkit-appearance:none</code> to be able to apply this property to search fields. On Windows 7, Internet Explorer 9 does not apply the border unless <code>background:none</code> is applied.</li> + <li>On Opera the {{cssxref("border-radius")}} property is applied only if an explicit border is set.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Buttons">Buttons</h3> + +<p>See the <code>{{htmlelement("input/button", "button")}}</code>, <code>{{htmlelement("input/submit", "submit")}}</code>, and <code>{{htmlelement("input/reset", "reset")}}</code> input types and the <code>{{htmlelement("button")}}</code> element.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>This property is not applied on WebKit based browsers on Mac OSX or iOS.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>This property is not applied on WebKit based browsers on Mac OSX or iOS.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>See the note about {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td> + <ol> + <li>On Opera the {{cssxref("border-radius")}} property is applied only if an explicit border is set.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Number">Number</h3> + +<p>See the <code>{{htmlelement("input/number", "number")}}</code> input type. There is no standard way to change the style of spinners used to change the value of the field, with the spinners on Safari being outside the field.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>On Opera, the spinners are zoomed in, which can hide the content of the field.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>On Opera, the spinners are zoomed in, which can hide the content of the field.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>See the note about {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td colspan="1" rowspan="3"> + <p>Supported but there is too much inconsistency between browsers to be reliable.</p> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + </tr> + </tbody> +</table> + +<h3 id="Check_boxes_and_radio_buttons">Check boxes and radio buttons</h3> + +<p>See the <code>{{htmlelement("input/checkbox", "checkbox")}}</code> and <code>{{htmlelement("input/radio", "radio")}}</code> input types.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Some browsers add extra margins and others stretch the widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Some browsers add extra margins and others stretch the widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Select_boxes_single_line">Select boxes (single line)</h3> + +<p>See the <code>{{htmlelement("select")}}</code>, <code>{{htmlelement("optgroup")}}</code> and <code>{{htmlelement("option")}}</code> elements.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>This property is okay on the <code>{{htmlelement("select")}}</code> element, but it cannot be the case on the <code>{{htmlelement("option")}}</code> or <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[2]</sup></td> + <td> + <ol> + <li>The property is applied, but in an inconsistent way between browsers on Mac OSX.</li> + <li>The property is well applied on the <code>{{htmlelement("select")}}</code> element, but is inconsistently handled on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>On Mac OSX, WebKit based browsers do not support this property on native widgets and they, along with Opera, do not support it at all on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>On Mac OSX, WebKit based browsers do not support this property on native widgets and they, along with Opera, do not support it at all on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property on <code>{{htmlelement("select")}}</code>, <code>{{htmlelement("option")}}</code>, and <code>{{htmlelement("optgroup")}}</code> elements; WebKit based browsers on Mac OSX do not support this property on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 on Windows 7 and WebKit based browsers on Mac OSX do not support this property on this widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Only Firefox provides full support for this property. Opera does not support this property at all and other browsers only support it on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1][2]</sup></td> + <td> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<p>Note Firefox does not provide any way to change the down arrow on the <code>{{htmlelement("select")}}</code> element.</p> + +<h3 id="Select_boxes_multiline">Select boxes (multiline)</h3> + +<p>See the <code>{{htmlelement("select")}}</code>, <code>{{htmlelement("optgroup")}}</code> and <code>{{htmlelement("option")}}</code> elements and the <a href="/en-US/docs/Web/HTML/Attributes/size"><code>size</code> attribute</a>.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Opera does not support {{cssxref("padding-top")}} and {{cssxref("padding-bottom")}} on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td>See the note about {{cssxref("line-height")}}.</td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property on <code>{{htmlelement("select")}}</code>, <code>{{htmlelement("option")}}</code>, and <code>{{htmlelement("optgroup")}}</code> elements; WebKit based browsers on Mac OSX do not support this property on <code>{{htmlelement("option")}}</code> and <code>{{htmlelement("optgroup")}}</code> elements.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 on Windows 7 and WebKit based browser on Mac OSX do not support this property on this widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Only supported by Firefox and IE9+.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Most of the browsers only support this property on the <code>{{htmlelement("select")}}</code> element.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes<sup>[1]</sup></td> + <td> + <ol> + <li>On Opera the {{cssxref("border-radius")}} property is applied only if an explicit border is set.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Datalist">Datalist</h3> + +<p>See the <code>{{htmlelement("datalist")}}</code> and <code>{{htmlelement("input")}}</code> elements and the <a href="/en-US/docs/Web/HTML/Attributes/list"><code>list</code> attribute</a>.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="File_picker">File picker</h3> + +<p>See the <code>{{htmlelement("input/file", "file")}}</code> input type.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Many browsers apply this property to the select button.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>It acts more or less like an extra left margin outside the widget.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h3 id="Date_pickers">Date pickers</h3> + +<p>See the <code>{{htmlelement("input/date", "date")}}</code> and <code>{{htmlelement("input/time", "time")}}</code> input types. Many properties are supported, but there is too much inconstency between browsers to be reliable.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td></td> + </tr> + </tbody> +</table> + +<h3 id="Color_pickers">Color pickers</h3> + +<p>See the <code>{{htmlelement("input/color", "color")}}</code> input type:</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>Opera handles this like a select widget with the same restriction.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>Opera handles this like a select widget with the same restriction.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Meters_and_progress">Meters and progress</h3> + +<p>See the <code>{{htmlelement("meter")}}</code> and <code>{{htmlelement("progress")}}</code> elements:</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Chrome hides the <code>{{htmlelement("progress")}}</code> and <code>{{htmlelement("meter")}}</code> element when the {{cssxref("padding")}} property is applied on a tweaked element.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Range">Range</h3> + +<p>See the <code>{{htmlelement("input/range", "range")}}</code> input type. There is no standard way to change the style of the range grip and Opera has no way to tweak the default rendering of the range widget.</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td> + <ol> + <li>Chrome and Opera add some extra space around the widget, whereas Opera on Windows 7 stretches the range grip.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td> + <ol> + <li>The {{cssxref("padding")}} is applied, but has no visual effect.</li> + </ol> + </td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td colspan="1" rowspan="3"> + <ol> + <li>Supported, but there is too much inconsistency between browsers to be reliable.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 153, 153); vertical-align: top;">No<sup>[1]</sup></td> + </tr> + </tbody> +</table> + +<h3 id="Image_buttons">Image buttons</h3> + +<p>See the <code>{{htmlelement("input/image", "image")}}</code> input type:</p> + +<table> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col" style="text-align: center;">N</th> + <th scope="col" style="text-align: center;">T</th> + <th scope="col">Note</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="4" scope="col"><em>CSS box model</em></th> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("width")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("height")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("border")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("margin")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + <tr> + <th scope="row" style="vertical-align: top;">{{cssxref("padding")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Text and font</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("color")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("font")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("letter-spacing")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-align")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-decoration")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-indent")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-overflow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-shadow")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("text-transform")}}</th> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td style="text-align: center; vertical-align: top;">N.A.</td> + <td></td> + </tr> + </tbody> + <tbody> + <tr> + <th colspan="4" scope="col"><em>Border and background</em></th> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("background")}}</th> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td style="text-align: center; background-color: rgb(204, 255, 102); vertical-align: top;">Yes</td> + <td colspan="1"></td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("border-radius")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1"> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + <tr> + <th scope="row" style="white-space: nowrap; vertical-align: top;">{{cssxref("box-shadow")}}</th> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td style="text-align: center; background-color: rgb(255, 255, 102); vertical-align: top;">Partial<sup>[1]</sup></td> + <td colspan="1"> + <ol> + <li>IE9 does not support this property.</li> + </ol> + </td> + </tr> + </tbody> +</table> + +<h2 id="See_also">See also</h2> + +<h3 id="Learning_path">Learning path</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Your first HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">How to structure an HTML form</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">The native form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML5_input_types">HTML5 input types</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Additional_form_controls">Additional form controls</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/UI_pseudo-classes">UI pseudo-classes</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Styling HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Form data validation</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> +</ul> + +<h3 id="Advanced_Topics">Advanced Topics</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">How to build custom form widgets</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">HTML forms in legacy browsers</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> diff --git a/files/es/learn/html/forms/prueba_tus_habilidades_colon__controles_html5/index.html b/files/es/learn/html/forms/prueba_tus_habilidades_colon__controles_html5/index.html new file mode 100644 index 0000000000..b73c8d4442 --- /dev/null +++ b/files/es/learn/html/forms/prueba_tus_habilidades_colon__controles_html5/index.html @@ -0,0 +1,75 @@ +--- +title: 'Prueba tus habilidades: controles HTML5' +slug: 'Learn/HTML/Forms/Prueba_tus_habilidades:_controles_HTML5' +tags: + - Aprendizaje + - Evaluación + - Formulário + - HTML5 + - Principiante +translation_of: 'Learn/Forms/Test_your_skills:_HTML5_controls' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta prueba es evaluar si has comprendido nuestro artículo <a href="/en-US/docs/Learn/Forms/HTML5_input_types">The HTML5 input types</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes intentar resolver esta prueba en los editores interactivos más abajo, sin embargo, puede ser útil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a> para trabajar en las tareas.<br> + <br> + Si te atascas, pide ayuda — mira la sección <a href="https://wiki.developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML/Prueba_tus_habilidades:_Enlaces#Evaluaci%C3%B3n_o_ayuda_adicional">Evaluación o ayuda adicional</a> al final de esta página.</p> +</div> + +<h2 id="Controles_HTML5_1">Controles HTML5 1</h2> + +<p>Primero exploraremos algunos de los tipos nuevos de <code>input</code> en HTML5. Crea las etiquetas <code>input</code> apropiadas para que un usuario actualice sus detalles para:</p> + +<ol> + <li>Email</li> + <li>Website</li> + <li>Número de teléfono</li> + <li>Color favorito</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para retrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/html5-controls/html5-controls1.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="/en-US/docshttps://github.com/mdn/learning-area/blob/master/html/forms/tasks/html5-controls/html5-controls1-download.html">Descarga el código inicial de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Controles_HTML5_2">Controles HTML5 2</h2> + +<p>A continuación, queremos que implementes un control deslizante para permitir al usuario escoger el número máximo de personas para invitar a su fiesta.</p> + +<ol> + <li>Implemente un control deslizante básico que acompañe a la etiqueta provista.</li> + <li>Establezca un valor minimo de 1, uno máximo de 30 y un valor inicial de 10.</li> + <li>Crea un elemento de salida correspondiente para poner el valor actual del deslizador. Asígnale la clase invite-output, y asocialo semanticamente con le entrada. Si haces esto correctamente, el JavaScript incluido en la página automáticamente actualizará el valor cuando se deslice el control.</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para retrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/html5-controls/html5-controls2.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/forms/tasks/html5-controls/html5-controls2-download.html">Descarga el código inicial de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Puedes practicar estos ejemplos en los editores interactivos que se encuentran más arriba.</p> + +<p>Si deseas que tu trabajo sea evaluado, o estás atorado y quieres solicitar ayuda:</p> + +<ol> + <li>Pon tu trabajo en un editor en línea con capacidad de compartir como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a>. Puedes escribir el código por ti mismo, o usar los archivos de punto de inicio enlazados en las secciones superiores.</li> + <li>Escribe una publicación solicitando evaluacion y/o ayuda en el <a href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Tu publicación debería incluir: + <ul> + <li>Un título descriptivo como "Solicito evaluacion para la prueba de habilidad de controles HTML5 1".</li> + <li>Detalles de lo que ya has intentado, y que te gustaría que hiciéramos, por ejemplo, si estas atascado y necesitas ayuda, o quieres una evaluación.</li> + <li>Un enlace al ejemplo que quieres que sea evaluado o por el que necesitas ayuda en un editor en linea con capacidad de compartir (como se mencionó en el paso 1 más arriba). Esta es una buena práctica - Es muy dificil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la tarea o página de evaluacion actual, para que podamos encontrar la pregunta con la cual necesitas ayuda.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/html/forms/prueba_tus_habilidades_colon__otros_controles/index.html b/files/es/learn/html/forms/prueba_tus_habilidades_colon__otros_controles/index.html new file mode 100644 index 0000000000..1496025a8d --- /dev/null +++ b/files/es/learn/html/forms/prueba_tus_habilidades_colon__otros_controles/index.html @@ -0,0 +1,87 @@ +--- +title: 'Prueba tus habilidades: Otros controles' +slug: 'Learn/HTML/Forms/Prueba_tus_habilidades:_Otros_controles' +translation_of: 'Learn/Forms/Test_your_skills:_Other_controls' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta pueba de habilidad es evaluar si has comprendido nuestro artículo <a href="/en-US/docs/Learn/Forms/Other_form_controls">Otros controles de formulario</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes intentar resolver esta prueba en los editores interactivos más abajo, sin embargo, puede ser útil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a> para trabajar en las tareas.<br> + <br> + Si te atascas, pide ayuda — mira la sección <a href="https://wiki.developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML/Prueba_tus_habilidades:_Enlaces#Evaluaci%C3%B3n_o_ayuda_adicional">Evaluación o ayuda adicional</a> al final de esta página.</p> +</div> + +<h2 id="Otros_controles_1">Otros controles 1</h2> + +<p>En nuestra primera evaluación de "Otros controles", te pediremos crear una entrada de texto de líneas múltiples.</p> + +<ol> + <li>Crea una entrada básica de texto de múltiples líneas.</li> + <li>Asócialo semánticamente con la etiqueta de "Comentario" asociado.</li> + <li>Define la entrada con 35 columnas y 10 filas de espacio en cual agregar comentarios.</li> + <li>Define para los comentatios una longitud máxima de 100 caracteres.</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/other-controls/other-controls1.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/forms/tasks/other-controls/other-controls1-download.html" rel="noopener">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Otros_controles_2">Otros controles 2</h2> + +<p>Ahora es tiempo de implementar un menú desplegable, para permitir al usuario escoger su comida favorita de las opciones entregadas.</p> + +<ol> + <li>Crea tu estructura de caja básica.</li> + <li>Asóciala semánticamente con la etiqueta de "comentarios" entregada.</li> + <li>Dentro de la lista, divide las opciones en 2 subgrupos - "principales" y "meriendas".</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/other-controls/other-controls2.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/forms/tasks/other-controls/other-controls2-download.html" rel="noopener">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Otros_controles_3">Otros controles 3</h2> + +<p>En la tarea final de esta evaluación, comenzaremos con la misma lista de opciones de comida. Sin embargo, esta vez queremos hacer las cosas de otra forma:</p> + +<ol> + <li>Crea una entrada de texto básica, que esté asociada semánticamente con la etiqueta entregada.</li> + <li>Coloca las opciones de comida en una lista que pueda ser asociada con una entrada de formulario.</li> + <li>Asocia la lista con tu entrada de texto, de forma que cuando escribas caracteres, cualquier opción de la lista que coincida con la secuencia de caracteres ingresada, aparezca en un listado desplegable como sugerencia de autocompletado.</li> +</ol> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/tasks/other-controls/other-controls3.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/forms/tasks/other-controls/other-controls3-download.html" rel="noopener">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Puedes practicar estos ejemplos en los editores interactivos que se encuentran más arriba.</p> + +<p>Si deseas que tu trabajo sea evaluado, o estás atorado y quieres solicitar ayuda:</p> + +<ol> + <li>Pon tu trabajo en un editor en línea con capacidad de compartir como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a>. Puedes escribir el código por ti mismo, o usar los archivos de punto de inicio enlazados en las secciones superiores.</li> + <li>Escribe una publicación solicitando evaluacion y/o ayuda en el <a href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Tu publicación debería incluir: + <ul> + <li>Un título descriptivo como "Solicito evaluacion para la prueba de habilidad de Otros controles 1".</li> + <li>Detalles de lo que ya has intentado, y que te gustaría que hiciéramos, por ejemplo, si estas atascado y necesitas ayuda, o quieres una evaluación.</li> + <li>Un enlace al ejemplo que quieres que sea evaluado o por el que necesitas ayuda en un editor en linea con capacidad de compartir (como se mencionó en el paso 1 más arriba). Esta es una buena práctica - Es muy dificil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la tarea o página de evaluacion actual, para que podamos encontrar la pregunta con la cual necesitas ayuda.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/html/forms/sending_and_retrieving_form_data/index.html b/files/es/learn/html/forms/sending_and_retrieving_form_data/index.html new file mode 100644 index 0000000000..d6ca2161a4 --- /dev/null +++ b/files/es/learn/html/forms/sending_and_retrieving_form_data/index.html @@ -0,0 +1,328 @@ +--- +title: Sending form data +slug: Learn/HTML/Forms/Sending_and_retrieving_form_data +translation_of: Learn/Forms/Sending_and_retrieving_form_data +--- +<div>{{LearnSidebar}} {{PreviousMenuNext("Aprende / HTML / Formularios / The_native_form_widgets", "Aprender / html / Formularios / Form_validation", "Aprender / html / Forms")}}</div> + +<p class="summary">En este artículo se analiza lo que sucede cuando un usuario envía un formulario - ¿A dónde van los datos y cómo los manejamos cuando llegan allí? - También tenemos en cuenta algunos de los problemas de seguridad asociados con el envío de los datos del formulario.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Conocimientos básicos de informática, una <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">comprensión de HTML</a> , y conocimientos básicos de <a href="/en-US/docs/Web/HTTP/Basics_of_HTTP">HTTP</a> y <a href="/en-US/docs/Learn/Server-side/First_steps">programación del lado del servidor</a> .</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para entender lo que sucede cuando se envía los datos del formulario, incluyendo la obtención de una idea básica de cómo se procesan los datos en el servidor</td> + </tr> + </tbody> +</table> + +<h2 id="¿A_dónde_van_los_datos">¿A dónde van los datos?</h2> + +<p>Aquí vamos a discutir lo que ocurre con los datos cuando se envía un formulario.</p> + +<h3 id="Sobre_la_arquitectura_cliente_servidor">Sobre la arquitectura cliente / servidor</h3> + +<p>La web se basa en una arquitectura cliente / servidor muy básica que se puede resumir de la siguiente manera: un cliente (normalmente un navegador Web) envía una petición a un servidor (la mayoría de las veces un servidor web como <a href="http://httpd.apache.org/" rel="external" title="http://www.apache.org/">Apache</a> , <a href="http://nginx.com/" rel="external" title="http://nginx.com/">Nginx</a> , <a href="http://www.iis.net/" rel="external" title="http://www.iis.net/">IIS</a> , <a href="http://tomcat.apache.org/" rel="external" title="http://tomcat.apache.org/">Tomcat</a> , etc.), utilizando el <a href="/en-US/docs/HTTP" title="/en-US/docs/HTTP">protocolo HTTP</a> . El servidor responde a la solicitud utilizando el mismo protocolo.</p> + +<p><img alt="Un esquema básico de la arquitectura cliente Web / servidor" src="/files/4291/client-server.png" style="display: block; height: 141px; margin: 0px auto; width: 400px;"></p> + +<p>En el lado del cliente, un formulario HTML no es más que una manera fácil de usar conveniente para configurar una petición HTTP para enviar datos a un servidor. Esto permite al usuario para proporcionar información a ser entregada en la petición HTTP.</p> + +<div class="note"> +<p><strong>Nota</strong> : Para tener una mejor idea de cómo funcionan las arquitecturas cliente-servidor, lea nuestra <a href="/en-US/docs/Learn/Server-side/First_steps">programación de páginas web del lado del servidor, módulo: primeros pasos</a>. En el lado del cliente: Debes definir como envías los datos.</p> +</div> + +<p>El elemento {{HTMLElement ( "form")}} define cómo se enviarán los datos. Todos sus atributos están diseñados para que pueda configurar la solicitud que se enviará cuando un usuario pulsa un botón de envío. Los dos atributos más importantes son {{htmlattrxref ( "acción", "forma")}} y {{htmlattrxref ( "método", "forma")}}.</p> + +<h4 id="El_atributo_htmlattrxref_acción_forma.">El atributo {{htmlattrxref ( "acción", "forma")}}.</h4> + +<p>Este atributo define el lugar donde los datos se envian. Su valor debe ser una dirección URL válida. Si no se proporciona este atributo, los datos serán enviados a la dirección URL de la página que contiene el formulario.</p> + +<p>En este ejemplo, los datos se envían a una dirección URL absoluta - <code>http://foo.com</code>:</p> + +<pre class="brush: html"><Acción del formulario = "http://foo.com"></pre> + +<p class="brush: html">Aquí, nosotros usamos una URL relativa - los datos se envían a una dirección URL diferente en el servidor:</p> + +<pre class="brush: html"><Acción del formulario = "/ somewhere_else"></pre> + +<p class="brush: html">Cuando se especifica sin atributos, como abajo, el {{HTMLElement ( "form")}} los datos se envían a la misma página en que la "forma" está presente :</p> + +<pre class="brush: html"><Form></pre> + +<p class="brush: html">Muchas páginas más antiguas utilizan la siguiente notación para indicar que los datos deben ser enviados a la misma página que contiene el formulario; Esto fue necesario porque hasta HTML5, el atributo {{htmlattrxref ( "acción", "form")}} fue requerido . Esto ya no es necesario.</p> + +<pre class="brush: html"><Form action = "#"></pre> + +<div class="note"> +<p><strong>Nota:</strong> Es posible especificar una dirección URL que utiliza el protocolo HTTPS (HTTP seguro). Al hacer esto, los datos se cifran junto con el resto de la solicitud, incluso si el propio formulario está alojado en una página insegura se accede a través de HTTPS. Por otro lado, si el formulario está alojado en una página segura, pero se especifica una dirección URL HTTP insegura con el atributo {{htmlattrxref ( "acción", "form")}} , todos los navegadores mostrarán una advertencia de seguridad para el usuario cada vez que intenten enviar datos, ya que estos no se pueden cifrar.</p> +</div> + +<h4 id="El_atributo_htmlattrxref_método_form">El atributo {{htmlattrxref ( "método", "form")}}</h4> + +<p>Este atributo define cómo se envían los datos. El <a href="/en-US/docs/HTTP" title="/en-US/docs/HTTP">protocolo HTTP</a> proporciona varias formas de realizar una solicitud; Los datos del formulario HTML se pueden transmitir a través de un número de diferentes queridos, los más comunes de los cuales son el método <code>GET</code> y el método <code>POST</code>.</p> + +<p>Para entender la diferencia entre estos dos métodos, vamos a dar un paso atrás y examinar cómo funciona HTTP. Cada vez que desee llegar a un recurso en la Web, el navegador envía una petición a una URL. Una petición HTTP consta de dos partes: un encabezado que contiene un conjunto de metadatos mundial sobre las capacidades del navegador, y un cuerpo que puede contener la información necesaria paraque el servidor pueda procesar la petición específica.</p> + +<h5 id="El_método_GET">El método GET</h5> + +<p>El método <code>GET</code> es utilizado por el navegador para pedir al servidor que se envíe de vuelta un recurso dado: "Hey servidor, quiero conseguir este recurso." En este caso, el navegador envía un cuerpo vacío. Debido a que el cuerpo está vacío, si un formulario se envía utilizando este método, los datos enviados al servidor se anexan a la URL.</p> + +<p>Considere la siguiente forma:</p> + +<pre class="brush: html"><form action="http://foo.com" method="get"> + <div> + <label for="decir"> ¿Qué saludo quiere decir? </label> + <input name="decir" id="decir" value="Hola"> + </div> + <div> + <label for="para"> ¿A quién se lo quiere decir? </label> + <input name="para" value="mamá"> + </div> + <div> + <button> Botón enviar mis saludos </ button> + </div> +</form></pre> + +<p>Dado que el método <code>GET</code>ha conseguido el recurso, verá en la URL lo siguiente en la barra de direcciones del navegador <code>www.foo.com/?say=Hi&to=Mom</code> cuando se envía el formulario.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14685/url-parameters.png" style="display: block; margin: 0 auto;">Los datos se añaden a la URL como una serie de pares de nombre / valor. Después que la dirección web URL ha terminado, se incluye un signo de interrogación ( <code>?</code>) seguido de los pares de nombre / valor, cada uno separado por un signo ( <code>&</code>). En este caso estamos pasando dos piezas de datos en el servidor:</p> + +<ul> + <li><code>say</code>, Que tiene un valor de <code>Hi</code></li> + <li><code>to</code>, Que tiene un valor de <code>Mom</code></li> +</ul> + +<p>La solicitud HTTP se ve así:</p> + +<pre>GET /? = Decir Hola & a = mamá HTTP / 1.1 +Anfitrión: foo.com</pre> + +<div class="note"> +<p><strong>Nota</strong> : Puede encontrar este ejemplo en GitHub - ver <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/get-method.html">llegar-method.html</a> ( <a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/get-method.html">verlo en directo también</a> ).</p> +</div> + +<h5 id="El_método_POST">El método POST</h5> + +<p>El <code>POST</code>método es un poco diferente. Es el método que el navegador utiliza para comunicarse con el servidor cuando se pide una respuesta que tenga en cuenta los datos proporcionados en el cuerpo de la petición HTTP: "Hey servidor, echa un vistazo a estos datos y envíame de vuelta un resultado apropiado." Si un formulario se envía utilizando este método, los datos se anexan al cuerpo de la petición HTTP.</p> + +<p>Veamos un ejemplo - se trata de algo similar a como se vió en el método <code>GET</code>del apartado anterior, pero con el {{htmlattrxref ( "método", "form")}} atributo establecido <code>post</code>.</p> + +<pre class="brush: html"><Form action = "http://foo.com" method = "post"> + <Div> + <Label for = "dice"> Lo saludo qué quiere decir? </ Label> + <Input name = "decir" id = "decir" value = "Hola"> + </ Div> + <Div> + <Label for = "para"> ¿Quién usted quiere decir que a? </ Label> + <Input name = "a" value = "mamá"> + </ Div> + <Div> + <> Botón enviar mis saludos </ botón> + </ Div> +</ Form></pre> + +<p>Cuando el formulario se envía mediante el método <code>POST</code>, no se obtienen los datos adjuntos en la dirección URL, y la solicitud HTTP se parece a esto y los datos son incluidos en el cuerpo de la petición en su lugar:</p> + +<pre>POST / HTTP/1.1 +Anfitrión: foo.com +Content-Type: application / x-www-form-urlencoded +Content-Length: 13 + +decir = Hi & a = mamá</pre> + +<p>La cabecera <code>Content-Length</code> indica el tamaño del cuerpo, y la cabecera <code>Content-Type</code> indica el tipo de recurso que se envía al servidor. Discutiremos estas cabeceras más adelante.</p> + +<div class="note"> +<p><strong>Nota</strong> : Puede encontrar este ejemplo en GitHub - ver <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/post-method.html">post-method.html</a> ( <a href="https://mdn.github.io/learning-area/html/forms/sending-form-data/post-method.html">verlo en directo también</a> ).</p> +</div> + +<h4 id="Visualización_de_peticiones_HTTP">Visualización de peticiones HTTP</h4> + +<p>Las peticiones HTTP nunca se muestran al usuario (si quieres verlos, es necesario utilizar herramientas como el <a href="/en-US/docs/Tools/Network_Monitor">Monitor de red Firefox</a> o las <a href="https://developers.google.com/chrome-developer-tools/" title="https://developers.google.com/chrome-developer-tools/">herramientas de desarrollo de Chrome</a> ). A modo de ejemplo, los datos del formulario se muestran a continuación en la pestaña de Chrome red:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14691/network-monitor.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Lo único que se muestra al usuario es la dirección URL llamada. Como mencionamos anteriormente, con una petición<code>GET</code> del usuario,se verán los datos en su barra de direcciones, pero con una petición <code>POST</code> no será de esta manera. Esto puede ser muy importante por dos razones:</p> + +<ol> + <li>Si necesita enviar una contraseña (o cualquier otra pieza sensible de los datos), nunca utilice el método<code>GET</code> o se arriesga a mostrar en la barra de direcciones, lo que sería muy inseguro.</li> + <li>Si necesita enviar una gran cantidad de datos, el método <code>POSt</code> es preferible debido a que algunos navegadores limitan los tamaños de las direcciones URL. Además, muchos servidores limitan la longitud de las URL que aceptan.</li> +</ol> + +<h3 id="En_el_lado_Servidor_la_recuperación_de_los_datos">En el lado Servidor: la recuperación de los datos</h3> + +<p>Sea cual sea el método HTTP que elija, el servidor recibe una cadena que será analizada con el fin de obtener los datos como una lista de pares clave / valor. La forma de acceder a esta lista depende de la plataforma de desarrollo que use y de las estructuras específicas que pueda estar usando con él. La tecnología se utiliza también determina cómo se manejan claves duplicadas; A menudo,se da prioridad al valor recibido más recientemente para una clave dada .</p> + +<h4 id="Ejemplo_PHP_Raw">Ejemplo: PHP Raw</h4> + +<p><a href="http://php.net/">PHP</a> ofrece algunos objetos globales para acceder a los datos. Suponiendo que usted ha utilizado el método<code>POST</code>, el siguiente ejemplo sólo toma los datos y lo muestra al usuario. Por supuesto, lo que se hace con los datos depende de usted. Es posible visualizarlos, almacenarlos en una base de datos, enviarlos por correo electrónico, o procesarlos de alguna otra manera.</p> + +<pre class="brush: php"><? Php + // La variable global $ _POST que permite acceder a los datos enviados con el método POST por su nombre + // Para acceder a los datos enviados con el método GET, puede usar $ _GET + $ = Decir htmlspecialchars ($ _POST [ 'decir']); + $ A = htmlspecialchars ($ _POST [ 'a']); + + echo $ digamos, '', $ a; +?></pre> + +<p>Este ejemplo muestra una página con los datos que enviamos. Esto se puede ver en acción en nuestro archivo ejemplo <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/php-example.html">php-example.html</a> - que contiene un ejemplo similar en forma como el que hemos visto antes, con un <code>method</code>con parámetro <code>post</code>y un <code>action</code> con parámetro <code>php-example.php</code> Cuando se envía, envía los datos del formulario al script <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/php-example.php">php-ejemplo.php</a> , que contiene el código de PHP que se ha visto en el bloque anterior. Cuando se ejecuta este código, la salida en el navegador es <code>Hi Mom</code>.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14693/php-result.png" style="display: block; margin: 0 auto;"></p> + +<div class="note"> +<p><strong>Nota</strong> : Este ejemplo no funcionará cuando se carga en un navegador localmente - los navegadores no pueden interpretar código PHP, por lo que cuando se envía el formulario en el navegador sólo se puede ofrecer la descarga del archivo PHP para usted. Para conseguir que funcione, es necesario ejecutar el ejemplo a través de un servidor PHP de algún tipo. Buenas opciones para probar PHP locales son <a href="https://www.mamp.info/en/downloads/">MAMP</a> (Mac y Windows) y <a href="http://ampps.com/download">AMPPS</a> (Mac, Windows, Linux).</p> +</div> + +<h4 id="Ejemplo_Python">Ejemplo: Python</h4> + +<p>Este ejemplo muestra como se puede utilizar Python para hacer la misma cosa - mostrar los datos presentados en una página web. Se utiliza el <a href="http://flask.pocoo.org/">framework Flask</a> para la prestación de las plantillas, el manejo de la presentación de datos de formulario, etc (ver <a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/python-example.py">python-example.py</a> ).</p> + +<pre class="line-numbers language-html"><code class="language-html">from flask import Flask, render_template, request +app = Flask(__name__) + +@app.route('/', methods=['GET', 'POST']) +def form(): + return render_template('form.html') + +@app.route('/hello', methods=['GET', 'POST']) +def hello(): + return render_template('greeting.html', say=request.form['say'], to=request.form['to']) + +if __name__ == "__main__": + app.run()</code></pre> + +<p>Las dos plantillas de referencia en el código anterior son los siguientes:</p> + +<ul> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/templates/form.html">form.html</a> : La misma forma que hemos visto anteriormente en la {{anch ( "El método POST")}} sección, pero con el <code>action</code>conjunto a <code>\{{ url_for('hello') }}</code>. (Esta es una <a href="http://jinja.pocoo.org/docs/2.9/">Jinja2</a> plantilla, que es básicamente HTML, pero puede contener llamadas al código Python que ejecuta el servidor web que figura entre corchetes. <code>url_for('hello')</code>Básicamente está diciendo "redirigir a <code>/hello</code>cuando se envía el formulario").</li> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/forms/sending-form-data/templates/greeting.html">greeting.html</a> :<span id="result_box" lang="es"><span>Esta plantilla solo contiene una línea que representa los dos bits de datos que se le pasan cuando se procesa</span></span>. Esto se hace a través de la función <code>hello()</code>que se ha visto anteriormente, y que se ejecuta cuando la URL<code>/hello</code> es accedida.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong> : Una vez más, este código no funcionará si sólo intenta cargarlo en un navegador directamente. Python funciona un poco diferente a PHP - Para ejecutar este código local que necesita para <a href="/en-US/docs/Learn/Server-side/Django/development_environment#Installing_Python_3">instalar Python / PIP</a> , a continuación, instalar el frasco utilizando <code>pip3 install flask</code>. En este punto, usted debe ser capaz de ejecutar el ejemplo utilizando <code>python3 python-example.py</code>, a continuación, deberá navegar a <code>localhost:5000</code>en su barra de direcciones.</p> +</div> + +<h4 id="Otros_lenguajes_y_frameworks">Otros lenguajes y frameworks</h4> + +<p>Hay muchas otras tecnologías del lado del servidor que puede utilizar para el manejo de formularios, incluyendo <a href="/en-US/docs/" title="/en-US/docs/">Perl</a> , <a href="/en-US/docs/" title="/en-US/docs/">Java</a> , <a href="http://www.microsoft.com/net" title="http://www.microsoft.com/net">.Net</a> , <a href="/en-US/docs/" title="/en-US/docs/">Rubí</a> , etc. Sólo tiene que elegir el que más le guste. Dicho esto, vale la pena señalar que es muy raro de usar estas tecnologías directamente porque esto puede ser complicado. Es más común el uso de uno de los muchos marcos de trabajo para un manejo más fácil del código, tales como:</p> + +<ul> + <li><a href="http://symfony.com/" rel="external" title="http://symfony.com/">Symfony</a> para PHP</li> + <li><a href="/en-US/docs/Learn/Server-side/Django" rel="external" title="https://www.djangoproject.com/">Django</a> para Python (un poco más pesado que el <a href="http://flask.pocoo.org/">frasco</a> , pero con más herramientas y opciones).</li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs">Express</a> de Node.js</li> + <li><a href="http://rubyonrails.org/" rel="external" title="http://rubyonrails.org/">Ruby on Rails</a> Ruby</li> + <li><a href="http://grails.org/" rel="external" title="http://grails.org/">Grails</a> para Java</li> + <li>etc.</li> +</ul> + +<p>Vale la pena señalar que incluso el uso de estos marcos, trabajar con formularios no es necesariamente <em>fácil</em> . Pero es mucho más fácil que tratar de escribir toda la funcionalidad a partir de cero, además, le ahorrará mucho tiempo.</p> + +<div class="note"> +<p><strong>Nota</strong> : Está más allá del alcance de este artículo para enseñarle cualquier lenguaje del lado del servidor o marcos de trabajo. Los enlaces de arriba le dará un poco de ayuda,en caso de que desee aprender.</p> +</div> + +<h2 id="Un_caso_especial_el_envío_de_archivos">Un caso especial: el envío de archivos</h2> + +<p>El envío de archivos con formularios HTML es un caso especial. Los archivos son datos binarios - o considerados como tal - mientras que todos los demás datos son datos de texto. Debido a que HTTP es un protocolo de texto, existen requisitos especiales para el manejo de datos binarios.</p> + +<h3 id="El_htmlattrxref_enctype_form_atributo">El {{htmlattrxref ( "enctype", "form")}} atributo</h3> + +<p>Este atributo le permite especificar el valor de la cabecera <code>Content-Type</code> HTTP incluido en la solicitud que se genera cuando se envía el formulario. Esta cabecera es muy importante porque le dice al servidor qué tipo de datos se está enviando. Por defecto, su valor es <code>application/x-www-form-urlencoded</code>. En términos humanos, esto significa: "<span class="short_text" id="result_box" lang="es"><span>Estos son datos de formulario que han sido codificados dentro de los parámetros de la URL</span></span>."</p> + +<p>Si desea enviar archivos, es necesario tomar tres pasos adicionales:</p> + +<ul> + <li>Ajuste el {{htmlattrxref ( "método", "form")}} atributo <code>POST</code>porque el contenido del archivo no se puede poner dentro de los parámetros de URL.</li> + <li>Establecer el valor de {{htmlattrxref ( "enctype", "form")}} que <code>multipart/form-data</code>debido a que los datos se dividen en múltiples partes, una para cada archivo más uno para los datos de texto incluidos en el cuerpo del formulario (si también se introduce el texto en la formulario).</li> + <li>Incluir uno o más widgets <a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets#File_picker">selector de archivos</a> para permitir a los usuarios seleccionar el archivo (s) que será subido.</li> +</ul> + +<p>Por ejemplo:</p> + +<pre class="brush: html"><Form method = "post" enctype = "multipart / form-data"> + <Div> + <Label for = "archivo"> Elija un archivo </ label> + <Input type = "file" id = "file" name = "myFile"> + </ Div> + <Div> + <> Botón Enviar el archivo </ botón> + </ Div> +</ Form></pre> + +<div class="note"> +<p><strong>Nota:</strong> Algunos navegadores son compatibles con la {{htmlattrxref ( "múltiple", "input")}} atributo en el elemento {{HTMLElement ( "input")}}, lo que permite elegir más de un archivo para subir con un único elemento <code><input></code> . Cómo el servidor gestiona los archivos realmente depende de la tecnología utilizada en el servidor. Como se mencionó anteriormente, el uso de un marco le hará la vida mucho más fácil.</p> +</div> + +<div class="warning"> +<p><strong>Advertencia:</strong> Muchos servidores están configurados con un límite de tamaño para los archivos y las peticiones HTTP con el fin de prevenir el abuso. Es importante comprobar este límite con el administrador del servidor antes de enviar un archivo.</p> +</div> + +<h2 id="Precauciones_de_seguridad_comunes">Precauciones de seguridad comunes</h2> + +<p>Cada vez que envíe datos a un servidor, debe tener en cuenta la seguridad de sus formularios HTML que son con mucho, los vectores de ataque más comunes (en lugares donde ocurren los ataques contra servidores). Los problemas nunca vienen de los formulariosHTML mismos - sino que proceden de cómo el servidor maneja los datos.</p> + +<p><span id="result_box" lang="es"><span>Dependiendo de lo que estés haciendo, hay algunos problemas de seguridad muy conocidos con los que te enfrentarás</span></span>:</p> + +<h3 id="XSS_y_CSRF">XSS y CSRF</h3> + +<p>Cross-Site Scripting (XSS) y Cross-Site Request Falsification (CSRF) son tipos comunes de ataques que se producen cuando se muestran los datos enviados por un usuario y que son devueltos a otro usuario para otro uso.</p> + +<p>XSS permite a los atacantes inyectar secuencias de comandos del lado del cliente en páginas Web visitadas por otros usuarios. Una vulnerabilidad de secuencias de comandos entre sitios, puede ser utilizada por los atacantes para eludir los controles de acceso, como la <a href="/en-US/docs/JavaScript/Same_origin_policy_for_JavaScript" title="/ Es-ES / docs / JavaScript / Same_origin_policy_for_JavaScript">política del mismo origen</a> . El efecto de estos ataques pueden ir desde una pequeña molestia a un riesgo de seguridad.</p> + +<p>Los ataques CSRF son similares a los ataques XSS porque comienzan de la misma manera - mediante la inyección de comandos de cliente en páginas Web - pero su objetivo es diferente. Los atacantes CSRF tratan de escalar privilegios de un usuario de mayores privilegios (por ejemplo, un administrador de sitio) para realizar una acción que no deberían ser capaces de hacer (por ejemplo, el envío de datos a un usuario no fiable).</p> + +<p>Los ataques XSS explotan la confianza depositada a un usuario de un sitio web, mientras que los ataques CSRF abusan de la confianza que un sitio web ofrece para sus usuarios.</p> + +<p>Para evitar estos ataques, siempre se deben comprobar los datos que un usuario envía a su servidor y (si es necesario mostrarlos) <span id="result_box" lang="es"><span>trate de no mostrar el contenido HTML provisto por el usuario</span></span>. En su lugar, se deben procesar los datos proporcionados por el usuario para no mostrarlos al pie de la letra. <span style="line-height: 1.5;">Casi todos los marcos de trabajo (<strong>frameworks</strong>) en el mercado hoy implementan un filtro mínimo que eliminan el código HTML {{HTMLElement ( "script")}}, {{HTMLElement ( "iframe")}} y {{HTMLElement ( "objeto")}} si fuesen enviados por cualquier usuario. Esto ayuda a mitigar el riesgo, pero no necesariamente lo erradica.</span></p> + +<h3 id="Inyección_SQL">Inyección SQL</h3> + +<p>La inyección de SQL es un tipo de ataque que intenta realizar acciones en una base de datos utilizada por el sitio web de destino. Esto normalmente implica el envío de una petición SQL con la esperanza de que el servidor la ejecutará (por lo general cuando el servidor de aplicaciones intenta almacenar los datos enviados por un usuario). Esto es en realidad <a href="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project" rel="external" title="https://www.owasp.org/index.php/Category:OWASP_Top_Ten_Project">uno de los principales vectores de ataque contra los sitios web </a> .</p> + +<p>Las consecuencias pueden ser terribles, que van desde la pérdida de datos o hasta que los ataques tomen el control de la infraestructura de todo el sitio web mediante el uso de una escalada de privilegios. Esta es una amenaza muy seria y nunca debe almacenar los datos enviados por un usuario sin realizar alguna sanitización (por ejemplo, mediante el uso <code><a href="http://www.php.net/manual/en/function.mysql-real-escape-string.php" rel="external" title="http://www.php.net/manual/en/function.mysql-real-escape-string.php">mysql_real_escape_string()</a></code>de una infraestructura de PHP / MySQL).</p> + +<h3 id="Inyección_de_cabecera_HTTP_y_la_inyección_de_correo_electrónico">Inyección de cabecera HTTP y la inyección de correo electrónico</h3> + +<p>Este tipo de ataques pueden ocurrir cuando su aplicación se basa cabeceras HTTP o mensajes de correo electrónico basado en la entrada de datos por un usuario en un formulario. Estos no dañan directamente su servidor o afectan a sus usuarios, pero son una puerta abierta a problemas más profundos tales como el secuestro de sesión o ataques de phishing.</p> + +<p>Estos ataques son en su mayoría en silencio, y pueden volver a su servidor en un <a href="http://en.wikipedia.org/wiki/Zombie_(computer_science)" rel="exernal" title="http://en.wikipedia.org/wiki/Zombie_(computer_science)">zombi</a> .</p> + +<h3 id="Sea_paranoico_Nunca_confíe_en_sus_usuarios">Sea paranoico: Nunca confíe en sus usuarios</h3> + +<p>Entonces, ¿cómo se lucha contra estas amenazas? Este es un tema mucho más allá de esta guía, pero hay algunas reglas a tener en cuenta. La regla más importante es: nunca vuelva a confiar en sus usuarios, incluyáse a sí mismo; incluso un usuario de confianza podría haber sido secuestrado.</p> + +<p>Todos los datos que vienen a su servidor deben comprobarse y ser desinfectados. Siempre. Sin excepción.</p> + +<ul> + <li>Escapar caracteres potencialmente peligrosos. Los caracteres específicos con los que debe tener cuidado variarán dependiendo del contexto en el que se utilizan los datos y la plataforma de servidores que emplean, pero todos los lenguajes del lado del servidor tienen funciones de este.</li> + <li>Limite la cantidad de entrada de datos para permitir sólo lo necesario.</li> + <li>Sandbox subido archivos (almacenarlos en un servidor diferente y permitir el acceso al archivo sólo a través de un subdominio diferente o incluso mejor a través de un nombre de dominio totalmente diferente).</li> +</ul> + +<p>Debería evitar muchos o la mayoría de estos problemas, si sigue estas tres reglas, pero siempre es una buena idea obtener una revisión de seguridad realizada por una tercera parte competente. No asuma que usted ha visto todos los posibles problemas.</p> + +<div class="note"> +<p><strong>Nota</strong> : La <a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">seguridad del sitio web</a> el artículo de nuestro <a href="/en-US/docs/Learn/Server-side">lado del servidor</a> tema de aprendizaje analiza las amenazas anteriores y las posibles soluciones con más detalle.</p> +</div> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Como se puede ver, el envío de los datos del formulario es fácil, pero asegurar una aplicación puede ser complicado. Sólo recuerde que un desarrollador de aplicaciones para usuario no es el que debe definir el modelo de seguridad de los datos. Sí, como veremos, es posible <a href="/en-US/docs/HTML/Forms/Data_form_validation" title="/ es-ES / docs / HTML / Formularios / Data_form_validation">realizar la validación de los datos del lado del cliente</a> , pero el servidor no puede confiar en esta validación porque no tiene manera de saber realmente lo que sucede en el lado del cliente.</p> + +<h2 id="Ver_también">Ver también</h2> + +<p>Si desea obtener más información sobre la seguridad de una aplicación web, se puede excavar en estos recursos:</p> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/First_steps">programación web del lado del servidor primeros pasos</a></li> + <li><a href="https://www.owasp.org/index.php/Main_Page" rel="external" title="https://www.owasp.org/index.php/Main_Page">El Proyecto Open Web Application Security (OWASP)</a></li> + <li><a href="http://shiflett.org/" rel="external" title="http://shiflett.org/">el blog de Chris Shiflett sobre Seguridad en PHP</a></li> +</ul> + +<p>{{PreviousMenuNext ( "Aprende / html / Formularios / The_native_form_widgets", "Saber / html / Formularios / Form_validation", "Aprender / html / Forms")}}</p> diff --git a/files/es/learn/html/forms/styling_html_forms/index.html b/files/es/learn/html/forms/styling_html_forms/index.html new file mode 100644 index 0000000000..26b4173ee8 --- /dev/null +++ b/files/es/learn/html/forms/styling_html_forms/index.html @@ -0,0 +1,345 @@ +--- +title: Estilizando formularios HTML +slug: Learn/HTML/Forms/Styling_HTML_forms +translation_of: Learn/Forms/Styling_web_forms +--- +<p>En este artículo aprenderemos como utilizar <a href="/es/docs/Web/CSS">CSS</a> con formularios <a href="/es/docs/Web/HTML">HTML</a> para hacerlos más atractivos. Aunque parezca extraño, esto es algo que puede llegar a ser complicado. Por razones históricas y técnicas, los widgets de formulario no suelen llevarse bien con CSS. Por este motivo, muchos desarrolladores prefieren <a href="https://developer.mozilla.org/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets">construir sus propios widgets</a> para tener el control de su aspecto en vez de utilizar los nativos. De todas formas, con los modernos navegadores, los diseñadores web <span style="line-height: 23.3333339691162px;">cada vez</span><span style="line-height: 1.5;"> tienen más control sobre el diseño de los elementos de formulario. Vamos a profundizar en esto.</span></p> + +<h2 id="¿Porqué_es_tan_difícil_aplicar_estilos_a_formularios_con_CSS">¿Porqué es tan difícil aplicar estilos a formularios con CSS?</h2> + +<p>En los principios de la Web —allá por1995—se añadieron los controles de formulario en la <a href="http://www.ietf.org/rfc/rfc1866.txt">2ª especificación HTML.</a> Debido a la complejidad de los widgets de formulario, los implementadores prefirieron dejar que el sistema operativo subyacente se encargara de su manejo y presentación.</p> + +<p>Pocos años después, se creó<span style="line-height: 23.3333339691162px;"> </span><span style="line-height: 1.5;">CSS y lo que era una necesidad técnica</span>— es decir, el uso de widgets nativos para implementar controles de formulario—empezó a requerir estilizado. Y en los primeros días de CSS, el estilizado de formularios no fué una prioridad.</p> + +<p>Por otra parte, como los usuarios estaban acostumbrados a la apariencia visual de sus plataformas respectivas, los fabricantes de navegadores fueron reacios a hacer que los controles de formularios pudieran recibir estilos.</p> + +<p>Hoy en día, ni siquiera uno solo de los navegadores actuales implementa <span style="line-height: 23.3333339691162px;">completamente</span><span style="line-height: 1.5;"> a CSS 2.1. Afortunadamente, con el tiempo, los fabricantes de navegadores han ido mejorado su soporte a CSS para los elementos de formulario e, incluso considerando que su usabilidad tiene mala reputación, actualmente, ya se puede usar CSS para estilizar </span><a href="https://developer.mozilla.org/en-US/docs/HTML/Forms" style="line-height: 1.5;">formularios HTML.</a></p> + +<h3 id="No_todos_los_widgets_se_crean_igual_con_CSS">No todos los widgets se crean igual con CSS</h3> + +<p>Actualmente aun se encuentran dificultades cuando se utiliza CSS con formularios; estos problemas se pueden dividir en tres categorías.</p> + +<h4 id="El_bueno">El bueno</h4> + +<p>A algunos elementos se les puede dar estilo con pocos o ningún problema independientemente de la plataforma. Entre estos se incluyen los siguientes elementos estructurales:</p> + +<ol> + <li>{{HTMLElement("form")}}</li> + <li>{{HTMLElement("fieldset")}}</li> + <li>{{HTMLElement("label")}}</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/output"><output></a></li> +</ol> + +<p style="line-height: 23.3333339691162px;">Esto también incluye todos los campos de texto (tanto los de línea simple como los de línea múltiple) y los botones.</p> + +<ol style="line-height: 23.3333339691162px;"> +</ol> + +<p style="line-height: 18px; font-size: 1.28571428571429rem;">El malo</p> + +<p>Hay otros elementos a los que raramente se les puede aplicar estilos y pueden llegar a requerir <span style="line-height: 23.3333339691162px;">técnicas</span><span style="line-height: 1.5;"> complejas y </span><span style="line-height: 1.5;">ocasionalmente necesitan conocimientos avanzados de CSS3.</span></p> + +<p>Entre estos se incluyen el elemento {{HTMLElement("legend")}} ; que no puede posicionarse adecuadamente en todas las plataformas. Los elementos checkbox y los botones de radio no permiten que se le apliquen estilos directamente; de todas formas, gracias a CSS3 esto puede soslayarse. Al contenido de <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#attr-placeholder">placeholder </a>no se le puede aplicar estilo de ninguna forma convencional; sin embargo, todos los navegadores que lo implementan también implementan pseudo-elementos<span style="line-height: 23.3333339691162px;"> o </span><span style="line-height: 1.5;">pseud</span><span style="line-height: 1.5;">o-clases propi</span>etarias que permiten darles estilo<span style="line-height: 1.5;">.</span></p> + +<p><span style="line-height: 1.5;">Veremos como trabajar con estos casos específicos en el artículo </span><a href="/en-US/docs/Advanced_styling_for_HTML_forms" style="line-height: 23.3333339691162px;" title="/en-US/docs/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a><span style="line-height: 23.3333339691162px;">.</span></p> + +<h4 id="El_feo">El feo</h4> + +<p>En algunos elementos, simplemente no se puede utilizar CSS. Estos son todos los elementos avanzados de interface de usuario tales como los controles range, color, o date, e igualmente pasa con los widgets desplegables como <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/select">select</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/option">option</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/optgroup">optgropup </a>y <a href="/es/docs/HTML/Elemento/datalist">datalist</a>. Respecto al selector de archivos, es bien sabido que no puede aplicarse estilo en absoluto. Los nuevos elementos <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/progress">progress </a>y <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/meter">meter </a>también caen dentro de esta categoría.</p> + +<p>El principal problema con todos estos widgets viene de que todos ellos tienen una estructura muy compleja y CSS no es lo suficientemente expresivo para estilizar cada una de sus sutiles partes. Si lo que se quiere es personalizar estos widgets se deberá recurrir a javaScript para construir un árbol DOM que te permita acceder a ellos. Para aprender como conseguirlo mirar en el artículo <a href="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets" style="line-height: 23.3333339691162px; text-decoration: underline;" title="/en-US/docs/HTML/Forms/How_to_build_custom_form_widgets"><span style="line-height: 23.3333339691162px;"><u>How to </u></span>build<span style="line-height: 23.3333339691162px;"><u> </u></span>custom<span style="line-height: 23.3333339691162px;"><u> </u></span>form<span style="line-height: 23.3333339691162px;"><u> </u></span>widgets</a>.</p> + +<h2 id="Estilizado_básico">Estilizado básico</h2> + +<p>Aplicar estilos a <a href="https://developer.mozilla.org/es/docs/Web/Guide/HTML/Forms/Styling_HTML_forms#El_bueno">elementos que son fáciles de estilizar</a> con CSS, no debería suponer ninguna dificultad ya que básicamente se comportan como cualquier otro elemento HTML. De todas formas, el agente de usuario de estilos para cada navegador puede mostrar pequeñas inconsistencias por lo que a continuación daremos algunos trucos para ayudar a aplicar estilos más cómodamente.</p> + +<h3 id="Campos_de_búsqueda">Campos de búsqueda</h3> + +<p>Las cajas de búsqueda son el único tipo de campo de texto que pueden ofrecer más dificultad al aplicar estilos. En los navegadores basados en webkit (Chrome, Safari, etc.) se debe lidiar con la propiedad -webkit-. Discutiremos esta propiedad más tarde en el artículo: <a href="/en-US/docs/Advanced_styling_for_HTML_forms" style="line-height: 23.3333339691162px; text-decoration: underline;" title="/en-US/docs/Advanced_styling_for_HTML_forms">Advanced styling for HTML forms</a><span style="line-height: 23.3333339691162px;">.</span></p> + +<h4 id="Ejemplo">Ejemplo</h4> + +<pre class="brush: html"><form> + <input type="search"> +</form> +</pre> + +<pre class="brush: css">input[type=search] { + border: 1px dotted #999; + border-radius: 0; + + -webkit-appearance: none; +}</pre> + +<p><img alt="This is a screenshot of a search filed on Chrome, with and without the use of -webkit-appearance" src="/files/4153/search-chrome-macos.png" style="border-style: solid; border-width: 1px; height: 107px; width: 179px;"></p> + +<p>En esta captura de pantalla pueden verse dos campos de búsqueda en Chrome, ambos campos tienen definido el borde como en nuestro ejemplo, pero el primero no utiliza -webkit- mientras que el segundo si lo hace con -webkit-appearance:none. Las diferencias son evidentes.</p> + +<h3 id="Fuentes_y_texto">Fuentes y texto</h3> + +<p>Las fuentes y capacidades de texto de CSS se pueden utilizar sin problemas en cualquier widget (y sí, se puede utilizar <a href="/es/docs/Web/CSS/@font-face">@font-face</a> en formularios). De todas formas, el comportamiento de los navegadores no es siempre consistente. Por defecto, algunos widgets no heredan <a href="/es/docs/Web/CSS/font-family">font-family</a> ni <a href="/es/docs/Web/CSS/font-size">font-size</a> de sus antecesores. Y muchos navegadores utilizan la apariencia por defecto. Para mantener la coherencia de los formularios con el resto de elementos se deben añadir las siguientes reglas a la hoja de estilos:</p> + +<pre class="brush: css">button, input, select, textarea { + font-family : inherit; + font-size : 100%; +}</pre> + +<p>La siguiente captura de pantalla muestra estas incosistencias; a la izquierda la apariencia por defecto en Firefox sobre Mac OS X, usando las fuentes por defecto de la plataforma. A la derecha los mismos elementos aplicando nuestras reglas de armonización de fuentes.</p> + +<p><img alt="This is a screenshot of the main form widgets on Firefox on Mac OSX, with and without font harmonization" src="/files/4157/font-firefox-macos.png" style="border-style: solid; border-width: 1px; height: 234px; width: 420px;"></p> + +<p>Hay muchas controversia sobre si los formularios tienen mejor aspecto usando los estilos por defecto del sistema o usando estilos personalizados que coincidan con el resto del contenido. Como diseñador del sitio o aplicación Web esta decisión es suya.</p> + +<h3 id="Modelo_de_cajas">Modelo de cajas</h3> + +<p>Todos los campos de texto tienen soporte completo para las propiedades relacionadas con el modelo de cajas de CSS (<a href="/es/docs/Web/CSS/width">width</a>, <a href="/es/docs/Web/CSS/height">height</a>, <a href="/es/docs/Web/CSS/padding_paspartu">padding</a>, margin y <a href="/es/docs/CSS/border">border</a>). Igual que antes, los navegadores se remiten a los estilos por defecto del sistema cuando muestran estos widgets. A cada cual te corresponde el como combinarlos dentro del resto de contenido. Si se quieres mantener el aspecto nativo de los widgets, entonces hay que afrontar pequeñas inconsistencias de tamaño.</p> + +<p>Esto es porque cada widget tiene sus propias reglas para el orden, margen y padding. Por lo que si quieres darle el mismo tamaño a varios widgets diferentes se debe usar la propiedad box-sizing: </p> + +<pre class="brush: css">input, textarea, select, button { + width : 150px; + margin: 0; + + -webkit-box-sizing: border-box; /* For legacy WebKit based browsers */ + -moz-box-sizing: border-box; /* For legacy (Firefox <29) Gecko based browsers */ + box-sizing: border-box; +}</pre> + +<p><img alt="This is a screenshot of the main form widgets on Chrome on Windows 7, with and without the use of box-sizing." src="/files/4161/size-chrome-win7.png" style="border-style: solid; border-width: 1px; height: 213px; width: 358px;"></p> + +<p>En la captura de pantalla de arriba, la columna la izquierda es sin utilizar box-sizing, mientras que la de la derecha usa esta propiedad con el valor border-box. Obsérvese cómo esto permite asegurar que todos los elementos ocupan la misma cantidad de espacio, independientemente de las reglas por defecto de la plataforma.</p> + +<h3 id="Posicionado">Posicionado</h3> + +<p>El posicionado de formularios HTML <span style="line-height: 23.3333339691162px;">no es </span><span style="line-height: 1.5;">generalmente un problema; sin embargo, hay dos elementos a los que prestar una especial atención:</span></p> + +<h4 id="legend">legend</h4> + +<p>El elemento <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend">legend </a>no tiene problemas de estilizado a excepción de las reglas de posición. En los navegadores el elemento <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/legend">legend </a>se posiciona encima del borde superior de su antecesor <a href="/es/docs/HTML/Elemento/fieldset">fieldset</a>. No existe ninguna posibilidad de colocarlo dentro del flujo HTML más allá del borde superior. Sin embargo se puede posicionar de forma relativa o absoluta mediante la propiedad position. En cualquier caso sigue siendo parte del borde de fieldset.</p> + +<p>Debido a que el elemento legend es muy importante por razones de accesibilidad (esto es lo que leen las tecnologías de asistencia como parte de las etiquetas de cada elemento de formulario dentro del fieldset), bastante menudo se empareja con un título que se oculta pero siendo aun accesible, de la forma siguiente:</p> + +<h5 id="HTML">HTML</h5> + +<pre class="brush: html"><fieldset> + <legend>Hi!</legend> + <h1>Hello</h1> +</fieldset></pre> + +<h5 id="CSS">CSS</h5> + +<pre class="brush: css">legend { + width: 1px; + height: 1px; + overflow: hidden; +}</pre> + +<h4 id="textarea">textarea</h4> + +<p>Por defecto, todos los navegadores consideran el elemento <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/textarea">textarea </a>como un inline block alineado con la línea base del texto. Esto es algo que raramente es lo que en realidad se quiere. Para convertir este elemento de un inline-block a uno tipo block, se realiza bastante fácilmente utilizando la propiedad <a href="/es/docs/CSS/display">display</a>. Si lo que quieres es utilizarlo inline, es corriente cambiar la alineación vertical: </p> + +<pre class="brush: css">textarea { + vertical-align: top; +}</pre> + +<h2 id="Ejemplo_2">Ejemplo</h2> + +<p>Vamos a ver un ejemplo de como aplicar estilo a un formulario HTML. Esto nos ayudará a tener las ideas más claras. A continuación construiremos el siguiente formulario de contacto de esta postal:</p> + +<p><img alt="This is what we want to achieve with HTML and CSS" src="/files/4149/screenshot.png" style="border-style: solid; border-width: 1px; height: 249px; width: 370px;"></p> + +<h3 id="HTML_2">HTML</h3> + +<p>El HTML incluye poco más de lo que se utiliza en el primer artículo de <a href="/en-US/docs/HTML/Forms/My_first_HTML_form">esta guía</a>; apenas el título y algún ID más.</p> + +<pre class="brush: html"><form> + <h1>to: Mozilla</h1> + + <div id="from"> + <label for="name">from:</label> + <input type="text" id="name" name="user_name"> + </div> + + <div id="reply"> + <label for="mail">reply:</label> + <input type="email" id="mail" name="user_email"> + </div> + + <div id="message"> + <label for="msg">Your message:</label> + <textarea id="msg" name="user_message"></textarea> + </div> + + <div class="button"> + <button type="submit">Send your message</button> + </div> +</form></pre> + +<h3 id="CSS_2">CSS</h3> + +<p>¿Aqui es donde empieza la diversión! Antes de empezar a codificar, necesitamos tres elementos adicionales:</p> + +<ol> + <li>El <a href="https://developer.mozilla.org/files/4151/background.jpg">fondo </a>de la postal</li> + <li>Una fuente tipográfica: <a href="http://www.fontsquirrel.com/fonts/Secret-Typewriter" rel="external" title="http://www.fontsquirrel.com/fonts/Secret-Typewriter">la "Secret Typewriter" de fontsquirrel.com</a></li> + <li>Una fuente manuscrita: <a href="http://www.fontsquirrel.com/fonts/Journal" rel="external" title="http://www.fontsquirrel.com/fonts/Journal">la "Journal" fde fontsquirrel.com</a></li> +</ol> + +<p>Ahora podemos repasar el código. Primero preparamos las bases definiendo las reglas <span style="line-height: 23.3333339691162px;"> </span><a href="https://developer.mozilla.org/es/docs/Web/CSS/@font-face" style="line-height: 23.3333339691162px;" title="@font-face permite al autor especificar fuentes online para visualizar en sus páginas web. Al permitir a los autores proporcionar sus propias fuentes, @font-face elimina la necesidad de depender del numero limitado de fuentes de usuarios instaladas en sus computadoras."><code>@font-face</code></a> y los elementos básicos de <a href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/body" style="line-height: 23.3333339691162px;" title="This article hasn't been written yet. Please consider contributing!"><code><body></code></a> y <a href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/form" style="line-height: 23.3333339691162px;" title="This article hasn't been written yet. Please consider contributing!"><code><form></code></a><span style="line-height: 23.3333339691162px;"> </span></p> + +<pre class="brush: css">@font-face{ + font-family : "handwriting"; + + src : url('journal.eot'); + src : url('journal.eot?') format('eot'), + url('journal.woff') format('woff'), + url('journal.ttf') format('truetype'); +} + +@font-face{ + font-family : "typewriter"; + + src : url('veteran_typewriter.eot'); + src : url('veteran_typewriter.eot?') format('eot'), + url('veteran_typewriter.woff') format('woff'), + url('veteran_typewriter.ttf') format('truetype'); +} + +body { + font : 21px sans-serif; + + padding : 2em; + margin : 0; + + background : #222; +} + +form { + position: relative; + + width : 740px; + height : 498px; + margin : 0 auto; + + background: #FFF url(background.jpg); +}</pre> + +<p>Ahora podemos posicionar los elementos, incluidos el título y los elementos del formulario.</p> + +<pre class="brush: css">h1 { + position : absolute; + left : 415px; + top : 185px; + + font : 1em "typewriter", sans-serif; +} + +#from { + position: absolute; + left : 398px; + top : 235px; +} + +#reply { + position: absolute; + left : 390px; + top : 285px; +} + +#message { + position: absolute; + left : 20px; + top : 70px; +}</pre> + +<p>Aquí es donde empezamos a trabajar los propios elementos. Primero, nos aseguramos que los elementos <span style="line-height: 23.3333339691162px;"> </span><a href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/label" style="line-height: 23.3333339691162px;" title="This article hasn't been written yet. Please consider contributing!"><code><label></code></a> reciben la fuente correcta.</p> + +<pre class="brush: css">label { + font : .8em "typewriter", sans-serif; +}</pre> + +<p>Los campos de texto necesitan algunas reglas comunes. Dicho simplemente, le quitamos bordes y fondos y redefinimos el padding y margin.</p> + +<pre class="brush: css">input, textarea { + font : .9em/1.5em "handwriting", sans-serif; + + border : none; + padding : 0 10px; + margin : 0; + width : 240px; + + background: none; +}</pre> + +<p>Cuando uno de estos campos recibe el foco, vamos a resaltarlo con un fondo transparente gris claro. Tome nota de que es importante añadir la propiedad <span style="line-height: 23.3333339691162px;"> </span><a class="new" href="https://developer.mozilla.org/es/docs/Web/CSS/outline" style="color: rgb(153, 0, 0); line-height: 23.3333339691162px;" title="The documentation about this has not yet been written; please consider contributing!"><code>outline</code></a><span style="line-height: 23.3333339691162px;"> </span> para quitar el resaltado de enfoque añadido por defecto por algunos navegadores.</p> + +<pre class="brush: css">input:focus, textarea:focus { + background : rgba(0,0,0,.1); + border-radius: 5px; + outline : none; +}</pre> + +<p>Ahora que nuestros campos de texto están terminados, necesitamos ajustar como se muestran los campos de simple y múltiple línea para que coincidan, ya que lo normal es que por defecto no se vean igual.</p> + +<p>El campo de línea simple requiere de algunos trucos para que se vean bien en Internet Explorer. Internet Explorer no define la altura de los campos basándose en la altura natural de la fuente (lo cual es el comportamiento normal del resto de navegadores). Para corregir esto necesitamos añadir explícitamente la altura a los campos de la siguiente forma:</p> + +<pre class="brush: css">input { + height: 2.5em; /* for IE */ + vertical-align: middle; /* This is optional but it makes legacy IEs look better */ +}</pre> + +<p>Los elementos <code style="color: rgb(153, 0, 0); line-height: 23.3333339691162px;"><a class="new" href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/textarea" style="color: rgb(153, 0, 0); line-height: 23.3333339691162px;" title="This article hasn't been written yet. Please consider contributing!"><textarea></a> </code>se muestran por defecto como bloques, Las dos cosas importantes aquí son las propiedades <a class="new" href="https://developer.mozilla.org/es/docs/Web/CSS/resize" style="color: rgb(153, 0, 0); line-height: 19.0909080505371px;" title="The documentation about this has not yet been written; please consider contributing!"><code>resize</code></a><span style="line-height: 19.0909080505371px;"> y </span><code style="line-height: 19.0909080505371px;"><a href="https://developer.mozilla.org/es/docs/Web/CSS/overflow" style="line-height: 19.0909080505371px;" title="La propiedad CSS overflow especifica: si recortar contenido, dibujar barras de desplazamiento o mostrar el contenido excedente en un elemento a nivel de bloque.">overflow</a>. </code>Ya que nuestro <code style="line-height: 19.0909080505371px;">diseño </code>es de tamaño fijo, utilizaremos la propiedad <code>resize</code> para impedir que el usuario pueda cambiar el tamaño de los campos multilínea. La propiedad <span style="line-height: 19.0909080505371px;"> </span><a href="https://developer.mozilla.org/es/docs/Web/CSS/overflow" style="line-height: 19.0909080505371px;" title="La propiedad CSS overflow especifica: si recortar contenido, dibujar barras de desplazamiento o mostrar el contenido excedente en un elemento a nivel de bloque."><code>overflow</code></a><span style="line-height: 19.0909080505371px;"> </span> se utiliza para que el campo se muestre de forma más consistente a través de diversos navegadores; algunos de ellos ponen por defecto esta propiedad en <code>auto</code>, pero en nuestro caso, es mejor asegurarse de que todos estén en <code>auto.</code></p> + +<pre class="brush: css">textarea { + display : block; + + padding : 10px; + margin : 10px 0 0 -10px; + width : 340px; + height : 360px; + + resize : none; + overflow: auto; +}</pre> + +<p>El elemento <code style="line-height: 19.0909080505371px;"><a href="https://developer.mozilla.org/es/docs/Web/HTML/Elemento/button" style="line-height: 19.0909080505371px;" title="This article hasn't been written yet. Please consider contributing!"><button></a> </code>se acomoda muy bien a CSS; se puede hacer lo que se quiera con el, ¡incluso utilizando<code style="line-height: 19.0909080505371px;"> <a href="https://developer.mozilla.org/en-US/docs/CSS/Pseudo-elements">pseudo-elementos</a>!</code></p> + +<pre class="brush: css">button { + position : absolute; + left : 440px; + top : 360px; + + padding : 5px; + + font : bold .6em sans-serif; + border : 2px solid #333; + border-radius: 5px; + background : none; + + cursor : pointer; + +-webkit-transform: rotate(-1.5deg); + -moz-transform: rotate(-1.5deg); + -ms-transform: rotate(-1.5deg); + -o-transform: rotate(-1.5deg); + transform: rotate(-1.5deg); +} + +button:after { + content: " >>>"; +} + +button:hover, +button:focus { + outline : none; + background: #000; + color : #FFF; +}</pre> + +<p>Y ¡listo! Sientase libre de probarlo usted mismo; como comprobará ¡esto funciona!</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Como puede verse, mientras que queramos construir formularios solo con campos de texto y botones, es sencillo aplicarles estilos con CSS. Si desea saber más pequeños trucos de CSS que le hagan más fácil la vida al trabajar con formularios, echele un vistazo a la parte de formularios de <a href="http://necolas.github.com/normalize.css" rel="external" style="line-height: 19.0909080505371px;" title="http://necolas.github.com/normalize.css">the normalize.css project</a><span style="line-height: 19.0909080505371px;">.</span></p> + +<p><span style="line-height: 19.0909080505371px;">En el próximo artículo, veremos como manejar widgets de formulario de la categoría de "el malo" y "el feo".</span></p> diff --git a/files/es/learn/html/forms/the_native_form_widgets/index.html b/files/es/learn/html/forms/the_native_form_widgets/index.html new file mode 100644 index 0000000000..c8a2651837 --- /dev/null +++ b/files/es/learn/html/forms/the_native_form_widgets/index.html @@ -0,0 +1,326 @@ +--- +title: Controles de formulario originales +slug: Learn/HTML/Forms/The_native_form_widgets +translation_of: Learn/Forms/Basic_native_form_controls +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Forms/How_to_structure_an_HTML_form", "Learn/Forms/HTML5_input_types", "Learn/Forms")}}</div> + +<p class="summary">En el <a href="/es/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">artículo anterior</a>, marcamos un ejemplo de formulario web funcional, presentamos algunos controles de formulario y elementos estructurales comunes, y nos centramos en las mejores prácticas de accesibilidad. A continuación, veremos con detalle las funciones de los diferentes controles de formulario, o <em>widgets</em>, y estudiaremos todas las diferentes opciones de que se dispone para la recopilación de diferentes tipos de datos. En este artículo en particular, veremos el conjunto original de controles de formulario, disponible en todos los navegadores desde los primeros días de la web.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática y de <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">lenguaje HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender en detalle el conjunto original de controles de formulario originales disponibles en los navegadores para la recopilación de datos y su implementación con HTML.</td> + </tr> + </tbody> +</table> + +<p>Ya conoces algunos elementos de formulario, incluidos {{HTMLelement ('form')}}, {{HTMLelement ('fieldset')}}, {{HTMLelement ('legend')}}, {{HTMLelement ('textarea' )}}, {{HTMLelement ('label')}}, {{HTMLelement ('button')}} y {{HTMLelement ('input')}}. Este artículo expone:</p> + +<ul> + <li>Los tipos de entrada comunes {{HTMLelement('input/button', 'button')}}, {{HTMLelement('input/checkbox', 'checkbox')}}, {{HTMLelement('input/file', 'file')}}, {{HTMLelement('input/hidden', 'hidden')}}, {{HTMLelement('input/image', 'image')}}, {{HTMLelement('input/password', 'password')}}, {{HTMLelement('input/radio', 'radio')}}, {{HTMLelement('input/reset', 'reset')}}, {{HTMLelement('input/submit', 'submit')}} y {{HTMLelement('input/text', 'text')}}.</li> + <li>Algunos de los atributos que comunes para todos los controles de formulario.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Las características que se consideran en este artículo son compatibles con todos los navegadores, lo que no es el caso para todos los controles de formulario. En los próximos dos artículos vamos a exponer los controles de formulario que se han añadido a HTML5 más recientemente. Si quieres una referencia más avanzada, consulta nuestra <a href="/es/docs/Web/HTML/Elemento#Formularios">referencia a elementos de formulario HTML</a>, y en particular nuestra extensa referencia a <a href="/es/docs/Web/HTML/Elemento/input">tipos <input></a>.</p> +</div> + +<h2 id="Campos_de_entrada_de_texto">Campos de entrada de texto</h2> + +<p>Los campos de texto {{htmlelement ("input")}} son los controles de formulario más básicos. Son un modo muy cómodo de permitir al usuario introducir cualquier tipo de datos, y ya hemos visto algunos ejemplos sencillos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Los campos de texto de los formularios HTML son controles de entrada de texto sencillos sin formato. Esto significa que no puedes usarlos para aplicar una <a href="/en-US/docs/Rich-Text_Editing_in_Mozilla" title="/en-US/docs/Rich-Text_Editing_in_Mozilla">edición enriquecida </a> (negrita, cursiva, etc.). Todos los controles de formulario que encuentres con texto enriquecido son controles de formulario personalizados creados con HTML, CSS y JavaScript.</p> +</div> + +<p>Todos los controles de texto básicos comparten algunos comportamientos comunes:</p> + +<ul> + <li>Se pueden marcar como {{htmlattrxref ("readonly","input")}} (el usuario no puede modificar el valor de entrada, pero este se envía con el resto de los datos del formulario) o {{htmlattrxref ("disabled","input")}} (el valor de entrada no se puede modificar y nunca se envía con el resto de los datos del formulario).</li> + <li>Pueden tener un {{htmlattrxref ("placeholder","input")}}; se trata de un texto que aparece dentro de la caja de entrada de texto y que se usa para describir brevemente el propósito de la caja de texto.</li> + <li>Pueden presentar una limitación de <a href="/en-US/docs/Web/HTML/Attributes/size">tamaño</a> (el tamaño físico de la caja de texto) y de la <a href="/en-US/docs/Web/HTML/Attributes/maxlength" title="/en-US/docs/HTML/Element/input#attr-maxlength">extensión máxima</a> (el número máximo de caracteres que se pueden poner en la caja de texto).</li> + <li>Admiten <a href="/en-US/docs/HTML/Element/input#attr-spellcheck" title="/en-US/docs/HTML/Element/input#attr-spellcheck"> corrección ortográfica</a> (utilizando el atributo <a href="/en-US/docs/Web/HTML/Attributes/spellcheck"><code>spellcheck</code></a>), si el navegador la admite.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: El elemento {{htmlelement ("input")}} es único entre los elementos HTML porque puede tomar muchas formas diferentes según el valor de su atributo. Se utiliza para crear la mayoría de los tipos de controles de formulario, que incluyen campos de texto de una sola línea, controles para la fecha y la hora, controles sin introducción de texto, como casillas de verificación, botones de opción y selectores de color, y botones.</p> +</div> + +<h3 id="Campos_de_texto_de_una_sola_línea">Campos de texto de una sola línea</h3> + +<p>Un campo de texto de una sola línea se crea utilizando un elemento {{HTMLElement ("input")}} cuyo valor de atributo {{htmlattrxref ("type","input")}} se establece en <code>text</code>, u omitiendo por completo el atributo {{htmlattrxref ( "type","input")}} (<code>text</code> es el valor predeterminado). El valor <code>text</code> de este atributo también es el valor alternativo si el navegador no reconoce el valor que has especificado para el atributo {{htmlattrxref ("type","input")}} (por ejemplo, si especificas <code>type="color"</code> y el navegador no está dotado en origen de un control de selección de colores).</p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar ejemplos de todos los tipos de campo de texto de una sola línea en GitHub en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/single-line-text-fields.html">single-line-text-fields.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/single-line-text-fields.html">o consultarlo en vivo</a>).</p> +</div> + +<p>Aquí hay un ejemplo básico de campo de texto de una sola línea:</p> + +<pre class="brush: html notranslate"><input type="text" id="comment" name="comment" value="I'm a text field"></pre> + +<p>Los campos de texto de una sola línea solo tienen una restricción verdadera: si escribes el texto con saltos de línea, el navegador elimina esos saltos de línea antes de enviar los datos al servidor.</p> + +<p><em>La captura de pantalla siguiente muestra los tipos de entrada de texto predeterminado, activo (con el foco) y deshabilitado en Firefox 71 y Safari en macOS y en Chrome 79 y Edge 18 en Windows 10.</em></p> + +<p><img alt="Captura de pantalla del atributo deshabilitado y predeterminado: estilo para una entrada de texto activa (con el foco) en Firefox, Safari, Chrome y Edge." src="https://mdn.mozillademos.org/files/17021/disabled.png" style="height: 113px; width: 442px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: HTML5 ha mejorado el campo de texto básico original de una sola línea al añadir valores especiales para el atributo {{htmlattrxref ("type", "input")}} que imponen restricciones de validación específicas y otras características, por ejemplo, específicas para introducir direcciones URL o números. Los expondremos en el artículo siguiente: <a href="/en-US/docs/Learn/Forms/HTML5_input_types">Los tipos de entrada en HTML5</a>.</p> +</div> + +<h4 id="Campo_de_contraseña">Campo de contraseña</h4> + +<p>Uno de los tipos de entrada originales era el tipo de campo de texto <code>password</code>:</p> + +<pre class="brush: html notranslate"><input type="password" id="pwd" name="pwd"></pre> + +<p>El valor de la contraseña no añade restricciones especiales al texto que se introduce, pero oculta el valor que se introduce en el campo (por ejemplo, con puntos o asteriscos) para impedir que otros puedan leerlo.</p> + +<p>Ten en cuenta que esto es solo una función de interfaz de usuario; a menos que envíes tu formulario en modo seguro, se enviará como texto plano, lo que es malo desde el punto de vista de la seguridad porque alguien con malas intenciones podría interceptar tus datos y robar tus contraseñas, datos de tarjetas de crédito o cualquier otra cosa que hayas enviado. La mejor manera de proteger a los usuarios de esto es alojar cualquier página que contenga formularios en una ubicación de conexión segura (es decir, en una dirección <code>https://</code>), de modo que los datos se cifren antes de enviarse.</p> + +<p>Los navegadores reconocen las implicaciones de seguridad de enviar datos de formulario por una conexión insegura y disponen de mensajes de advertencia para disuadir a los usuarios de usar formularios no seguros. Para obtener más información sobre las implementaciones de Firefox al respecto, consulta el artículo <a href="/es/docs/Seguridad/ContraseñasInseguras">Contraseñas inseguras</a>.</p> + +<h3 id="Contenido_oculto">Contenido oculto</h3> + +<p>Otro control de texto original es el tipo de entrada <code>hidden</code>. Se usa para crear un control de formulario que es invisible para el usuario, pero que aun así se envía al servidor junto con el resto de los datos del formulario una vez se transmiten; por ejemplo, es posible que desees enviar una marca de tiempo al servidor que indique cuándo se realizó un pedido. Al estar oculto, el usuario no puede ver ni editar su valor intencionadamente, el control nunca recibirá el foco y un lector de pantalla tampoco lo detectará.</p> + +<pre class="brush: html notranslate"><input type="hidden" id="timestamp" name="timestamp" value="1286705410"> +</pre> + +<p>Si creas un elemento así, es necesario establecer sus atributos <code>name</code> y <code>value</code>. Su valor puede establecerse dinámicamente a través de JavaScript. El tipo de entrada oculta no debe tener ninguna etiqueta asociada.</p> + +<p>Otros tipos de entrada de texto, como {{HTMLElement ("input / search", "search")}}, {{HTMLElement ("input / url", "url")}} y {{HTMLElement ("input / tel" , "tel")}}, se añadieron con HTML5. Se tratarán en el próximo artículo: Tipos de entrada HTML5.</p> + +<h2 id="Elementos_de_selección_casillas_de_verificación_y_botones_de_opción">Elementos de selección: casillas de verificación y botones de opción</h2> + +<p>Los elementos de selección (o <em>checkable items</em>, en inglés) son controles cuyo estado puede cambiar cuando se hace clic en ellos o en sus etiquetas asociadas. Hay dos tipos de elementos de selección: las casillas de verificación (o <em>check boxes</em>) y los botones de opción (o <em>radio buttons</em>). Ambos usan el atributo <code>checked</code> para indicar si el control de formulario está seleccionado por defecto o no.</p> + +<p>Vale la pena señalar que estos controles no se comportan exactamente como otros controles de formulario. Para la mayoría de los controles de formulario, cuando se envía el formulario, se envían todos los controles que tienen un atributo <a href="/en-US/docs/Web/HTML/Attributes/name"><code>name</code></a>, incluso si en ellos no se ha introducido ningún valor. En el caso de elementos de selección, sus valores se envían solo si están seleccionados. Si no están seleccionados, no se envía nada, ni siquiera su nombre. Si están seleccionados pero no tienen ningún valor asignado, el nombre se envía con el valor <em>on.</em></p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar los ejemplos de esta sección en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/checkable-items.html">checkable-items.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/checkable-items.html">o consultarlos en vivo</a>).</p> +</div> + +<p>Para una usabilidad/accesibilidad óptima, te recomendamos delimitar cada lista de elementos que estén relacionados entre sí dentro de un elemento {{htmlelement ("fieldset")}} con un elemento {{htmlelement ("legend")}} que proporcione una descripción general de la lista. Cada par individual de elementos {{htmlelement ("label")}}/{{htmlelement ("input")}} ha de estar contenido en un elemento de lista propio (o similar). El elemento {{htmlelement ('label')}} asociado se coloca en general inmediatamente después del botón de opción o la casilla de verificación, con las instrucciones para el grupo de botones de opción o casillas de verificación, que suelen ser el contenido del elemento {{htmlelement ("legend")}}. Observa las estructuras de ejemplo en los ejemplos asociados anteriores.</p> + +<h3 id="Casillas_de_verificación">Casillas de verificación</h3> + +<p>Las casillas de verificación se crean estableciendo el atributo <a href="/en-US/docs/Web/HTML/Attributes/type"><code>type</code></a> del elemento {{HTMLElement ("input")}} en el valor {{HTMLElement ("input / checkbox", "checkbox")}}.</p> + +<pre class="brush: html notranslate"><input type="checkbox" id="carrots" name="carrots" value="carrots" checked> +</pre> + +<p>Al incluir el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/checked">checked</a></code>, la casilla de verificación se marca automáticamente cuando se carga la página. Al hacer clic en la casilla de verificación o en su etiqueta asociada, la casilla de verificación se activa o desactiva.</p> + +<p>Las capturas de pantalla siguientes muestran casillas de verificación predeterminadas, activas (con el foco) y deshabilitadas en Firefox 71 y Safari 13 en macOS y Chrome 79 y Edge 18 en Windows 10:</p> + +<p><img alt="Casillas de verificación predeterminadas, activas y deshabilitadas en Firefox 71 y Safari 13 en Mac y Chrome 79 y Edge 18 en Windows 10" src="https://mdn.mozillademos.org/files/17024/checkboxes.png" style="height: 203px; width: 293px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Las casillas de verificación y los botones de opción con atributo <code><a href="/en-US/docs/Web/HTML/Attributes/checked">checked</a></code> al cargarse coinciden con la pseudoclase {{cssxref ('<code>:default</code>')}}, incluso aunque ya no estén seleccionadas. Las que están seleccionadas coinciden con la pseudoclase <code>{{cssxref(':checked')}}</code>.</p> +</div> + +<p id="Radio_button">Debido a su naturaleza activa-inactiva, las casillas de verificación se consideran botones de conmutación, y muchos desarrolladores y diseñadores han ampliado el estilo de casilla de verificación predeterminado para crear botones que parecen interruptores de conmutación. Aquí puedes ver un <a href="https://mdn.github.io/learning-area/html/forms/toggle-switch-example/">ejemplo en acción</a> (observa también el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/toggle-switch-example/index.html">código fuente</a>).</p> + +<h3 id="Botón_de_opción">Botón de opción</h3> + +<p>Un botón de opción se crea estableciendo el atributo {{htmlattrxref ("type", "input")}} del elemento {{HTMLElement ("input")}} en el valor <code>radio</code>:</p> + +<pre class="brush: html notranslate"><input type="radio" id="soup" name="meal" checked></pre> + +<p>Es posible asociar diversos botones de opción. Si comparten el mismo valor de atributo {{htmlattrxref ("name", "input")}}, se considera que están en el mismo grupo de botones. Solo un botón dentro de un grupo puede estar activado en cada momento. Esto significa que cuando uno de ellos se selecciona, todos los demás se deseleccionan automáticamente. Al enviar el formulario, solo se envía el valor del botón de opción seleccionado. Si ninguno de ellos está seleccionado, se considera que el conjunto completo de botones de opción está en un estado desconocido y no se envía ningún valor con el formulario. Cuando en un grupo de botones con el mismo nombre se selecciona uno de los botones de opción, no es posible deseleccionar todos los botones sin reiniciar el formulario.</p> + +<pre class="brush: html notranslate"><fieldset> + <legend>¿Cuál es tu comida favorita?</legend> + <ul> + <li> + <label for="soup">Sopa</label> + <input type="radio" id="soup" name="meal" value="soup" checked> + </li> + <li> + <label for="curry">Curry</label> + <input type="radio" id="curry" name="meal" value="curry"> + </li> + <li> + <label for="pizza">Pizza</label> + <input type="radio" id="pizza" name="meal" value="pizza"> + </li> + </ul> +</fieldset></pre> + +<p>Las capturas de pantalla siguientes muestran botones de opción sin seleccionar y seleccionados, algunos con el foco y otros desactivados sin seleccionar y seleccionados, en Firefox 71 y Safari 13 en MacOS y Chrome 79 y Edge 18 en Windows 10.</p> + +<p><img alt="Botones de opción en Firefox 71 y Safari 13 en Mac y Chrome 79 y Edge 18 en Windows 10" src="https://mdn.mozillademos.org/files/17022/radios.png" style="height: 142px; width: 196px;"></p> + +<h2 id="Botones">Botones</h2> + +<p>El botón de opción no es realmente un botón, a pesar de su nombre; sigamos adelante y echemos un vistazo a los controles de formulario que son botones propiamente. Hay tres tipos de entrada según el tipo de botones que se utilicen:</p> + +<dl> + <dt><code>submit</code></dt> + <dd>Envía los datos del formulario al servidor. Para los elementos {{HTMLElement ("button")}}, omitir el atributo <code>type</code> (o introducir un valor de tipo no válido) da como resultado un botón de envío (<em>submit</em>).</dd> + <dt><code>reset</code></dt> + <dd>Restablece todos los controles de formulario a sus valores por defecto.</dd> + <dt><code>button</code></dt> + <dd>Botones que no tienen efecto automático, pero que se pueden personalizar con código JavaScript.</dd> +</dl> + +<p>Además, el elemento {{htmlelement ("button")}} puede tomar un atributo <code>type</code> para imitar estos tres tipos de entrada. La diferencia principal entre los dos es que los elementos <code><button></code> propiamente admiten aplicación de estilo en mayor medida.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: El tipo de entrada <code>image</code> también se representa como un botón. También desarrollaremos este tema más adelante.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar los ejemplos de esta sección en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/forms/native-form-widgets/button-examples.html">button-examples.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/native-form-widgets/button-examples.html">o consultarlos en vivo</a>).</p> +</div> + +<p>A continuación puedes encontrar ejemplos de cada tipo de botón <code><input></code>, junto con el tipo de botón equivalente.</p> + +<h3 id="enviar">enviar</h3> + +<pre class="brush: html notranslate"><button type="submit"> + Este es un <strong>botón de envío</strong> +</button> + +<input type="submit" value="Este es un botón de envío"></pre> + +<h3 id="reiniciar">reiniciar</h3> + +<pre class="brush: html notranslate"><button type="reset"> + Este es un <strong>botón de reinicio</strong> +</button> + +<input type="reset" value="Este es un botón de reinicio"></pre> + +<h3 id="anónimo">anónimo</h3> + +<pre class="brush: html notranslate"><button type="button"> + Este es un <strong>botón anónimo</strong> +</button> + +<input type="button" value="Este es un botón anónimo"></pre> + +<p>Los botones siempre se comportan igual, independientemente de su usas un elemento {{HTMLElement ("button")}} o un elemento {{HTMLElement ("input")}}. Sin embargo, como puedes ver en los ejemplos, los elementos {{HTMLElement ("button")}} te permiten usar HTML en tu contenido, que se inserta entre las etiquetas <code><button></code> de apertura y cierre. Los elementos {{HTMLElement ("input")}}, por otro lado, son elementos vacíos; el contenido que muestran está inserto en el atributo <code>value</code> y, por lo tanto, solo acepta contenido de texto sin formato.</p> + +<p>Los ejemplos siguientes muestran los tipos de entrada de botones predeterminados, activos y deshabilitados: en Firefox 71 y Safari 13 en macOS, y Chrome 79 y Edge 18 en Windows 10.</p> + +<p><img alt="Tipos de entrada de botones predeterminados, activos y deshabilitados en Firefox 71 y Safari 13 en Mac y Chrome 79 y Edge 18 en Windows 10" src="https://mdn.mozillademos.org/files/17023/buttons.png" style="height: 182px; width: 286px;"></p> + +<h3 id="Botón_de_imagen">Botón de imagen</h3> + +<p>El control <strong>botón de imagen</strong> se muestra exactamente como un elemento {{HTMLElement ("img")}}, excepto que cuando el usuario hace clic en él, se comporta como un botón de envío.</p> + +<p>Se crea un botón de imagen usando un elemento {{HTMLElement ("input")}} con su atributo {{htmlattrxref ("type","input")}} establecido en el valor <code>image</code>. Este elemento admite exactamente el mismo conjunto de atributos que el elemento {{HTMLElement ("img")}}, además de todos los atributos que admiten el resto de botones de formulario.</p> + +<pre class="brush: html notranslate"><input type="image" alt="¡Púlsame!" src="my-img.png" width="80" height="30"></pre> + +<p>Si el botón de imagen se usa para enviar un formulario, este control no envía su valor; en lugar de ello se envían las coordenadas X e Y del clic que se ha hecho sobre la imagen (las coordenadas son relativas a la imagen, lo que significa que la esquina superior izquierda de la imagen representa la coordenada (0, 0)). Las coordenadas se envían como dos pares clave/valor:</p> + +<ul> + <li>La clave del valor X es el valor del atributo {{htmlattrxref ("name","input")}} seguido de la cadena de caracteres «<em>.x</em>».</li> + <li>La clave del valor Y es el valor del atributo {{htmlattrxref ("name","input")}} seguido de la cadena de caracteres «<em>.y</em>».</li> +</ul> + +<p>Por ejemplo, cuando haces clic en las coordenadas (123, 456) de la imagen y se hace el envío por el método <code>get</code>, verás los valores añadidos a la URL de la manera siguiente:</p> + +<pre class="notranslate">http://foo.com?pos.x=123&pos.y=456</pre> + +<p>Esta es una forma muy cómoda de construir un «mapa dinámico». La forma en que se envían y recuperan estos valores se detalla en el artículo <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos del formulario</a>.</p> + +<h2 id="Selector_de_archivos">Selector de archivos</h2> + +<p>Hay un último tipo de <code><input></code> que nos llegó a principios del HTML: el tipo entrada de archivo. Los formularios pueden enviar archivos a un servidor (esta acción específica también se detalla en el artículo <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos del formulario</a>). El control de selección de archivos se puede usar para elegir uno o más archivos para enviar.</p> + +<p>Para crear un <a href="/en-US/docs/Web/HTML/Element/input/file">control de selección de archivos</a>, utilizas el elemento {{HTMLElement ("input")}} con su atributo {{htmlattrxref ("type","input")}} establecido en <code>file</code>. Es posible restringir los tipos de archivos que se aceptan utilizando el atributo {{htmlattrxref ("accept","input")}}. Además, puedes permitir que el usuario elija más de un archivo añadiendo el atributo {{htmlattrxref ("multiple","input")}}.</p> + +<h4 id="Ejemplo">Ejemplo</h4> + +<p>En este ejemplo, se crea un control de selección de archivos que solicita archivos de imágenes gráficas. El usuario puede seleccionar múltiples archivos en este caso.</p> + +<pre class="brush: html notranslate"><input type="file" name="file" id="file" accept="image/*" multiple></pre> + +<p>En algunos dispositivos móviles, el control de selección de archivos puede acceder a fotos, vídeos y audio capturados directamente por la cámara y el micrófono del dispositivo y añadir información de captura al atributo <code>accept</code> de la manera siguiente:</p> + +<pre class="notranslate"><input type="file" accept="image/*;capture=camera"> +<input type="file" accept="video/*;capture=camcorder"> +<input type="file" accept="audio/*;capture=microphone"></pre> + +<h2 id="Atributos_comunes">Atributos comunes</h2> + +<p>Muchos de los elementos que se utilizan para definir controles de formulario tienen sus atributos específicos propios. Sin embargo, hay un conjunto de atributos que son comunes para todos los elementos de formulario. Ya has conocido algunos, pero a continuación encontrarás una lista de esos atributos comunes para referencias futuras:</p> + +<table> + <thead> + <tr> + <th scope="col">Nombre del atributo</th> + <th scope="col">Valor por defecto</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/autofocus">autofocus</a></code></td> + <td>false</td> + <td>Este atributo booleano te permite especificar que el elemento ha de tener el foco de entrada automáticamente cuando se carga la página. En un documento, solo un elemento asociado a un formulario puede tener este atributo especificado.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/disabled">disabled</a></code></td> + <td>false</td> + <td>Este atributo booleano indica que el usuario no puede interactuar con el elemento. Si no se especifica este atributo, el elemento hereda su configuración del elemento que lo contiene, por ejemplo, {{HTMLElement ("fieldset")}}. Si el elemento que lo contiene no tiene el atributo establecido en <code>disabled</code>, el elemento está habilitado.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/form">form</a></code></td> + <td></td> + <td>El elemento <code><form></code> con el que está asociado el control, que se usa cuando no está anidado dentro de ese formulario. El valor del atributo debe ser el atributo <code>id</code> de un elemento {{HTMLElement ("form")}} del mismo documento. Esto te permite asociar un formulario con un control de formulario que esté fuera de aquel, incluso si está dentro de un elemento de formulario diferente.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/name">name</a></code></td> + <td></td> + <td>El nombre del elemento; se envía con los datos del formulario.</td> + </tr> + <tr> + <td><code><a href="/en-US/docs/Web/HTML/Attributes/value">value</a></code></td> + <td></td> + <td>El valor inicial del elemento.</td> + </tr> + </tbody> +</table> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Este artículo ha expuesto los tipos de entrada más antiguos: el conjunto original que se introdujo en los primeros días de HTML, que es compatible con todos los navegadores. En el artículo siguiente veremos los valores del atributo <code>type</code> que se han añadido en HTML5 más recientemente.</p> + +<p>{{PreviousMenuNext("Learn/Forms/How_to_structure_an_HTML_form", "Learn/Forms/HTML5_input_types", "Learn/Forms")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Your_first_HTML_form">Tu primer formulario HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">Cómo estructurar un formulario HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/The_native_form_widgets">Los controles básicos de formulario originales</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML5_input_types">Tipos de entrada HTML5</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Additional_form_controls">Controles de formulario adicionales</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/UI_pseudo-classes">Pseudoclases UI</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Styling_HTML_forms">Aplicar estilo a formularios HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Form_validation">Validación de datos en un formulario</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a></li> +</ul> + +<h3 id="Temas_avanzados">Temas avanzados</h3> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Forms/Sending_forms_through_JavaScript">Enviar formularios con JavaScript</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/How_to_build_custom_form_widgets">Cómo crear widgets de formularios personalizados</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/HTML_forms_in_legacy_browsers">Formularios HTML en navegadores antiguos</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Advanced_styling_for_HTML_forms">Cuestiones avanzadas de aplicación de estilo para formularios HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Forms/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad de los controles de formulario</a></li> +</ul> diff --git a/files/es/learn/html/forms/tipos_input_html5/index.html b/files/es/learn/html/forms/tipos_input_html5/index.html new file mode 100644 index 0000000000..d463399e93 --- /dev/null +++ b/files/es/learn/html/forms/tipos_input_html5/index.html @@ -0,0 +1,276 @@ +--- +title: Tipos de input de HTML5 +slug: Learn/HTML/Forms/Tipos_input_HTML5 +translation_of: Learn/Forms/HTML5_input_types +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Forms/Basic_native_form_controls", "Learn/Forms/Other_form_controls", "Learn/Forms")}}</div> + +<p class="summary">En el <a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">artículo anterior</a> vimos el elemento {{htmlelement("input")}} y los valores de su atributo <code>type</code>, disponibles desde los inicios de HTML. Ahora veremos en detalle la funcionalidad de los controles de formulario más recientes, incluyendo algunos tipos de input nuevos, los cuales fueron añadidos en HTML5 para permitir la recolección de tipos de datos específicos</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Formación básica en informática, y una <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">comprensión básica de HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender los valores de tipo input disponibles más recientes para crear controles de formulario nativos, y cómo implementarlos utilizando HTML.</td> + </tr> + </tbody> +</table> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: La mayoría de las características discutidas en este artículo tienen un amplio soporte en todos los navegadores, anotaremos cualquier excepción. Si quieres más detalles referente al soporte de navegadores, deberías consultar nuestra <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element#Forms">referéncia de elementos de formulario HTML</a>, y en particular nuestra referéncia extensiva de <a href="/en-US/docs/Web/HTML/Element/input">Tipos de <input></a>.</p> +</div> + +<p>Debido a que la apariéncia de un control de formulario puede ser algo distinta con respecto a unas especificaciones del diseñador, los desarrolladores web a veces construyen sus propios controles de formulario personalizados. Cubrimos este aspecto en un tutorial avanzado: <a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_widgets">Cómo construir widgets de formulario personalizados</a>.</p> + +<h2 id="Campo_de_dirección_de_correo_electrónico">Campo de dirección de correo electrónico</h2> + +<p>Este tipo de campo se define utilizando el valor <code>email</code> en el atributo {{htmlattrxref("type","input")}} del elemento <input>:</p> + +<pre class="brush: html notranslate"><input type="email" id="email" name="email"></pre> + +<p>Cuando se utiliza este valor {{htmlattrxref("type","input")}} , se le obliga al usuario a escribir dentro del campo una dirección de correo electrónico válida. Cualquier otro contenido ocasiona que el navegador muestre un mensaje de error cuando se envía el formulario. Puedes verlo en acción en la siguiente captura de pantalla</p> + +<p><img alt='An invalid email input showing the message "Please enter an email address."' src="https://mdn.mozillademos.org/files/17027/email_address_invalid.png" style="display: block; height: 224px; margin: 0 auto; width: 369px;"></p> + +<p>Puedes utilizar también el atributo <a href="/en-US/docs/Web/HTML/Attributes/multiple"><code>multiple</code></a> en combinación con el tipo input<code>email</code> para permitir que sean introducidas varias direcciones de correo electrónico separadas por comas en el mismo input:</p> + +<pre class="brush: html notranslate"><input type="email" id="email" name="email" multiple></pre> + +<p>En algunos dispositivos, en particular dispositivos táctiles con teclados dinámicos como los smart phones, debería presentarse un teclado virtual que es más adecuado para introducir direcciones de correo electrónico, incluyendo la tecla <code>@</code>. Mira como ejemplo la siguiente captura de pantalla del teclado de Firefox para Android:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17054/fx-android-email-type-keyboard.jpg" style="border-style: solid; border-width: 1px; display: block; height: 324px; margin: 0 auto; width: 400px;"></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar ejemplos sobre los tipos de entrada de texto básicos en <a href="https://mdn.github.io/learning-area/html/forms/basic-input-examples/">Ejemplos input básicos</a> (Consulta también el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/basic-input-examples/index.html">código fuente</a>).</p> +</div> + +<p>Mejorar la experiéncia del usuario para usuarios con estos dispositivos, es otra buena razón para utilizar estos tipos de input más recientes.</p> + +<h3 id="Validación_del_lado_cliente">Validación del lado cliente</h3> + +<p>Como puedes haber visto anteriormente, <code>email</code>, junto con otros tipos de <code>input</code> más recientes, proporciona la validación de errores <em>en el lado cliente</em> de forma predeterminada, realizados por el navegador antes de que los datos obtenidos se envíen al servidor. <em>Es</em> una ayuda útil guiar a los usuarios a rellenar un formulario de forma precisa y puede ahorrar tiempo: es útil saber de inmediato que tu dato no es correcto, en vez de tener que esperar el viaje de ida y vuelta al servidor.</p> + +<p>Pero <em>no debería ser considerado</em> una medida de seguridad exhaustiva! Tus aplicaciones siempre deben realizar comprobaciones de seguridad en cada dato, tanto en el <em>lado servidor</em> como en el lado cliente debido a que la validación en el lado cliente es muy fácil desactivarla, por lo que usuarios malintencionados pueden enviar fácilmente datos incorrectos al servidor. Lee <a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">Seguridad en el sitio web</a> para tener una idea de lo que <em>podría</em> ocurrir; Implementar validación en el lado servidor está más allá del alcance de este módulo-guía, pero debería tenerlo en cuenta.</p> + +<p>Ten en cuenta que <code>a@b</code> es una dirección de correo electrónico válida de acuerdo a las restricciones proporcionadaas por defecto. Esto es debido a que el tipo de input <code>email</code>, permite por defecto direcciones de correo electrónico de una intranet. Para implementar un comportamiento diferente de validación puedes utilizar el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/pattern">pattern</a></code>, y también puedes utilizar mensajes de error personalizados; Hablaremos de cómo utilizar estas características en <a href="/en-US/docs/Learn/Forms/Form_validation">Validación de formularios en el lado cliente</a> en un artículo posterior.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si los datos introducidos no son una dirección de correo electrónico, habrá coincidéncia con la pseudo clase {{cssxref(':invalid')}}, y la propiedad {{domxref('validityState.typeMismatch')}} devolverá <code>true</code>.</p> +</div> + +<h2 id="Campo_de_búsqueda">Campo de búsqueda</h2> + +<p>Los campos de búsqueda están destinados a ser utilizados para crear cajas de búsqueda en páginas y aplicaciones. Este tipo de campo se define utilizando el valor <code>search</code> en su atributo {{htmlattrxref("type","input")}}:</p> + +<pre class="brush: html notranslate"><input type="search" id="search" name="search"></pre> + +<p>La diferéncia principal entre un campo <code>text</code> y un campo <code>search</code>, es la forma en que el navegador aplica estilo a su apariéncia. A menudo los campos <code>search</code> se muestran con bordes redondeados; y a veces también muestran una "Ⓧ", el cual despeja el campo de cualquier valor cuando se pulsa sobre él. Adicionalmente, en dispositivos con teclado dinámico, la tecla enter del teclado puede leer "<strong>search</strong>" o mostrar un icono de lupa.</p> + +<p>La captura de pantalla siguiente muestra un campo de búsqueda con contenido, en Firefox 71, Safari 13, y Chrome 79 en macOS, y Edge 18 y Chrome 79 en Windows 10. Ten en cuenta que el icono de reseteo sólo aparece si el campo tiene un valor y, aparte de Safari, sólo se muestra cuando el campo tiene el foco.</p> + +<p><img alt="Screenshots of search fields on several platforms." src="https://mdn.mozillademos.org/files/17028/search_focus.png" style="height: 179px; width: 549px;"></p> + +<p>Otra característica que vale la pena señalar es que se puede guardar los valores de un campo <code>search</code> automáticamente y reutilizarse en múltiples páginas del mismo sitio web para ofrecer autocompletado. Esta característica suele ocurrir de forma automática en la mayoría de navegadores modernos.</p> + +<h2 id="Campo_número_de_teléfono">Campo número de teléfono</h2> + +<p>Se puede crear un campo especial para introducir números de teléfono utilizando <code>tel</code> como valor del atributo {{htmlattrxref("type","input")}}:</p> + +<pre class="brush: html notranslate"><input type="tel" id="tel" name="tel"></pre> + +<p>Cuando se accede desde un dispositivo táctil con teclados dinámicos, muchos de ellos mostrarán un teclado numérico cuando se encuentren con <code>type="tel"</code>, lo que significa que este tipo es útil no sólo para ser utilizado para números de teléfono, sino también cuando sea útil un teclado numérico.</p> + +<p>La siguiente captura de pantalla del teclado de Firefox para Android proporciona un ejemplo:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17056/fx-android-tel-type-keyboard.jpg" style="border-style: solid; border-width: 1px; display: block; height: 276px; margin: 0px auto; width: 400px;"></p> + +<p>Debido a la gran variedad de formatos de número de teléfono existentes, este tipo de campo no cumple con ningún tipo de restricción sobre el valor introducido por el usuario. (Esto significa que puede incluir letras, etc...).</p> + +<p>Como mencionamos anteriormente, se puede utilizar el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/pattern">pattern</a></code> para que asuma restricciones, sobre el cuál aprenderemos en <a href="/en-US/docs/Learn/Forms/Form_validation">Validación de formulario en el lado cliente</a>.</p> + +<h2 id="Campo_URL">Campo URL</h2> + +<p>Se puede crear un tipo especial de campo para introducir URLs utilizando el valor <code>url</code> para el atributo {{htmlattrxref("type","input")}}:</p> + +<pre class="brush: html notranslate"><input type="url" id="url" name="url"></pre> + +<p>Este tipo añade restricciones de validación en el campo. El navegador informará de un error si no se introdujo el protocolo (como <code>http:</code>), o si de algún modo el URL está mal formado. En dispositivos con teclados dinámicos a menudo mostrará por defecto algunas o todas las teclas como los dos puntos, el punto, y la barra inclinada.</p> + +<p>Mira el siguiente ejemplo tomado de Firefox para Android:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17057/fx-android-url-type-keyboard.jpg" style="border-style: solid; border-width: 1px; display: block; height: 325px; margin: 0px auto; width: 400px;"></p> + +<div class="note"><strong>Nota:</strong> Solo porque el URL esté bien formado no significa necesariamente que la dirección al que hace referéncia exista!</div> + +<h2 id="Campo_numérico">Campo numérico</h2> + +<p>Se pueden crear controles para introducir números con el {{htmlattrxref("type","input")}} <code>number</code> de {{HTMLElement("input")}}. Este control se parece a un campo de texto pero solo permite números de punto flotante, y normalmente proporciona botones deslizadores para incrementar o reducir el valor del control. En dispositivos con teclados dinámicos generalmente se muestra el teclado numérico.</p> + +<p>La siguiente captura de pantalla tomada de Firefox para Android proporciona un ejemplo:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17055/fx-android-number-type-keyboard.jpg" style="border-style: solid; border-width: 1px; display: block; height: 275px; margin: 0px auto; width: 400px;"></p> + +<p>Con el tipo de input <code>number</code> puedes limitar los valores mínimo y máximo permitidos definiendo los atributos {{htmlattrxref("min","input")}} y {{htmlattrxref("max","input")}}.</p> + +<p>También puedes utilizar el atributo <code>step</code> para cambiar el incremento y decremento causado por los botones deslizadores. Por defecto, el tipo de input number sólo valida si el número es un entero. Para permitir números decimales, especifica <code><a href="/en-US/docs/Web/HTML/Attributes/step">step="any"</a></code>. Si se omite, su valor por defecto es <code>1</code>, lo que significa que solo son válidos números enteros.</p> + +<p>Miremos algunos ejemplos. El primero de los siguientes crea un control numérico cuyo valor está restringido a cualquier valor entre <code>1</code> y <code>10</code>, y sus botones cambian su valor en incrementos o decrementos de <code>2</code>.</p> + +<pre class="brush: html notranslate"><input type="number" name="age" id="age" min="1" max="10" step="2"></pre> + +<p>El segundo crea un control numérico cuyo valor está restringido a cualquier valor entre el <code>0</code> y <code>1</code> ambos inclusive, y sus botones cambian su valor en incrementos o decrementos de <code>0.01</code>.</p> + +<pre class="brush: html notranslate"><input type="number" name="change" id="pennies" min="0" max="1" step="0.01"></pre> + +<p>El tipo de input <code>number</code> tiene sentido cuando esté limitado el rango de valores válidos, por ejemplo la edad de una persona o su altura. Si el rango es demasiado grande para que los cambios de incremento tengan sentido ( por ejemplo los códigos postales de USA, cuyo rango va de <code>00001</code> a <code>99999</code>), entonces sería una mejor opción utilizar el tipo <code>tel</code>: proporciona el teclado numérico mientras que omite el componente de interfaz de usuario de los deslizadores de número.</p> + +<div class="blockIndicator note"> +<p><strong>Ten en cuenta que</strong>: En versiones inferiores a la 10 de Internet Explorer no se soportan las entradas <code>number</code></p> +</div> + +<h2 id="Slider_controls">Slider controls</h2> + +<p>Otra forma de tomar un número es usando un <strong>slider</strong>. Podrás observar cómo son bastantes parecidas a los sitios inmobiliarios, dónde quieres determinar un máximo de precio por propiedad y filtrar tu búsqueda en el. Observaremos un ejemplo en vivo.</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/range-example/index.html", '100%', 200)}}</p> + +<p>Usage-wise, sliders are less accurate than text fields. Therefore, they are used to pick a number whose <em>precise</em> value is not necessarily important.</p> + +<p>A slider is created using the {{HTMLElement("input")}} with its {{htmlattrxref("type","input")}} attribute set to the value <code>range</code>. The slider-thumb can be moved via mouse or touch, or with the arrows of the keypad.</p> + +<p>It's important to properly configure your slider. To that end, it's highly recommended that you set the <code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code>, <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code>, and <code><a href="/en-US/docs/Web/HTML/Attributes/step">step</a></code> attributes which set the minimum, maximum and increment values, respectively.</p> + +<p>Let's look at the code behind the above example, so you can see how its done. First of all, the basic HTML:</p> + +<pre class="brush: html notranslate"><label for="price">Choose a maximum house price: </label> +<input type="range" name="price" id="price" min="50000" max="500000" step="100" value="250000"> +<output class="price-output" for="price"></output></pre> + +<p>This example creates a slider whose value may range between <code>50000</code> and <code>500000</code>, which increments/decrements by 100 at a time. We've given it default value of <code>250000</code>, using the <code>value</code> attribute.</p> + +<p>One problem with sliders is that they don't offer any kind of visual feedback as to what the current value is. This is why we've included an {{htmlelement("output")}} element — to contain the current value (we'll also look at this element in the next article). You could display an input value or the output of a calculation inside any element, but <code><output></code> is special — like <code><label></code>, it can take a <code>for</code> attribute that allows you to associate it with the element or elements that the output value came from.</p> + +<p>To actually display the current value, and update it as it changed, you must use JavaScript, but this is relatively easy to do:</p> + +<pre class="brush: js notranslate">const price = document.querySelector('#price') +const output = document.querySelector('.price-output') + +output.textContent = price.value + +price.addEventListener('input', function() { + output.textContent = price.value +});</pre> + +<p>Here we store references to the <code>range</code> input and the <code>output</code> in two variables. Then we immediately set the <code>output</code>'s <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> to the current <code>value</code> of the input. Finally, an event listener is set to ensure that whenever the range slider is moved, the <code>output</code>'s <code>textContent</code> is updated to the new value.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: <code>range</code> inputs are not supported in versions of Internet Explorer below 10.</p> +</div> + +<h2 id="Date_and_time_pickers">Date and time pickers</h2> + +<p>Gathering date and time values has traditionally been a nightmare for web developers. For good user experience, it is important to provide a calendar selection UI, enabling users to select dates without necessating context switching to a native calendar application or potentially entering them in differing formats that are hard to parse. The last minute of the previous millenium can be expressed in the following different ways, for example: 1999/12/31, 23:59 or 12/31/99T11:59PM.</p> + +<p>HTML date controls are available to handle this specific kind of data, providing calendar widgets and making the data uniform.</p> + +<p>A date and time control is created using the {{HTMLElement("input")}} element and an appropriate value for the {{htmlattrxref("type","input")}} attribute, depending on whether you wish to collect dates, times, or both. Here's a live example that falls back to {{htmlelement("select")}} elements in non-supporting browsers:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/datetime-local-picker-fallback/index.html", '100%', 200)}}</p> + +<p>Let's look at the different available types in brief. Note that the usage of these types is quite complex, especially considering browser support (see below); to find out the full details, follow the links below to the reference pages for each type, including detailed examples.</p> + +<h3 id="datetime-local"><code>datetime-local</code></h3> + +<p><code><a href="/en-US/docs/Web/HTML/Element/input/datetime-local"><input type="datetime-local"></a></code> creates a widget to display and pick a date with time with no specific time zone information.</p> + +<pre class="brush: html notranslate"><input type="datetime-local" name="datetime" id="datetime"></pre> + +<h3 id="month"><code>month</code></h3> + +<p><code><a href="/en-US/docs/Web/HTML/Element/input/month"><input type="month"></a></code> creates a widget to display and pick a month with a year.</p> + +<pre class="brush: html notranslate"><input type="month" name="month" id="month"></pre> + +<h3 id="time"><code>time</code></h3> + +<p><code><a href="/en-US/docs/Web/HTML/Element/input/time"><input type="time"></a></code> creates a widget to display and pick a time value. While time may <em>display</em> in 12-hour format, the <em>value returned</em> is in 24-hour format.</p> + +<pre class="brush: html notranslate"><input type="time" name="time" id="time"></pre> + +<h3 id="week"><code>week</code></h3> + +<p><code><a href="/en-US/docs/Web/HTML/Element/input/week"><input type="week"></a></code> creates a widget to display and pick a week number and its year.</p> + +<p>Weeks start on Monday and run to Sunday. Additionally, the first week 1 of each year contains the first Thursday of that year—which may not include the first day of the year, or may include the last few days of the previous year.</p> + +<pre class="brush: html notranslate"><input type="week" name="week" id="week"></pre> + +<h3 id="Constraining_datetime_values">Constraining date/time values</h3> + +<p>All date and time controls can be constrained using the <code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code> and <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code> attributes, with further constraining possible via the <code><a href="/en-US/docs/Web/HTML/Attributes/step">step</a></code> attribute (whose value varies according to input type).</p> + +<pre class="brush: html notranslate"><label for="myDate">When are you available this summer?</label> +<input type="date" name="myDate" min="2013-06-01" max="2013-08-31" step="7" id="myDate"></pre> + +<h3 id="Browser_support_for_datetime_inputs">Browser support for date/time inputs</h3> + +<p>You should be warned that the date and time widgets don't have the best browser support. At the moment, Chrome, Edge, and Opera support them well, but there is no support in Internet Explorer, Safari has some mobile support (but no desktop support), and Firefox supports <code>time</code> and <code>date</code> only.</p> + +<p>The reference pages linked to above provide suggestions on how to program fallbacks for non-supporting browsers; another option is to consider using a JavaScript library to provide a date picker. Most modern frameworks have good components available to provide this functionality, and there are standalone libraries available to (see <a href="https://flatlogic.com/blog/best-javascript-date-picker-libraries/">Top date picker javascript plugins and libraries</a> for some suggestions).</p> + +<h2 id="Color_picker_control">Color picker control</h2> + +<p>Colors are always a bit difficult to handle. There are many ways to express them: RGB values (decimal or hexadecimal), HSL values, keywords, etc.</p> + +<p>A <code>color</code> control can be created using the {{HTMLElement("input")}} element with its {{htmlattrxref("type","input")}} attribute set to the value <code>color</code>:</p> + +<pre class="brush: html notranslate"><input type="color" name="color" id="color"></pre> + +<p>When supported, clicking a color control will tend to display the operating system's default color picking functionality for you to actually make your choice with. The following screenshot taken on Firefox for macOS provides an example:</p> + +<p><img alt="firefox for android email keyboard, with ampersand displayed by default." src="https://mdn.mozillademos.org/files/17058/fx-macos-color.jpg" style="border-style: solid; border-width: 1px; display: block; height: 412px; margin: 0px auto; width: 700px;"></p> + +<p>And here is a live example for you to try out:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/forms/color-example/index.html", '100%', 200)}}</p> + +<p>The value returned is always a lowercase 6-value hexidecimal color.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: <code>color</code> inputs are not supported in Internet Explorer.</p> +</div> + +<h2 id="Summary">Summary</h2> + +<p>That brings us to the end of our tour of the HTML5 form input types. There are a few other control types that cannot be easily grouped together due to their very specific behaviors, but which are still essential to know about. We cover those in the next article.</p> + +<p>{{PreviousMenuNext("Learn/Forms/Basic_native_form_controls", "Learn/Forms/Other_form_controls", "Learn/Forms")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/Your_first_form">Your first form</a></li> + <li><a href="/en-US/docs/Learn/Forms/How_to_structure_a_web_form">How to structure a web form</a></li> + <li><a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">Basic native form controls</a></li> + <li><a href="/en-US/docs/Learn/Forms/HTML5_input_types">The HTML5 input types</a></li> + <li><a href="/en-US/docs/Learn/Forms/Other_form_controls">Other form controls</a></li> + <li><a href="/en-US/docs/Learn/Forms/Styling_web_forms">Styling web forms</a></li> + <li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Advanced form styling</a></li> + <li><a href="/en-US/docs/Learn/Forms/UI_pseudo-classes">UI pseudo-classes</a></li> + <li><a href="/en-US/docs/Learn/Forms/Form_validation">Client-side form validation</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">Sending form data</a></li> +</ul> + +<h3 id="Advanced_Topics">Advanced Topics</h3> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_controls">How to build custom form controls</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript">Sending forms through JavaScript</a></li> + <li><a href="/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_widgets">Property compatibility table for form widgets</a></li> +</ul> diff --git a/files/es/learn/html/forms/validacion_formulario_datos/index.html b/files/es/learn/html/forms/validacion_formulario_datos/index.html new file mode 100644 index 0000000000..e967b68973 --- /dev/null +++ b/files/es/learn/html/forms/validacion_formulario_datos/index.html @@ -0,0 +1,845 @@ +--- +title: Validación de formularios de datos +slug: Learn/HTML/Forms/Validacion_formulario_datos +tags: + - Ejemplo + - Guía + - HTML + - Intermedio + - JavaScript + - Web + - formulários +translation_of: Learn/Forms/Form_validation +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Forms/UI_pseudo-classes", "Learn/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}</div> + +<p>Antes de enviar datos al servidor, es importante asegurarse de que se completan todos los controles de formulario requeridos, y en el formato correcto. Esto se denomina <strong>validación de formulario en el lado del cliente</strong> y ayuda a garantizar que los datos que se envían coinciden con los requisitos establecidos en los diversos controles de formulario. Este artículo te guiará por los conceptos básicos y ejemplos de validación de formularios en el lado del cliente.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, y entender cómo funcionan el <a href="/es/docs/Learn/HTML">HTML</a>, el <a href="/es/docs/Learn/CSS">CSS</a> y el <a href="/es/docs/Learn/JavaScript">JavaScript</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender qué es la validación de formularios en el lado del cliente, porqué es importante y cómo aplicar diversas técnicas para implementarla.</td> + </tr> + </tbody> +</table> + +<p>La validación en el lado del cliente es una verificación inicial y una característica importante para garantizar una buena experiencia de usuario; mediante la detección de datos no válidos en el lado del cliente, el usuario puede corregirlos de inmediato. Si el servidor lo recibe y, a continuación, lo rechaza; se produce un retraso considerable en la comunicación entre el servidor y el cliente que insta al usuario a corregir sus datos.</p> + +<p>Sin embargo, ¡la validación en el lado del cliente <em>no debe considerarse </em> una medida de seguridad exhaustiva! Tus aplicaciones siempre deben realizar comprobaciones de seguridad de los datos enviados por el formulario <em>en el lado del servidor</em>, <strong>así como también</strong> en el lado del cliente, porque la validación en el lado del cliente es demasiado fácil de evitar, por lo que los usuarios malintencionados pueden enviar fácilmente datos incorrectos a tu servidor. Lee <a href="/es/docs/Learn/Server-side/Primeros_pasos/seguridad_sitios_web">Seguridad en los sitios web</a> para ver qué <em>podría</em> suceder. Cómo implementar la validación en el lado del servidor está fuera del alcance de este módulo, pero debes tenerlo en cuenta.</p> + +<h2 id="¿Qué_es_la_validación_de_formularios">¿Qué es la validación de formularios?</h2> + +<p>Ve a cualquier sitio web popular que incluya un formulario de registro y observa que proporcionan comentarios cuando no introduces tus datos en el formato que se espera. Recibirás mensajes como:</p> + +<ul> + <li>«Este campo es obligatorio» (No se puede dejar este campo en blanco).</li> + <li>«Introduzca su número de teléfono en el formato xxx-xxxx» (Se requiere un formato de datos específico para que se considere válido).</li> + <li>«Introduzca una dirección de correo electrónico válida» (los datos que introdujiste no están en el formato correcto).</li> + <li>«Su contraseña debe tener entre 8 y 30 caracteres y contener una letra mayúscula, un símbolo y un número». (Se requiere un formato de datos muy específico para tus datos).</li> +</ul> + +<p>Esto se llama <strong>validación de formulario</strong>. Cuando introduces los datos, el navegador y/o el servidor web verifican que estén en el formato correcto y dentro de las restricciones establecidas por la aplicación. La validación realizada en el navegador se denomina validación <strong>en el lado del cliente</strong>, mientras que la validación realizada en el servidor se denomina validación <strong>en el lado del servidor</strong>. En este capítulo nos centraremos en la validación en el lado del cliente.</p> + +<p>Si la información está en el formato correcto, la aplicación permite que los datos se envíen al servidor y (en general) que se guarden en una base de datos; si la información no está en el formato correcto, da al usuario un mensaje de error que explica lo que debe corregir y le permite volver a intentarlo.</p> + +<p>Queremos que completar formularios web sea lo más fácil posible. Entonces, ¿por qué insistimos en validar nuestros formularios? Hay tres razones principales:</p> + +<ul> + <li><strong>Queremos obtener los datos correctos en el formato correcto.</strong> Nuestras aplicaciones no funcionarán correctamente si los datos de nuestros usuarios se almacenan en el formato incorrecto, son incorrectos o se omiten por completo.</li> + <li><strong>Queremos proteger los datos de nuestros usuarios</strong>. Obligar a nuestros usuarios a introducir contraseñas seguras facilita proteger la información de su cuenta.</li> + <li><strong>Queremos protegernos a nosotros mismo</strong>. Hay muchas formas en que los usuarios maliciosos puedan usar mal los formularios desprotegidos y dañar la aplicación (consulta <a href="/es/docs/Learn/Server-side/Primeros_pasos/seguridad_sitios_web">Seguridad del sitio web</a>).</li> +</ul> + +<div class="warning"><strong>Atención:</strong> No confíes nunca en los datos que se pasan al servidor desde el cliente. Incluso si tu formulario se valida correctamente y evita la introducción de datos con formato incorrecto en el lado del cliente, un usuario malintencionado puede alterar la petición de red.</div> + +<h2 id="Diferentes_tipos_de_validación_en_el_lado_del_cliente">Diferentes tipos de validación en el lado del cliente</h2> + +<p>Hay dos tipos diferentes de validación por parte del cliente que encontrarás en la web:</p> + +<ul> + <li>La <strong>validación de formularios incorporada</strong> utiliza características de validación de formularios HTML5, que hemos visto en muchos lugares a lo largo de este módulo. Esta validación generalmente no requiere mucho JavaScript. La validación de formularios incorporada tiene un mejor rendimiento que JavaScript, pero no es tan personalizable como la validación con JavaScript.</li> + <li>La <strong>validación con JavaScript</strong> se codifica utilizando JavaScript. Esta validación es completamente personalizable, pero debes crearlo todo (o usar una biblioteca).</li> +</ul> + +<h2 id="Usar_la_validación_de_formulario_incorporada">Usar la validación de formulario incorporada</h2> + +<p>Una de las características más importantes de los <a href="/en-US/docs/Learn/Forms/HTML5_input_types">controles de formulario de HTML5</a> es la capacidad de validar la mayoría de los datos de usuario sin depender de JavaScript. Esto se realiza mediante el uso de atributos de validación en los elementos del formulario. Los hemos visto anteriormente en el curso, pero recapitulamos aquí:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/HTML/Attributes/required">required</a></code>: Especifica si un campo de formulario debe completarse antes de que se pueda enviar el formulario.</li> + <li><code><a href="/en-US/docs/Web/HTML/Attributes/minlength">minlength</a></code> y <code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>: Especifican la longitud mínima y máxima de los datos de texto (cadenas).</li> + <li><code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code> y <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code>: Especifican los valores mínimo y máximo de los tipos de entrada numéricos.</li> + <li><code>type</code>: Especifica si los datos deben ser un número, una dirección de correo electrónico o algún otro tipo de preajuste específico. </li> + <li><code><a href="/en-US/docs/Web/HTML/Attributes/pattern">pattern</a></code>: Especifica una <a href="/es/docs/Web/JavaScript/Guide/Regular_Expressions">expresión regular</a> que define un patrón que los datos que se introduzcan deben seguir.</li> +</ul> + +<p>Si los datos que se introducen en un campo de formulario siguen todas las reglas que especifican los atributos anteriores, se consideran válidos. Si no, se consideran no válidos.</p> + +<p>Cuando un elemento es válido, se cumplen los aspectos siguientes:</p> + +<ul> + <li>El elemento coincide con la pseudoclase {{cssxref(":valid")}} de CSS, lo que te permite aplicar un estilo específico a los elementos válidos.</li> + <li>Si el usuario intenta enviar los datos, el navegador envía el formulario siempre que no haya nada más que lo impida (por ejemplo, JavaScript).</li> +</ul> + +<p>Cuando un elemento no es válido, se cumplen los aspectos siguientes:</p> + +<ul> + <li>El elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS, y a veces con otras pseudoclases de interfaz de usuario (UI) –por ejemplo, {{cssxref(":out-of-range")}}– dependiendo del error, que te permite aplicar un estilo específico a elementos no válidos.</li> + <li>Si el usuario intenta enviar los datos, el navegador bloquea el formulario y muestra un mensaje de error.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Hay varios errores que evitan que el formulario se envíe, incluidos {{domxref('validityState.badInput', 'badInput')}}, {{domxref('validityState.patternMismatch','patternMismatch')}}, {{domxref('validityState.rangeOverflow','rangeOverflow')}} o {{domxref('validityState.rangeUnderflow','rangeUnderflow')}}, {{domxref('validityState.stepMismatch','stepMismatch')}}, {{domxref('validityState.tooLong','tooLong')}} o {{domxref('validityState.tooShort','tooShort')}}, {{domxref('validityState.typeMismatch','typeMismatch')}}, {{domxref('validityState.valueMissing','valueMissing')}} o {{domxref('validityState.customError','customError')}}.</p> +</div> + +<h2 id="Ejemplos_de_validación_de_formularios_incorporados">Ejemplos de validación de formularios incorporados</h2> + +<p>En esta sección probaremos algunos de los atributos que hemos comentado antes.</p> + +<h3 id="Archivo_de_inicio_sencillo">Archivo de inicio sencillo</h3> + +<p>Vamos a empezar con un ejemplo sencillo: una entrada que te permite elegir si prefieres un plátano o una cereza. Este ejemplo implica una simple entrada ({{HTMLElement("input")}}) de texto con una etiqueta ({{htmlelement("label")}}) asociada y un botón de envío ({{htmlelement ("button")}}). Puedes encontrar el código fuente en GitHub en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a> y el ejemplo en vivo a continuación.</p> + +<pre class="brush: html notranslate"><form> + <label for="choose">¿Prefieres un plátano o una cereza?</label> + <input id="choose" name="i_like"> + <button>Enviar</button> +</form></pre> + +<pre class="brush: css notranslate">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +}</pre> + +<p>{{EmbedLiveSample("Archivo_de_inicio_sencillo", "100%", 80)}}</p> + +<p>Para empezar, haz una copia de <code>fruit-start.html</code> en un nuevo directorio de tu disco duro.</p> + +<h3 id="El_atributo_required">El atributo <code>required</code></h3> + +<p>La característica de validación de HTML5 más simple es el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/required">required</a></code>. Añade este atributo al elemento para que una entrada sea obligatoria. Cuando se establece este atributo, el elemento coincide con la pseudoclase de la interfaz de usuario {{cssxref(':required')}} y el formulario no se envía; muestra un mensaje de error al enviarlo si la entrada está vacía. Si está vacía, la entrada también se considera inválida, coincidiendo con la pseudoclase de interfaz de usuario {{cssxref(':invalid')}}.</p> + +<p>Añade un atributo <code>required</code> a tu entrada, como se muestra a continuación.</p> + +<pre class="brush: html notranslate"><form> + <label for="choose">¿Prefieres un plátano o una cereza? (requerido) </label> + <input id="choose" name="i_like" <strong>required</strong>> + <button>Enviar</button> +</form></pre> + +<p>Ten en cuenta el CSS que en el archivo de ejemplo se ha incluido:</p> + +<pre class="brush: css notranslate">input:invalid { + border: 2px dashed red; +} + +input:invalid:required { + background-image: linear-gradient(to right, pink, lightgreen); +} + +input:valid { + border: 2px solid black; +}</pre> + +<p>Este CSS da un borde discontinuo rojo cuando la entrada no es válida, y un borde negro sólido más sutil cuando es válida. También añadimos un gradiente de fondo cuando la entrada es obligatoria <em>y</em> no válida. Prueba el nuevo comportamiento en el ejemplo siguiente:</p> + +<p>{{EmbedLiveSample("El_atributo_required", "100%", 80)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-required.html">fruit-validation.html</a> (consulta también el <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-required.html">código fuente</a>).</p> +</div> + +<p>Intenta enviar el formulario sin introducir ningún valor. Observa que la entrada no válida recibe el cursor, aparece un mensaje de error predeterminado («Complete este campo») y el formulario no se puede enviar.</p> + +<p>La presencia del atributo <code>required</code> en cualquier elemento que admite este atributo significa que el elemento coincide con la pseudoclase {{cssxref(':required')}}, tenga o no un valor. Si en el elemento {{HTMLElement("input")}} no se ha introducido ningún valor, <code>input</code> coincidirá con la pseudoclase {{cssxref(':invalid')}}.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Para una buena experiencia de usuario, indica al usuario que campos de formulario se requieren. No solo es una buena experiencia de usuario, sino que lo exigen las pautas de <a href="/es/docs/Learn/Accessibility">accesibilidad</a> de WCAG. Además, solo requiere que los usuarios introduzcan los datos que realmente necesitas: Por ejemplo, ¿por qué realmente necesitas saber el género o el tratamiento de alguien?</p> +</div> + +<h3 id="Validación_de_una_expresión_regular">Validación de una expresión regular</h3> + +<p>Otra característica útil de validación es el atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>, que espera una <a href="/es/docs/Web/JavaScript/Guide/Regular_Expressions">expresión regular</a> como valor. Una expresión regular (<em>regex</em>) es un patrón que se puede usar para establecer combinaciones de caracteres en cadenas de texto, por lo que las expresiones regulares son ideales para la validación de formularios y sirven para una gran variedad de otros usos en JavaScript.</p> + +<p>Las expresiones regulares son bastante complejas y no vamos a exponerlas exhaustivamente en este artículo. A continuación hay algunos ejemplos para que te hagas una idea de cómo funcionan.</p> + +<ul> + <li><code>a</code>: coincide con un carácter que es <code>a</code> (ni <code>b</code>, ni <code>aa</code>, etc.).</li> + <li><code>abc</code>: coincide con <code>a</code>, seguido de <code>b</code>, seguido de <code>c</code>.</li> + <li><code>ab?c</code>: coincide con <code>a</code>, seguida opcionalmente de una sola <code>b</code>, seguida de <code>c</code> (<code>ac</code> o <code>abc</code>).</li> + <li><code>ab*c</code>: coincide con <code>a</code>, seguido opcionalmente de cualquier número de <code>b</code>, seguido de <code>c</code>. (<code>ac</code>, <code>abc</code>, <code>abbbbbc</code>, etc.)</li> + <li><code>a|b</code>: coincide con un carácter que es <code>a</code> o <code>b</code>.</li> + <li><code>abc|xyz</code>: coincide exactamente con <code>abc</code> o <code>xyz</code> (pero no con <code>abcxyz</code> <code>a</code> o <code>y</code>, y así sucesivamente).</li> +</ul> + +<p>Hay muchas más posibilidades que no exponemos aquí. Para obtener una lista completa y muchos ejemplos, consulta nuestro documento de <a href="/es/docs/Web/JavaScript/Guide/Regular_Expressions">expresiones regulares</a>.</p> + +<p>Implementemos un ejemplo. Actualiza tu HTML para añadir un atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a> como este:</p> + +<pre class="brush: html notranslate"><form> + <label for="choose">¿Prefieres un plátano o una cereza?</label> + <input id="choose" name="i_like" required pattern="[Pp]látano|[Cc]ereza "> + <button>Enviar</button> +</form> +</pre> + +<div class="hidden"> +<pre class="brush: css notranslate">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +}</pre> +</div> + +<p>Esto nos da la siguiente actualización; pruébalo:</p> + +<p>{{EmbedLiveSample("Validación de una expresión regular", "100%", 80)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-pattern.html">fruit-pattern.html</a> (consulta también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-pattern.html">código fuente</a>).</p> +</div> + +<p>En este ejemplo, el elemento {{HTMLElement("input")}} acepta uno de los cuatro valores posibles: las cadenas «plátano», «Plátano», «cereza» o «Cereza». Las expresiones regulares distinguen entre mayúsculas y minúsculas, pero hemos hecho que admita versiones en mayúsculas y minúsculas utilizando un patrón «Aa» adicional anidado dentro de corchetes.</p> + +<p>En este punto, intenta cambiar el valor dentro del atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a> para que se vean iguales que algunos de los ejemplos vistos anteriormente, y observa que esto afecta a los valores que puedes añadir para que el valor de entrada sea válido. Intenta escribir algo por tu cuenta y mira cómo va. ¡Haz que estén relacionadas con la fruta siempre que sea posible para que tus ejemplos tengan sentido!</p> + +<p>Si un valor no vacío de {{HTMLElement("input")}} no coincide con el patrón de la expresión regular, <code>input</code> coincidirá con la pseudoclase {{cssxref(':invalid')}}.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Algunos tipos de elementos {{HTMLElement ("input")}} no necesitan validar una expresión regular con el atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>. Especificar el tipo de correo electrónico (<code>email</code>), por ejemplo, valida el valor de las entradas con un patrón de dirección de correo electrónico bien formado o un patrón que coincida con una lista de direcciones de correo electrónico separadas por comas si tiene el atributo <a href="/en-US/docs/Web/HTML/Attributes/multiple"><code>multiple</code></a>.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: El elemento {{HTMLElement("textarea")}} no admite el atributo <a href="/en-US/docs/Web/HTML/Attributes/pattern"><code>pattern</code></a>.</p> +</div> + +<h3 id="Restringir_la_longitud_de_tus_entradas">Restringir la longitud de tus entradas</h3> + +<p>Puedes restringir la longitud de los caracteres de todos los campos de texto creados por {{HTMLElement("input")}} o {{HTMLElement("textarea")}} utilizando los atributos <a href="/en-US/docs/Web/HTML/Attributes/minlength"><code>minlength</code></a> y <code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>. Un campo no es válido si tiene un valor y ese valor tiene menos caracteres que el valor de longitud mínima (<a href="/en-US/docs/Web/HTML/Attributes/minlength"><code>minlength</code></a>), o más que el valor de longitud máxima (<code><a href="/en-US/docs/Web/HTML/Attributes/maxlength">maxlength</a></code>).</p> + +<p>Los navegadores a menudo no permiten que el usuario escriba un valor más largo de lo esperado en los campos de texto. Lo que otorga una mejor experiencia de usuario que <code>maxlength</code> es proporcionar comentarios de recuento de caracteres de manera accesible y permitirles editar su contenido a un tamaño más reducido. Un ejemplo de esto es el límite de caracteres de Twitter. JavaScript, incluidas las <a href="https://github.com/mimo84/bootstrap-maxlength">soluciones que utilizan <code>maxlength</code></a>, se puede utilizar para proporcionar esta funcionalidad.</p> + +<h3 id="Restringir_los_valores_de_tus_entradas">Restringir los valores de tus entradas</h3> + +<p>Los atributos <code><a href="/en-US/docs/Web/HTML/Attributes/min">min</a></code> y <code><a href="/en-US/docs/Web/HTML/Attributes/max">max</a></code> se pueden usar para proporcionar a los campos numéricos (es decir, <code><a href="/en-US/docs/Web/HTML/Element/input/number"><input type="number"></a></code>) un rango de valores válidos. El campo no será válido si contiene un valor fuera de este rango.</p> + +<p>Veamos otro ejemplo. Crea una nueva copia del archivo <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a>.</p> + +<p>Ahora elimina el contenido del elemento <code><body></code> y reemplázalo con lo siguiente:</p> + +<pre class="brush: html notranslate"><form> + <div> + <label for="choose">¿Prefieres un plátano o una cereza?</label> + <input type="text" id="choose" name="i_like" required minlength="6" maxlength="6"> + </div> + <div> + <label for="number">¿Cuántos te gustaría comer?</label> + <input type="number" id="number" name="amount" value="1" min="1" max="10"> + </div> + <div> + <button>Enviar</button> + </div> +</form></pre> + +<ul> + <li>Aquí verás que le hemos dado al campo de <code>text</code> unos valores <code>minlength</code> y <code>maxlength</code> de seis, que es la misma longitud que tienen el plátano y la cereza.</li> + <li>También le hemos dado al campo <code>number</code> un <code>min</code> de uno y un <code>max</code> de diez. Los números introducidos que queden fuera de este rango se mostrarán como no válidos; los usuarios no podrán usar las flechas de incremento/decremento para mover el valor fuera de este rango. Si el usuario introduce un número desde el teclado fuera de este rango, los datos no serán válidos. El número no es obligatorio, por lo que eliminar el valor aún dará como resultado un valor válido.</li> +</ul> + +<div class="hidden"> +<pre class="brush: css notranslate">input:invalid { + border: 2px dashed red; +} + +input:valid { + border: 2px solid black; +} + +div { + margin-bottom: 10px; +}</pre> +</div> + +<p>Aquí está el ejemplo que se ejecuta en vivo:</p> + +<p>{{EmbedLiveSample("Restringir_los_valores_de_tus_entradas", "100%", 100)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/fruit-length.html">fruit-length.html</a> (consulta también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-length.html">código fuente</a>).</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: <code><input type="number"></code> (y otros tipos, como <code>range</code> y <code>date</code>) también pueden tomar un atributo <a href="/en-US/docs/Web/HTML/Attributes/step"><code>step</code></a>, que especifica en qué incremento aumenta o disminuye el valor cuando se utilizan los controles de entrada (como el botones numéricos arriba y abajo). En el ejemplo anterior no hemos incluido un atributo <code>step</code>, por lo que el valor predeterminado es <code>1</code>. Esto significa que los valores de coma flotante, como 3.2, también se mostrarán como no válidos.</p> +</div> + +<h3 id="Ejemplo_completo">Ejemplo completo</h3> + +<p>Aquí hay un ejemplo completo que muestra el uso de las funciones de validación integradas en HTML. En primer lugar, un poco de HTML:</p> + +<pre class="brush: html notranslate"><form> + <p> + <fieldset> + <legend>¿Tienes carné de conducir?<abbr title="Este campo es obligatorio" aria-label="required">*</abbr></legend> + <!-- Solo se puede seleccionar un botón de opción en un grupo con el mismo nombre, + y, por lo tanto, solo un botón de opción en un grupo con el mismo nombre que tiene marcado el atributo «requerido» + basta para hacer de una selección un requisito --> + <input type="radio" required name="driver" id="r1" value="yes"><label for="r1">Sí</label> + <input type="radio" required name="driver" id="r2" value="no"><label for="r2">No</label> + </fieldset> + </p> + <p> + <label for="n1">¿Qué edad tienes?</label> + <!-- El atributo pattern puede actuar como una alternativa para los navegadores que + no implementan el tipo de entrada de número, pero admiten el atributo pattern. + Ten en cuenta que los navegadores que admiten el atributo pattern lo harán + fallar silenciosamente cuando se use con un campo numérico. + Su uso aquí solo actúa como una alternativa --> + <input type="number" min="12" max="120" step="1" id="n1" name="age" + pattern="\d+"> + </p> + <p> + <label for="t1">¿Cuál es tu fruta favorita?<abbr title="Este campo es obligatorio" aria-label="required">*</abbr></label> + <input type="text" id="t1" name="fruit" list="l1" required + pattern="[Bb]anana|[Cc]herry|[Aa]pple|[Ss]trawberry|[Ll]emon|[Oo]range "> + <datalist id="l1"> + <option>Plátano</option> + <option>Cereza</option> + <option>Manzana</option> + <option>Fresa</option> + <option>Limón</option> + <option>Naranja</option> + </datalist> + </p> + <p> + <label for="t2">¿Cuál es tu dirección de correo electrónico? </label> + <input type="email" id="t2" name="email"> + </p> + <p> + <label for="t3">Deja un mensaje</label> + <textarea id="t3" name="msg" maxlength="140" rows="5"></textarea> + </p> + <p> + <button>Enviar</button> + </p> +</form></pre> + +<p>Y ahora, algo de CSS para añadir estilo al HTML:</p> + +<pre class="brush: css notranslate">form { + font: 1em sans-serif; + max-width: 320px; +} + +p > label { + display: block; +} + +input[type="text"], +input[type="email"], +input[type="number"], +textarea, +fieldset { + width : 100%; + border: 1px solid #333; + box-sizing: border-box; +} + +input:invalid { + box-shadow: 0 0 5px 1px red; +} + +input:focus:invalid { + box-shadow: none; +}</pre> + +<p>Esto se traduce de la siguiente manera:</p> + +<p>{{EmbedLiveSample("Ejemplo_completo", "100%", 420)}}</p> + +<p>Consulta <a href="/es/docs/HTML/HTML5/Validacion_de_restricciones#Atributos_relacionados_con_validaciones">Atributos relacionados con la validación</a> para obtener una lista completa de los atributos que se pueden usar para restringir los valores de entrada y los tipos de entrada que los admiten.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/full-example.html">full-example.html</a> (consulta también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/full-example.html">código fuente</a>).</p> +</div> + +<h2 id="Validar_formularios_utilizando_JavaScript">Validar formularios utilizando JavaScript</h2> + +<p>Debes usar JavaScript si quieres controlar la apariencia de los mensajes de error nativos o tratar con navegadores heredados que no admiten la validación de formularios incorporados en HTML. En esta sección veremos las diferentes formas de hacer esto.</p> + +<h3 id="La_API_de_validación_de_restricciones">La API de validación de restricciones</h3> + +<p>La mayoría de los navegadores admiten la <a href="/en-US/docs/Web/API/Constraint_validation">API de validación de restricciones</a>, que consta de un conjunto de métodos y propiedades disponibles en las interfaces DOM de elementos de formulario siguientes:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/API/HTMLButtonElement">HTMLButtonElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/button"><button></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLFieldSetElement">HTMLFieldSetElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/fieldset"><fieldset></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLInputElement">HTMLInputElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/input"><input></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLOutputElement">HTMLOutputElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/output"><output></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLSelectElement">HTMLSelectElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/select"><select></a></code>)</li> + <li><code><a href="/en-US/docs/Web/API/HTMLTextAreaElement">HTMLTextAreaElement</a></code> (representa un elemento <code><a href="/en-US/docs/Web/HTML/Element/textarea"><textarea></a></code>)</li> +</ul> + +<p id="Constraint_validation_API_properties">La API de validación de restricciones hace que las propiedades siguientes estén disponibles en los elementos anteriores.</p> + +<ul> + <li><code>validationMessage</code>: Devuelve un mensaje localizado que describe las restricciones de validación que el control no satisface (si corresponde). Si el control no es candidato para la validación de restricciones (<code>willValidate</code> es <code>false</code>) o el valor del elemento satisface sus restricciones (es válido), esto devolverá una cadena vacía.</li> + <li><code>validity</code>: Devuelve un objeto <code>ValidityState</code> que contiene varias propiedades que describen el estado de validez del elemento. Puedes encontrar todos los detalles de todas las propiedades disponibles en la página de referencia {{domxref("ValidityState")}}; a continuación se enumeran algunos de los más comunes: + <ul> + <li>{{domxref("ValidityState.patternMismatch", "patternMismatch")}}: Devuelve <code>true</code> si el valor no coincide con el {{htmlattrxref("pattern", "input")}} especificado, y <code>false</code> si coincide. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + <li>{{domxref("ValidityState.tooLong", "tooLong")}}: Devuelve <code>true</code> si el valor es mayor que la longitud máxima especificada por el atributo {{htmlattrxref("maxlength", "input")}}, o <code>false</code> si es menor o igual al máximo. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + <li>{{domxref("ValidityState.tooShort", "tooShort")}}: Devuelve <code>true</code> si el valor es menor que la longitud mínima especificada por el atributo {{htmlattrxref("minlength", "input")}}, o <code>false</code> si es mayor o igual al mínmo. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + <li>{{domxref("ValidityState.rangeOverflow", "rangeOverflow")}}: Devuelve <code>true</code> si el valor es mayor que el máximo especificado por el atributo {{htmlattrxref("max", "input")}}, o <code>false</code> si es menor o igual que el máximo. Si es verdadero, el elemento coincide con las pseudoclases {{cssxref(":invalid")}} y {{cssxref(":out-of-range")}} de CSS.</li> + <li>{{domxref("ValidityState.rangeUnderflow", "rangeUnderflow")}}: Devuelve <code>true</code> si el valor es menor que el mínimo especificado por el atributo {{htmlattrxref("min", "input")}}, o <code>false</code> si es mayor o igual que el mínimo. Si es verdadero, el elemento coincide con las pseudoclases {{cssxref(":invalid")}} y {{cssxref(":out-of-range")}} de CSS.</li> + <li>{{domxref("ValidityState.typeMismatch", "typeMismatch")}}: Devuelve <code>true</code> si el valor no está en la sintaxis requerida (cuando {{htmlattrxref("type", "input")}} es <code>email</code> o <code>url</code>), o <code>false</code> si la sintaxis es correcta. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + <li><code>valid</code>: Devuelve <code>true</code> si el elemento cumple con todas sus restricciones de validación y por lo tanto se considera válido, o <code>false</code> si falla alguna restricción. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":valid")}} de CSS; o con la pseudoclase {{cssxref(":invalid")}} de CSS de lo contrario.</li> + <li><code>valueMissing</code>: Devuelve <code>true</code> si el elemento tiene un atributo {{htmlattrxref("required", "input")}} pero no tiene valor, o <code>false</code> de lo contrario. Si es verdadero, el elemento coincide con la pseudoclase {{cssxref(":invalid")}} de CSS.</li> + </ul> + </li> + <li><code>willValidate</code>: Devuelve <code>true</code> si el elemento se valida cuando se envía el formulario; <code>false</code> de lo contrario.</li> +</ul> + +<p id="Constraint_validation_API_methods">La API de validación de restricciones también pone a disposición los siguientes métodos en los elementos anteriores.</p> + +<ul> + <li><code>checkValidity()</code>: Devuelve <code>true</code> si el valor del elemento no tiene problemas de validez; <code>false</code> en caso contrario. Si el elemento no es válido, este método también activa un <a href="/es/docs/Web/API/HTMLInputElement/invalid_event">evento <code>invalid</code></a> en el elemento.</li> + <li><code>setCustomValidity(<em>message</em>)</code>: Añade un mensaje de error personalizado al elemento; si configuras un mensaje de error personalizado, el elemento se considera no válido y se muestra el error especificado. Esto te permite utilizar el código JavaScript para establecer un fallo de validación distinto de los ofrecidos por las restricciones estándar de validación de HTML5. El mensaje se muestra al usuario cuando se informa del problema.</li> +</ul> + +<h4 id="Implementar_un_mensaje_de_error_personalizado">Implementar un mensaje de error personalizado</h4> + +<p>Como has visto en los ejemplos de restricciones de validación de HTML5 anteriores, cada vez que un usuario intenta enviar un formulario no válido, el navegador muestra un mensaje de error. La forma en que se muestra este mensaje depende del navegador.</p> + +<p>Estos mensajes automatizados tienen dos inconvenientes:</p> + +<ul> + <li>No hay una forma estándar de cambiar su aspecto con CSS.</li> + <li>Dependen de la configuración regional del navegador, lo que significa que puedes tener una página en un idioma pero un mensaje de error en otro idioma, como se ve en la siguiente captura de pantalla de Firefox.</li> +</ul> + +<p><img alt="Ejemplo de un mensaje de error en francés en una página de Firefox en inglés" src="/files/4329/error-firefox-win7.png" style="height: 97px; width: 228px;"></p> + +<p>La personalización de estos mensajes de error es uno de los casos de uso más comunes de la <a href="/en-US/docs/Web/API/Constraint_validation" rel="external">API de validación de restricciones</a>. Veamos un ejemplo simple de cómo hacer esto.</p> + +<p>Comenzaremos con un HTML simple (siéntete libre de poner esto en un archivo HTML en blanco; usa una copia nueva de <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/fruit-start.html">fruit-start.html</a> como base, si lo deseas):</p> + +<pre class="brush: html notranslate"><form> + <label for="mail">Me gustaría que me proporcionara una dirección de correo electrónico:<label> + <input type="email" id="mail" name="mail"> + <button>Enviar</button> +</form></pre> + +<p>Y añade a la página el JavaScript siguiente:</p> + +<pre class="brush: js notranslate">const email = document.getElementById("mail"); + +email.addEventListener("input", function (event) { + if (email.validity.typeMismatch) { + email.setCustomValidity("¡Se esperaba una dirección de correo electrónico!"); + } else { + email.setCustomValidity(""); + } +});</pre> + +<p>Aquí guardamos una referencia para la entrada de la dirección de correo electrónico, luego le añadimos un detector de eventos que ejecuta el código de <code>content</code> cada vez que el valor de la entrada cambia.</p> + +<p>Dentro del código que contiene, verificamos si la propiedad <code>validity.typeMismatch</code> de la entrada de la dirección de correo electrónico devuelve <code>true</code>, lo que significa que el valor que contiene no coincide con el patrón para una dirección de correo electrónico bien formada. Si es así, llamamos al método <a href="/es/docs/HTML/HTML5/Validacion_de_restricciones"><code>setCustomValidity()</code></a> con un mensaje personalizado. Esto hace que la entrada no sea válida, de modo que cuando intentas enviar el formulario, el envío falla y se muestra el mensaje de error personalizado.</p> + +<p>Si la propiedad <code>validity.typeMismatch</code> devuelve <code>false</code>, llamamos al método <code>setCustomValidity()</code> con una cadena vacía. Esto hace que la entrada sea válida, y el formulario se envía.</p> + +<p>Puedes probarlo a continuación:</p> + +<p>{{EmbedGHLiveSample("/en-US/learning-area/html/forms/form-validation/custom-error-message.html", '100%', 80)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puede encontrar este ejemplo vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/custom-error-message.html">custom-error-message.html</a> (véase también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/custom-error-message.html">código fuente</a>).</p> +</div> + +<h4 id="Un_ejemplo_más_detallado">Un ejemplo más detallado</h4> + +<p>Ahora que hemos visto un ejemplo realmente sencillo, veamos cómo podemos usar esta API para construir una validación personalizada un poco más compleja.</p> + +<p>En primer lugar, el código HTML. Una vez más, siéntete libre de construir esto junto con nosotros:</p> + +<pre class="brush: html notranslate"><form novalidate> + <p> + <label for="mail"> + <span>Por favor, introduzca una dirección de correo electrónico: </span> + <input type="email" id="mail" name="mail" required minlength="8"> + <span class="error" aria-live="polite"></span> + </label> + </p> + <button>Enviar</button> +</form></pre> + +<p>Este sencillo formulario usa el atributo <code><a href="/en-US/docs/Web/HTML/Attributes/novalidate">novalidate</a></code> para desactivar la validación automática del navegador; esto permite que nuestra secuencia de comandos tome control sobre la validación. Sin embargo, esto no deshabilita la compatibilidad para la API de validación de restricciones ni la aplicación de pseudoclases de CSS como {{cssxref(":valid")}}, etc. Eso significa que, aunque el navegador no verifica automáticamente la validez del formulario antes de enviar los datos, puedes hacerlo tú mismo y diseñar el formulario en consecuencia.</p> + +<p>Nuestra entrada para validar es <code><a href="/es/docs/Web/HTML/Elemento/input/email"><input type="email"></a></code>, que es obligatoria y tiene una longitud mínima (<code>minlength</code>) de 8 caracteres. Vamos a verificar esto con nuestro propio código para que muestre un mensaje de error personalizado para cada elemento.</p> + +<p>Nuestro objetivo es mostrar los mensajes de error dentro de un elemento <code><span></code>. El atributo <a href="/en-US/docs/Accessibility/ARIA/ARIA_Live_Regions"><code>aria-live</code></a> se establece en ese <code><span></code> para asegurar que todo el mundo podrá ver nuestro mensaje de error personalizado, incluidos los usuarios de lectores de pantalla.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Un punto clave a tener en cuenta es que establecer el atributo <code>novalidate</code> en el formulario impide que el formulario muestre sus propios cuadros de diálogo de error, y nos permite mostrar los mensajes de error personalizados en el DOM de la manera que nosotros elijamos.</p> +</div> + +<p>Ahora aplicaremos algo de CSS básico para mejorar ligeramente el aspecto del formulario y proporcionar algunos comentarios visuales cuando los datos de entrada no sean válidos:</p> + +<pre class="brush: css notranslate">body { + font: 1em sans-serif; + width: 200px; + padding: 0; + margin : 0 auto; +} + +p * { + display: block; +} + +input[type=email]{ + -webkit-appearance: none; + appearance: none; + + width: 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + box-sizing: border-box; +} + +/* Este es nuestro diseño para los campos no válidos */ +input:invalid{ + border-color: #900; + background-color: #FDD; +} + +input:focus:invalid { + outline: none; +} + +/* Este es el diseño para nuestros mensajes de error */ +.error { + width : 100%; + padding: 0; + + font-size: 80%; + color: white; + background-color: #900; + border-radius: 0 0 5px 5px; + + box-sizing: border-box; +} + +.error.active { + padding: 0.3em; +}</pre> + +<p>Vamos a ver el JavaScript que implementa la validación de error personalizada.</p> + +<pre class="brush: js notranslate">// Hay muchas formas de elegir un nodo DOM; aquí obtenemos el formulario y, a continuación, el campo de entrada +// del correo electrónico, así como el elemento span en el que colocaremos el mensaje de error. +const form = document.getElementsByTagName('form')[0]; + +const email = document.getElementById('mail'); +const emailError = document.querySelector('#mail + span.error'); + +email.addEventListener('input', function (event) { + // Cada vez que el usuario escribe algo, verificamos si + // los campos del formulario son válidos. + + if (email.validity.valid) { + // En caso de que haya un mensaje de error visible, si el campo + // es válido, eliminamos el mensaje de error. + emailError.innerHTML = ''; // Restablece el contenido del mensaje + emailError.className = 'error'; // Restablece el estado visual del mensaje + } else { + // Si todavía hay un error, muestra el error exacto + showError(); + } +}); + +form.addEventListener('submit', function (event) { + // si el campo de correo electrónico es válido, dejamos que el formulario se envíe + + if(!email.validity.valid) { + // Si no es así, mostramos un mensaje de error apropiado + showError(); + // Luego evitamos que se envíe el formulario cancelando el evento + event.preventDefault(); + } +}); + +function showError() { + if(email.validity.valueMissing) { + // Si el campo está vacío + // muestra el mensaje de error siguiente. + emailError.textContent = 'Debe introducir una dirección de correo electrónico.'; + } else if(email.validity.typeMismatch) { + // Si el campo no contiene una dirección de correo electrónico + // muestra el mensaje de error siguiente. + emailError.textContent = 'El valor introducido debe ser una dirección de correo electrónico.'; + } else if(email.validity.tooShort) { + // Si los datos son demasiado cortos + // muestra el mensaje de error siguiente. + emailError.textContent = 'El correo electrónico debe tener al menos ${ email.minLength } caracteres; ha introducido ${ email.value.length }.'; + } + + // Establece el estilo apropiado + emailError.className = 'error activo'; +}</pre> + +<p>Los comentarios explican las cosas bastante bien, pero de una manera muy breve:</p> + +<ul> + <li>Cada vez que cambiamos el valor de la entrada, verificamos si contiene datos válidos. Si es así, eliminamos cualquier mensaje de error que se muestre. Si los datos no son válidos, ejecutamos <code>showError()</code> para mostrar el error correspondiente.</li> + <li>Cada vez que intentamos enviar el formulario, verificamos nuevamente si los datos son válidos. Si es así, dejamos que envíe el formulario. Si no, ejecutamos <code>showError()</code> para mostrar el error correspondiente y detenemos el envío del formulario con <code><a href="/en-US/docs/Web/API/Event/preventDefault">preventDefault()</a></code>.</li> + <li>La función <code>showError()</code> usa varias propiedades de la entrada <code>validity</code> para determinar cuál es el error y luego muestra un mensaje de error según corresponda.</li> +</ul> + +<p>Este es el resultado:</p> + +<p>{{EmbedGHLiveSample("/en-US/learning-area/html/forms/form-validation/detailed-custom-validation.html", '100%', 150)}}</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes encontrar este ejemplo en vivo en GitHub como <a href="https://mdn.github.io/learning-area/html/forms/form-validation/detailed-custom-validation.html">detailed-custom-validation.html</a> (consulta también su <a href="https://github.com/mdn/learning-area/blob/master/html/forms/form-validation/detailed-custom-validation.html">código fuente</a>).</p> +</div> + +<p>La API de validación de restricciones te proporciona una herramienta poderosa para manejar la validación de formularios, y te permite tener un control enorme sobre la interfaz de usuario más allá de lo que puedas hacer solo con HTML y CSS.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Para obtener más información, consulta nuestra <a href="/es/docs/HTML/HTML5/Validacion_de_restricciones">guía de validación de restricciones</a> y la referencia de <a href="/en-US/docs/Web/API/Constraint_validation">API de validación de restricciones</a>.</p> +</div> + +<h3 id="Validar_formularios_sin_una_API_incorporada">Validar formularios sin una API incorporada</h3> + +<p>En algunos casos, como la compatibilidad heredada del navegador o los <a href="/es/docs/Learn/HTML/Forms/como_crear_widgets_de_formularios_personalizados">controles personalizados</a>, no podrás o no querrás usar la API de validación de restricciones. Todavía puedes usar JavaScript para validar tu formulario, pero vas a tener que escribirlo.</p> + +<p>Antes de validar el formulario, hazte estas preguntas:</p> + +<dl> + <dt>¿Qué tipo de validación debería realizar?</dt> + <dd>Debes determinar cómo validar los datos: operaciones de cadena, conversión de tipos, expresiones regulares, etc. Tú decides.</dd> + <dt>¿Qué debo hacer si el formulario no se valida?</dt> + <dd>Esto es claramente un problema de la interfaz de usuario. Tienes que decidir cómo se comportará el formulario. ¿El formulario va a enviar los datos de todos modos? ¿Deberías resaltar los campos que dan error? ¿Deberías mostrar mensajes de error?</dd> + <dt>¿Cómo puedo ayudar al usuario a corregir datos no válidos?</dt> + <dd>Para reducir la frustración del usuario, es muy importante proporcionar tanta información útil como sea posible para guiarlo a fin de que corrija sus entradas de datos. Debes ofrecer sugerencias por adelantado para que sepan lo que se espera de ellos, así como mensajes de error claros. Si deseas profundizar en los requisitos de interfaz de usuario para la validación de formularios, aquí hay algunos artículos útiles que debes leer: + <ul> + <li>SmashingMagazine: <a href="http://uxdesign.smashingmagazine.com/2012/06/27/form-field-validation-errors-only-approach/" rel="external">Form-Field Validation: The Errors-Only Approach</a> [Validación de campo de formulario: El enfoque de solo errores]</li> + <li>SmashingMagazine: <a href="http://www.smashingmagazine.com/2009/07/07/web-form-validation-best-practices-and-tutorials/" rel="external">Web Form Validation: Best Practices and Tutorials </a> [Validación de formularios web: Buenas prácticas y tutoriales]</li> + <li>Six Revision: <a href="http://sixrevisions.com/user-interface/best-practices-for-hints-and-validation-in-web-forms/" rel="external">Best Practices for Hints and Validation in Web Forms</a> [Buenas prácticas para sugerencias y validación de formularios web]</li> + <li>A List Apart: <a href="http://www.alistapart.com/articles/inline-validation-in-web-forms/" rel="external">Inline Validation in Web Forms</a> [Validación en línea de formularios web]</li> + </ul> + </dd> +</dl> + +<h4 id="Un_ejemplo_que_no_usa_la_API_de_validación_de_restricciones">Un ejemplo que no usa la API de validación de restricciones</h4> + +<p>Para ilustrar esto, mostramos una versión simplificada del ejemplo anterior que funciona con navegadores con compatibilidad heredada.</p> + +<p>El HTML es casi el mismo; solo hemos eliminado las funciones de validación de HTML.</p> + +<pre class="brush: html notranslate"><form> + <p> + <label for="mail"> + <span>Por favor, introduzca una dirección de correo electrónico: </span> + <input type="text" class="mail" id="mail" name="mail"> + <span class="error" aria-live="polite"></span> + </label> + </p> + <!-- Algunos navegadores con compatibilidad heredada deben tener el atributo «type» + establecido explícitamente en el elemento «button» de «submit»--> + <button type="submit">Enviar</button> +</form></pre> + +<p>Del mismo modo, no es necesario cambiar mucho el CSS; acabamos de convertir la pseudoclase {{cssxref(":invalid")}} de CSS en una clase real y evitamos usar el selector de atributos que no funciona en Internet Explorer 6.</p> + +<pre class="brush: css notranslate">body { + font: 1em sans-serif; + width: 200px; + padding: 0; + margin : 0 auto; +} + +form { + max-width: 200px; +} + +p * { + display: block; +} + +input.mail { + -webkit-appearance: none; + + width: 100%; + border: 1px solid #333; + margin: 0; + + font-family: inherit; + font-size: 90%; + + box-sizing: border-box; +} + +/* Este es nuestro diseño para los campos no válidos */ +input.invalid{ + border-color: #900; + background-color: #FDD; +} + +input:focus.invalid { + outline: none; +} + +/* Este es el diseño para nuestros mensajes de error */ +.error { + width : 100%; + padding: 0; + + font-size: 80%; + color: white; + background-color: #900; + border-radius: 0 0 5px 5px; + box-sizing: border-box; +} + +.error.active { + padding: 0.3em; +}</pre> + +<p>Los grandes cambios están en el código JavaScript, que necesita hacer mucho más trabajo pesado.</p> + +<pre class="brush: js notranslate">// Hay menos formas de elegir un nodo DOM con navegadores antiguos +const form = document.getElementsByTagName('form')[0]; +const email = document.getElementById('mail'); + +// Lo siguiente es un truco para llegar al siguiente nodo de elementos hermanos en el DOM +// Esto es peligroso porque puedes construir fácilmente un bucle infinito. +// En los navegadores modernos es mejor usar element.nextElementSibling +let error = email; +while ((error = error.nextSibling).nodeType != 1); + +// según la especificación HTML5 +const emailRegExp = /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/; + +// Muchos navegadores antiguos no son compatibles con el método addEventListener. +// Aquí hay una manera simple de manejar esto; está lejos de ser la única. +function addEvent(element, event, callback) { + let previousEventCallBack = element["on"+event]; + element["on"+event] = function (e) { + const output = callback(e); + + // Una devolución de llamada que devuelve «false» detiene la cadena de devolución de llamada + // e interrumpe la ejecución de la devolución de llamada del evento. + if (output === false) return false; + + if (typeof previousEventCallBack === 'function') { + output = previousEventCallBack(e); + if(output === false) return false; + } + } +}; + +// Ahora podemos reconstruir nuestra restricción de validación +// Debido a que no confiamos en la pseudoclase de CSS, tenemos que +// establecer explícitamente la clase valid/invalid en nuestro campo de correo electrónico +addEvent(window, "load", function () { + // Aquí probamos si el campo está vacío (recuerda, el campo no es obligatorio) + // Si no es así, verificamos si su contenido es una dirección de correo electrónico con el formato correcto. + const test = email.value.length === 0 || emailRegExp.test(email.value); + + email.className = test ? "valid" : "invalid"; +}); + +// Esto define lo que sucede cuando el usuario escribe en el campo +addEvent(email, "input", function () { + const test = email.value.length === 0 || emailRegExp.test(email.value); + if (test) { + email.className = "valid"; + error.innerHTML = ""; + error.className = "error"; + } else { + email.className = "invalid"; + } +}); + +// Esto define lo que sucede cuando el usuario intenta enviar los datos. +addEvent(form, "submit", function () { + const test = email.value.length === 0 || emailRegExp.test(email.value); + + if (!test) { + email.className = "invalid"; + error.innerHTML = "I expect an e-mail, darling!"; + error.className = "error active"; + + // Algunos navegadores antiguos no son compatibles con el método event.preventDefault () + return false; + } else { + email.className = "valid"; + error.innerHTML = ""; + error.className = "error"; + } +});</pre> + +<p>El resultado es el siguiente:</p> + +<p>{{EmbedLiveSample("Validar_formularios_sin_una_API_incorporada", "100%", 130)}}</p> + +<p>Como puedes ver, no es tan difícil construir un sistema de validación por tu cuenta. La parte difícil es hacer que sea lo suficientemente genérico para que se pueda usar en diferentes plataformas y en cualquier forma. Hay muchas bibliotecas de archivos disponibles para realizar la validación de formularios, como por ejemplo <a href="http://rickharrison.github.com/validate.js/" rel="external">Validate.js</a></p> + +<p>.</p> + +<h2 id="Prueba_tus_habilidades!">Prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo pero ¿puedes recordar la información más importante?Puedes encontrar pruebas adicionales para comprovar que has comprendido la información antes de que continue — visita <a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/Forms/Test_your_skills:_Form_validation">Prueba tus habilidades: Validación de formularios</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>La validación de formularios en el lado del cliente a veces requiere JavaScript si deseas personalizar el estilo y los mensajes de error, pero <em>siempre</em> requiere que pienses cuidadosamente en el usuario. Recuerda que siempre debes ayudar a tus usuarios a corregir los datos que proporcionan. Para ese fin, asegúrate de:</p> + +<ul> + <li>Mostrar mensajes de error explícitos.</li> + <li>Ser permisivo con el formato de entrada.</li> + <li>Señalar exactamente dónde se produce el error, especialmente en formularios extensos.</li> +</ul> + +<p>Una vez que hayas verificado que el formulario se ha completado correctamente, puedes proceder a enviarlo. Vamos a exponer el <a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">envío de los datos del formulario</a> en el próximo artículo.</p> + +<p>{{PreviousMenuNext("Learn/Forms/UI_pseudo-classes", "Learn/Forms/Sending_and_retrieving_form_data", "Learn/HTML/Forms")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/Your_first_form">Tu primer formulario</a></li> + <li><a href="/en-US/docs/Learn/Forms/How_to_structure_a_web_form">Cómo estructurar un formulario web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">Los controles de formulario básicos originales</a></li> + <li><a href="/en-US/docs/Learn/Forms/HTML5_input_types">Los tipos de entrada en HTML5</a></li> + <li><a href="/en-US/docs/Learn/Forms/Other_form_controls">Otros controles de formulario</a></li> + <li><a href="/en-US/docs/Learn/Forms/Styling_web_forms">Aplicar estilo a formularios web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Aplicación de estilo a formularios avanzada</a></li> + <li><a href="/en-US/docs/Learn/Forms/UI_pseudo-classes">Pseudoclases UI</a></li> + <li><a href="/en-US/docs/Learn/Forms/Form_validation">Validación de formularios en el lado del cliente</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a></li> +</ul> + +<h3 id="Temas_avanzados">Temas avanzados</h3> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_controls">Cómo construir controles de formulario personalizados</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript">Enviar formularios por JavaScript</a></li> + <li><a href="/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad de propiedades para controles de formulario</a></li> +</ul> diff --git a/files/es/learn/html/forms/your_first_html_form/index.html b/files/es/learn/html/forms/your_first_html_form/index.html new file mode 100644 index 0000000000..df9d73bc60 --- /dev/null +++ b/files/es/learn/html/forms/your_first_html_form/index.html @@ -0,0 +1,305 @@ +--- +title: Mi primer formulario HTML +slug: Learn/HTML/Forms/Your_first_HTML_form +tags: + - Ejemplo + - Guía + - HTML + - Principiante + - Web + - formulários +translation_of: Learn/Forms/Your_first_form +--- +<div>{{LearnSidebar}}{{NextMenu("Learn/Forms/How_to_structure_a_web_form", "Learn/Forms")}}</div> + +<p class="summary">El primer artículo de nuestra serie te proporciona una primera experiencia de creación de un formulario web, que incluye diseñar un formulario sencillo con controles de formulario adecuados y otros elementos HTML, añadir un poco de estilo muy simple con CSS y describir cómo se envían los datos a un servidor. Ampliaremos cada uno de estos subtemas más adelante.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática y de <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">lenguaje HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarse con los formularios web, para qué se usan, cómo diseñarlos y qué elementos HTML básicos vas a necesitar para casos sencillos.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_son_los_formularios_web">¿Qué son los formularios web?</h2> + +<p>Los <strong>formularios web</strong> son uno de los principales puntos de interacción entre un usuario y un sitio web o aplicación. Los formularios permiten a los usuarios la introducción de datos, que generalmente se envían a un servidor web para su procesamiento y almacenamiento (consulta <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a> más adelante en el módulo), o se usan en el lado del cliente para provocar de alguna manera una actualización inmediata de la interfaz (por ejemplo, se añade otro elemento a una lista, o se muestra u oculta una función de interfaz de usuario).</p> + +<p>El HTML de un <strong>formulario web</strong> está compuesto por uno o más <strong>controles de formulario</strong> (a veces llamados <strong>widgets</strong>), además de algunos elementos adicionales que ayudan a estructurar el formulario general; a menudo se los conoce como <strong>formularios HTML</strong>. Los controles pueden ser campos de texto de una o varias líneas, cajas desplegables, botones, casillas de verificación o botones de opción, y se crean principalmente con el elemento {{htmlelement("input")}}, aunque hay algunos otros elementos que también hay que conocer.</p> + +<p>Los controles de formulario también se pueden programar para forzar la introducción de formatos o valores específicos (<strong>validación de formulario</strong>), y se combinan con etiquetas de texto que describen su propósito para los usuarios con y sin discapacidad visual.</p> + +<h2 id="Diseñar_tu_formulario">Diseñar tu formulario</h2> + +<p>Antes de comenzar a escribir código, siempre es mejor dar un paso atrás y tomarte el tiempo necesario para pensar en tu formulario. Diseñar una maqueta rápida te ayudará a definir el conjunto de datos adecuado que deseas pedirle al usuario que introduzca. Desde el punto de vista de la experiencia del usuario (UX), es importante recordar que cuanto más grande es tu formulario, más te arriesgas a frustrar a las personas y perder usuarios. Tiene que ser simple y conciso: solicita solo los datos que necesitas.</p> + +<p>Diseñar formularios es un paso importante cuando creas un sitio web o una aplicación. Va más allá del alcance de este artículo exponer la experiencia de usuario de los formularios, pero si deseas profundizar en ese tema, puedes leer los artículos siguientes:</p> + +<ul> + <li>Smashing Magazine tiene algunos <a href="https://www.smashingmagazine.com/2018/08/ux-html5-mobile-form-part-1/" rel="external" title="http://uxdesign.smashingmagazine.com/tag/forms/">artículos muy buenos sobre formularios UX</a>, incluido el artículo —antiguo pero relevante— <a href="https://www.smashingmagazine.com/2011/11/extensive-guide-web-form-usability/" rel="external" title="http://uxdesign.smashingmagazine.com/2011/11/08/extensive-guide-web-form-usability/">An Extensive Guide To Web Form Usability</a> [Amplia guía de usabilidad para formularios web].</li> + <li>UXMatters también es un recurso que da buenos consejos, desde <a href="http://www.uxmatters.com/mt/archives/2012/05/7-basic-best-practices-for-buttons.php" rel="external" title="http://www.uxmatters.com/mt/archives/2012/05/7-basic-best-practices-for-buttons.php"> buenas prácticas básicas</a> hasta cuestiones complejas como los <a href="http://www.uxmatters.com/mt/archives/2010/03/pagination-in-web-forms-evaluating-the-effectiveness-of-web-forms.php" title="http://www.uxmatters.com/mt/archives/2010/03/pagination-in-web-forms-evaluating-the-effectiveness-of-web-forms.php"> formularios de varias páginas</a>.</li> +</ul> + +<p>En este artículo, vamos a crear un formulario de contacto sencillo. Hagamos un esbozo.</p> + +<p><img alt="Esbozo aproximado del formulario que vamos a construir" src="/files/4579/form-sketch-low.jpg" style="border-style: solid; border-width: 1px; display: block; height: 352px; margin: 0px auto; width: 400px;"></p> + +<p>Nuestro formulario va a tener tres campos de texto y un botón. Le pedimos al usuario su nombre, su correo electrónico y el mensaje que desea enviar. Al pulsar el botón sus datos se enviarán a un servidor web.</p> + +<h2 id="Aprendizaje_activo_La_implementación_de_nuestro_formulario_HTML">Aprendizaje activo: La implementación de nuestro formulario HTML</h2> + +<p>De acuerdo, intentemos crear el HTML para nuestro formulario. Vamos a utilizar los elementos HTML siguientes: {{HTMLelement("form")}}, {{HTMLelement("label")}}, {{HTMLelement("input")}}, {{HTMLelement("textarea")}} y {{HTMLelement("button")}}.</p> + +<p>Antes de continuar, haz una copia local de nuestra <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">plantilla HTML simple</a>: introduce aquí tu formulario HTML.</p> + +<h3 id="El_elemento_HTMLelementform">El elemento {{HTMLelement("form")}}</h3> + +<p>Todos los formularios comienzan con un elemento {{HTMLelement("form")}}, como este:</p> + +<pre class="brush:html; notranslate"><form action="/my-handling-form-page" method="post"> + +</form></pre> + +<p>Este elemento define formalmente un formulario. Es un elemento contenedor, como un elemento {{HTMLelement("section")}} o {{HTMLelement("footer")}}, pero específico para contener formularios; también admite algunos atributos específicos para la configuración de la forma en que se comporta el formulario. Todos sus atributos son opcionales, pero es una práctica estándar establecer siempre al menos los atributos <a href="/en-US/docs/Web/HTML/Attributes/action"><code>action</code></a> y <a href="/en-US/docs/Web/HTML/Attributes/method"><code>method</code></a>:</p> + +<ul> + <li>El atributo <code>action</code> define la ubicación (URL) donde se envían los datos que el formulario ha recopilado cuando se validan.</li> + <li>El atributo <code>method</code> define con qué método HTTP se envían los datos (generalmente <code>get</code> o <code>post</code>).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Veremos cómo funcionan esos atributos en nuestro artículo <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data" title="/en-US/docs/HTML/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a> que encontrarás más adelante.</p> +</div> + +<p>Por ahora, añade el elemento {{htmlelement("form")}} anterior a tu elemento HTML {{htmlelement("body")}}.</p> + +<h3 id="Los_elementos_HTMLelementlabel_HTMLelementinput_y_HTMLelementtextarea">Los elementos {{HTMLelement("label")}}, {{HTMLelement("input")}} y {{HTMLelement("textarea")}}</h3> + +<p>Nuestro formulario de contacto no es complejo: la parte para la entrada de datos contiene tres campos de texto, cada uno con su elemento {{HTMLelement("label")}} correspondiente:</p> + +<ul> + <li>El campo de entrada para el nombre es un {{HTMLelement("input/text", "campo de texto de una sola línea")}}.</li> + <li>El campo de entrada para el correo electrónico es una {{HTMLelement ("input/email", "entrada de datos de tipo correo electrónico")}}: un campo de texto de una sola línea que acepta solo direcciones de correo electrónico.</li> + <li>El campo de entrada para el mensaje es {{HTMLelement("textarea")}}; un campo de texto multilínea.</li> +</ul> + +<p>En términos de código HTML, para implementar estos controles de formulario necesitamos algo como lo siguiente:</p> + +<pre class="brush:html; notranslate" dir="rtl"><form action="/my-handling-form-page" method="post"> + <ul> + <li> + <label for="name">Nombre:</label> + <input type="text" id="name" name="user_name"> + </li> + <li> + <label for="mail">Correo electrónico:</label> + <input type="email" id="mail" name="user_mail"> + </li> + <li> + <label for="msg">Mensaje:</label> + <textarea id="msg" name="user_message"></textarea> + </li> + </ul> +</form></pre> + +<p>Actualiza el código de tu formulario para que se vea como el anterior.</p> + +<p>Los elementos {{HTMLelement("li")}} están ahí para estructurar nuestro código convenientemente y facilitar la aplicación de estilo (ver más adelante en el artículo). Por motivos de usabilidad y accesibilidad incluimos una etiqueta explícita para cada control de formulario. Ten en cuenta el uso del atributo <a href="/en-US/docs/Web/HTML/Attributes/for"> <code>for</code> </a> en todos los elementos {{HTMLelement("label")}}, que toma como valor el <a href="/en-US/docs/Web/HTML/Attributes/id"><code>id</code></a> del control de formulario con el que está asociado; así es como asocias un formulario con su etiqueta.</p> + +<p>Hacer esto presenta muchas ventajas porque la etiqueta está asociada al control del formulario y permite que los usuarios con ratón, panel táctil y dispositivos táctiles hagan clic en la etiqueta para activar el control correspondiente, y también proporciona accesibilidad con un nombre que los lectores de pantalla leen a sus usuarios. Encontrarás más detalles sobre las etiquetas de los formularios en <a href="/es/docs/Learn/HTML/Forms/How_to_structure_an_HTML_form">Cómo estructurar un formulario web</a>.</p> + +<p>En el elemento {{HTMLelement("input")}}, el atributo más importante es <code>type</code>. Este atributo es muy importante porque define la forma en que el elemento {{HTMLelement("input")}} aparece y se comporta. Encontrarás más información sobre esto en el artículo sobre <a href="/es/docs/Learn/HTML/Forms/The_native_form_widgets">Controles de formularios nativos básicos</a> más adelante.</p> + +<ul> + <li>En nuestro ejemplo sencillo, usamos el valor {{HTMLelement("input/text")}} para la primera entrada, el valor predeterminado para este atributo. Representa un campo de texto básico de una sola línea que acepta cualquier tipo de entrada de texto.</li> + <li>Para la segunda entrada, usamos el valor {{HTMLelement("input/email")}}, que define un campo de texto de una sola línea que solo acepta una dirección de correo electrónico. Esto convierte un campo de texto básico en una especie de campo «inteligente» que efectúa algunas comprobaciones de validación de los datos que el usuario escribe. También hace que aparezca un diseño de teclado más apropiado para introducir direcciones de correo electrónico (por ejemplo, con un símbolo @ por defecto) en dispositivos con teclados dinámicos, como teléfonos inteligentes. Encontrarás más información sobre la validación de formularios en el artículo de <a href="/es/docs/Learn/HTML/Forms/Validacion_formulario_datos">Validación de formularios por parte del cliente</a> más adelante.</li> +</ul> + +<p>Por último, pero no por ello menos importante, ten en cuenta la sintaxis de <code><input></code> en contraposición con la de <code><textarea></textarea></code>. Esta es una de las rarezas del HTML. La etiqueta <code><input></code> es un elemento vacío, lo que significa que no necesita una etiqueta de cierre. El elemento {{HTMLElement("textarea")}} no es un elemento vacío, lo que significa que debe cerrarse con la etiqueta de cierre adecuada. Esto tiene un impacto en una característica específica de los formularios: el modo en que defines el valor predeterminado. Para definir el valor predeterminado de un elemento {{HTMLElement("input")}}, debes usar el atributo <a href="/en-US/docs/Web/HTML/Attributes/value"><code>value</code></a> de esta manera:</p> + +<pre class="brush:html; notranslate"><input type="text" value="por defecto este elemento se llena con este texto"></pre> + +<p>Por otro lado, si deseas definir un valor predeterminado para un elemento {{HTMLElement("textarea")}}, lo colocas entre las etiquetas de apertura y cierre del elemento {{HTMLElement("textarea")}}, así:</p> + +<pre class="brush:html; notranslate"><textarea> +Por defecto, este elemento contiene este texto +</textarea></pre> + +<h3 id="El_elemento_HTMLelementbutton">El elemento {{HTMLelement("button")}}</h3> + +<p>El marcado de nuestro formulario está casi completo; solo necesitamos añadir un botón para permitir que el usuario envíe sus datos una vez que haya completado el formulario. Esto se hace con el elemento {{HTMLelement("button")}}; añade lo siguiente justo encima de la etiqueta de cierre <code></form></code>:</p> + +<pre class="brush:html; notranslate"><li class="button"> + <button type="submit">Envíe su mensaje</button> +</li></pre> + +<p>El elemento {{htmlelement("button")}} también acepta un atributo de <code>type</code>, que a su vez acepta uno de estos tres valores: <code>submit</code>, <code>reset</code> o <code>button</code>.</p> + +<ul> + <li>Un clic en un botón <code>submit</code> (el valor predeterminado) envía los datos del formulario a la página web definida por el atributo <code>action</code> del elemento {{HTMLelement("form")}}.</li> + <li>Un clic en un botón <code>reset</code> restablece de inmediato todos los controles de formulario a su valor predeterminado. Desde el punto de vista de UX, esto se considera una mala práctica, por lo que debes evitar usar este tipo de botones a menos que realmente tengas una buena razón para incluirlos.</li> + <li>Un clic en un botón <code>button</code> no hace... ¡nada! Eso suena tonto, pero es muy útil para crear botones personalizados: puedes definir su función con JavaScript.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: También puedes usar el elemento {{HTMLElement("input")}} con el atributo <code>type</code> correspondiente para generar un botón, por ejemplo <code><input type="submit"></code>. La ventaja principal del elemento {{HTMLelement("button")}} es que el elemento {{HTMLelement("input")}} solo permite texto sin formato en su etiqueta, mientras que el elemento {{HTMLelement("button")}} permite contenido HTML completo, lo que permite generar botones creativos más complejos.</p> +</div> + +<h2 id="Aplicar_estilo_básico_a_un_formulario">Aplicar estilo básico a un formulario</h2> + +<p>Ahora que has terminado de escribir el código HTML de tu formulario, guárdalo y observa lo que ocurre en un navegador. Por ahora, se verá bastante feo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si crees que no has escrito bien el código HTML, compáralo con nuestro ejemplo final: véase <a href="https://github.com/mdn/learning-area/blob/master/html/forms/your-first-HTML-form/first-form.html">first-form.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form.html">ver en vivo</a>).</p> +</div> + +<p>Resulta notablemente difícil aplicar estilo a los formularios. Está más allá del alcance de este artículo enseñarte cómo aplicar estilo a los formularios en detalle, por lo que por el momento solo vamos a exponer cómo añadir un poco de CSS para que se vea un poco bien.</p> + +<p>En primer lugar, añade un elemento {{htmlelement("style")}} a tu página, dentro de la cabecera del HTML. Debe quedar así:</p> + +<pre class="brush: html notranslate"><style> + +</style></pre> + +<p>Dentro de las etiquetas <code>style</code>, añade el código CSS siguiente:</p> + +<pre class="brush:css; notranslate">form { + /* Centrar el formulario en la página */ + margin: 0 auto; + width: 400px; + /* Esquema del formulario */ + padding: 1em; + border: 1px solid #CCC; + border-radius: 1em; +} + +ul { + list-style: none; + padding: 0; + margin: 0; +} + +form li + li { + margin-top: 1em; +} + +label { + /* Tamaño y alineación uniforme */ + display: inline-block; + width: 90px; + text-align: right; +} + +input, +textarea { + /* Para asegurarse de que todos los campos de texto tienen la misma configuración de letra + Por defecto, las áreas de texto tienen un tipo de letra monoespaciada */ + font: 1em sans-serif; + + /* Tamaño uniforme del campo de texto */ + width: 300px; + box-sizing: border-box; + + /* Hacer coincidir los bordes del campo del formulario */ + border: 1px solid #999; +} + +input:focus, +textarea:focus { + /* Destacado adicional para elementos que tienen el cursor */ + border-color: #000; +} + +textarea { + /* Alinear los campos de texto multilínea con sus etiquetas */ + vertical-align: top; + + /* Proporcionar espacio para escribir texto */ + height: 5em; +} + +.button { + /* Alinear los botones con los campos de texto */ + padding-left: 90px; /* mismo tamaño que los elementos de la etiqueta */ +} + +button { + /* Este margen adicional representa aproximadamente el mismo espacio que el espacio + entre las etiquetas y sus campos de texto */ + margin-left: .5em; +}</pre> + +<p>Guarda y vuelve a cargar, y observa que tu formulario presenta un aspecto mucho menos feo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar nuestra versión en GitHub en <a href="https://github.com/mdn/learning-area/blob/master/html/forms/your-first-HTML-form/first-form-styled.html">first-form-styled.html</a> (<a href="https://mdn.github.io/learning-area/html/forms/your-first-HTML-form/first-form-styled.html">ver en vivo</a>).</p> +</div> + +<h2 id="Enviar_los_datos_del_formulario_a_un_servidor_web">Enviar los datos del formulario a un servidor web</h2> + +<p>La última parte, y quizás la más complicada, es manejar los datos del formulario en el lado del servidor. El elemento {{HTMLelement("form")}} define dónde y cómo enviar los datos gracias a los atributos <a href="/en-US/docs/Web/HTML/Attributes/action"><code>action</code></a> y <a href="/en-US/docs/Web/HTML/Attributes/method"><code>method</code></a>.</p> + +<p>Proporcionamos un nombre (<a href="/en-US/docs/Web/HTML/Attributes/name"><code>name</code></a>) a cada control de formulario. Los nombres son importantes tanto en el lado del cliente como del servidor; le dicen al navegador qué nombre debe dar a cada dato y, en el lado del servidor, dejan que el servidor maneje cada dato por su nombre. Los datos del formulario se envían al servidor como pares de nombre/valor.</p> + +<p>Para poner nombre a los diversos datos que se introducen en un formulario, debes usar el atributo <code>name</code> en cada control de formulario que recopila un dato específico. Veamos de nuevo algunos de nuestros códigos de formulario:</p> + +<pre class="brush:html; notranslate"><form action="/my-handling-form-page" method="post"> + <ul> + <li> + <label for="name">Nombre:</label> + <input type="text" id="name" name="user_name" /> + </li> + <li> + <label for="mail">Correo electrónico:</label> + <input type="email" id="mail" name="user_email" /> + </li> + <li> + <label for="msg">Mensaje:</label> + <textarea id="msg" name="user_message"></textarea> + </li> + + ... +</pre> + +<p>En nuestro ejemplo, el formulario envía tres datos denominados «<code>user_name</code>», «<code>user_email</code>» y «<code>user_message</code>». Esos datos se envían a la URL «<code>/my-handling-form-page</code>» utilizando el método <a href="/en-US/docs/Web/HTTP/Methods/POST"><code>post</code> de HTTP</a>.</p> + +<p>En el lado del servidor, la secuencia de comandos de la URL «<code>/my-handling-form-page</code>» recibe los datos como una lista de tres elementos clave/valor contenidos en la solicitud HTTP. La forma en que este script maneja esos datos depende de ti. Cada lenguaje de servidor (PHP, Python, Ruby, Java, C#, etc.) tiene su propio mecanismo de manipulación de datos de formulario. No profundizaremos sobre el tema en esta guía, pero si deseas obtener más información, proporcionamos algunos ejemplos en nuestro artículo <a href="/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data" title="/en-US/docs/HTML/Forms/Sending_and_retrieving_form_data"><span>Enviar los datos de un formulario</span></a> que encontrarás más adelante.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>¡Enhorabuena!, has creado tu primer formulario web. Debería verse así:</p> + +<p>{{ EmbedLiveSample('A_simple_form', '100%', '240', '', 'Learn/Forms/Your_first_form/Example') }}</p> + +<p>Pero esto es solo el comienzo: ahora ha llegado el momento de profundizar en el tema. Los formularios tienen mucho más potencial de lo que hemos visto aquí y los artículos siguientes de este módulo te ayudarán a dominarlo.</p> + +<p>{{NextMenu("Learn/Forms/How_to_structure_a_web_form", "Learn/Forms")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/Your_first_form">Tu primer formulario</a></li> + <li><a href="/en-US/docs/Learn/Forms/How_to_structure_a_web_form">Cómo estructurar un formulario web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Basic_native_form_controls">Los controles de formulario básicos originales</a></li> + <li><a href="/en-US/docs/Learn/Forms/HTML5_input_types">Los tipos de entrada en HTML5</a></li> + <li><a href="/en-US/docs/Learn/Forms/Other_form_controls">Otros controles de formulario</a></li> + <li><a href="/en-US/docs/Learn/Forms/Styling_web_forms">Aplicación de estilo a formularios web</a></li> + <li><a href="/en-US/docs/Learn/Forms/Advanced_form_styling">Aplicación de estilo a formularios avanzada</a></li> + <li><a href="/en-US/docs/Learn/Forms/UI_pseudo-classes">Pseudoclases UI</a></li> + <li><a href="/en-US/docs/Learn/Forms/Form_validation">Validación del formulario del lado del cliente</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_and_retrieving_form_data">Enviar los datos de un formulario</a></li> +</ul> + +<h3 id="Temas_avanzados">Temas avanzados</h3> + +<ul> + <li><a href="/en-US/docs/Learn/Forms/How_to_build_custom_form_controls">Cómo construir controles de formulario personalizados</a></li> + <li><a href="/en-US/docs/Learn/Forms/Sending_forms_through_JavaScript">Enviar formularios a través de JavaScript</a></li> + <li><a href="/en-US/docs/Learn/Forms/Property_compatibility_table_for_form_widgets">Tabla de compatibilidad para las propiedades de los controles de formulario</a></li> +</ul> diff --git a/files/es/learn/html/index.html b/files/es/learn/html/index.html new file mode 100644 index 0000000000..6262b7f957 --- /dev/null +++ b/files/es/learn/html/index.html @@ -0,0 +1,66 @@ +--- +title: HTML +slug: Learn/HTML +tags: + - Aprender + - Guía + - HTML + - Novato + - Principiante + - Tema + - introducción +translation_of: Learn/HTML +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Para crear sitios web, debes conocer el {{Glossary('HTML')}} — la tecnología fundamental que se utiliza para definir la estructura de una página web. HTML se utiliza para especificar si tu contenido web se debe reconocer como un párrafo, lista, encabezado, enlace, imagen, reproductor multimedia, formulario o uno de los muchos otros elementos disponibles o incluso un nuevo elemento que tú definas.</p> + +<div class="in-page-callout webdev"> +<h3 id="¿Quieres_transformarte_en_un_desarrollador_de_la_interfaz_de_usuario_web">¿Quieres transformarte en un desarrollador de la interfaz de usuario web?</h3> + +<p>Hemos elaborado un curso que incluye toda la información esencial que necesitas para trabajar hacia tu objetivo.</p> + +<p><a class="cta primary" href="/docs/Learn/Front-end_web_developer">Empieza aquí</a></p> +</div> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<ul> +</ul> + +<p>Antes de comenzar con este tema, debes tener al menos una familiaridad básica con el uso de computadoras y el uso pasivo de la web (es decir, simplemente mirarlo, consumir el contenido). Debes tener un entorno de trabajo básico configurado como se detalla en {{web.link("/es/docs/Learn/Getting_started_with_the_web/Installing_basic_software", "Instalación de software básico")}}, y comprender cómo crear y administrar archivos, como se detalla en {{web.link("/es/docs/Learn/Getting_started_with_the_web/Dealing_with_files", "Manejo de archivos")}}; ambos son parte del módulo para principiantes en la {{web.link("/es/docs/Learn/Getting_started_with_the_web", "Introducción a la Web")}}.</p> + +<p>Se recomienda que trabajes con {{web.link("/es/docs/Learn/Getting_started_with_the_web", "Comenzando con la web")}} antes de intentar este tema, sin embargo, no es absolutamente necesario; gran parte de lo que se cubre en el artículo {{web.link("/es/docs/Learn/Getting_started_with_the_web/HTML_basics", "conceptos básicos de HTML")}} también se cubre en el {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML", "Módulo de introducción a HTML")}}, aunque con mucho más detalle.</p> + +<p>Después de comprender HTML, puedes pasar a aprender temas más avanzados como:</p> + +<ul> + <li>{{web.link("/es/docs/Learn/CSS", "CSS")}}, y cómo usarlo para estilizar HTML (por ejemplo, modificar el tamaño del texto y los tipos de letra utilizados, agregar bordes y sombras, modelar tu página con varias columnas, agregar animaciones y otros efectos visuales).</li> + <li>{{web.link("/es/docs/Learn/JavaScript", "JavaScript")}}, y cómo usarlo para agregar funcionalidad dinámica a las páginas web (por ejemplo, encontrar tu ubicación y trazarla en un mapa, hacer que los elementos de la <em><strong>I</strong>nterfaz de <strong>U</strong>suario</em> (<strong>IU</strong> en adelante) aparezcan/desaparezcan cuando se alterna un botón, guardar los datos del usuario localmente en su computadora y mucho más).</li> +</ul> + +<h2 id="Módulos">Módulos</h2> + +<p>Este tema contiene los siguientes módulos, en un orden sugerido para trabajar con ellos. Definitivamente deberías comenzar con el primero.</p> + +<dl> + <dt>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML", "Introducción a HTML")}}</dt> + <dd>Este módulo prepara el escenario para que te acostumbres a conceptos y sintaxis importantes, explica cómo aplicar HTML al texto, cómo crear hipervínculos y cómo usar HTML para estructurar una página web.</dd> + <dt>{{web.link("/es/docs/Learn/HTML/Multimedia_and_embedding", "Multimedia e inserción")}}</dt> + <dd>Este módulo explora cómo usar HTML para incluir multimedia en tus páginas web, incluidas las diferentes formas en que se pueden incluir imágenes y cómo insertar video, audio e incluso otras páginas web completas.</dd> + <dt>{{web.link("/es/docs/Learn/HTML/Tables", "tablas HTML")}}</dt> + <dd>Representar datos tabulares en una página web de una manera comprensible y {{Glossary("Accessibility", "accesible")}} puede ser un desafío. Este módulo cubre el marcado básico de tablas, junto con características más complejas como la implementación de subtítulos y resúmenes.</dd> +</dl> + +<h2 id="Resolver_problemas_comunes_de_HTML">Resolver problemas comunes de HTML</h2> + +<p>{{web.link("/es/docs/Learn/HTML/Howto", "Usa HTML para resolver problemas comunes")}} proporciona vínculos a secciones de contenido que explican cómo usar HTML para resolver muchos problemas comunes al crear una página web: lidiar con títulos, agregar imágenes o videos, enfatizar contenido, crear una forma básica, etc.</p> + +<h2 id="Ve_también">Ve también</h2> + +<dl> + <dt>{{web.link("/es/docs/Learn/HTML/Forms", "Formularios Web")}}</dt> + <dd>Este módulo proporciona una serie de artículos que te ayudarán a dominar los conceptos básicos de los formularios web. Los formularios web son una herramienta muy poderosa para interactuar con los usuarios — generalmente, se utilizan para recopilar datos de los usuarios o para permitirles controlar una interfaz de usuario. Sin embargo, por razones históricas y técnicas, no siempre es obvio cómo utilizarlos en todo su potencial. Aborda todos los aspectos esenciales de los formularios web, incluido el marcado de su estructura HTML, el diseño de controles de formulario, la validación de datos de formulario y el envío de datos al servidor.</dd> + <dt>{{web.link("/es/docs/Web/HTML", "HTML (lenguaje de marcado de hipertexto)")}}</dt> + <dd>El punto de entrada principal para la documentación de referencia HTML en MDN, incluidas las referencias detalladas de elementos y atributos; si deseas saber qué atributos tiene un elemento o qué valores tiene un atributo, por ejemplo, este es un excelente lugar para comenzar.</dd> +</dl> diff --git a/files/es/learn/html/introduccion_a_html/advanced_text_formatting/index.html b/files/es/learn/html/introduccion_a_html/advanced_text_formatting/index.html new file mode 100644 index 0000000000..7e96d3c6d7 --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/advanced_text_formatting/index.html @@ -0,0 +1,695 @@ +--- +title: Formateo de texto avanzado +slug: Learn/HTML/Introduccion_a_HTML/Advanced_text_formatting +tags: + - CodingScripting + - Guía + - HTML + - Lista de descripción + - Novato + - Principiante + - Texto + - abreviatura + - aprende + - cita + - semántica +translation_of: Learn/HTML/Introduction_to_HTML/Advanced_text_formatting +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">Hay muchos otros elementos en HTML para dar formato al texto, que no expusimos en el artículo {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Fundamentos de texto HTML")}}. Los elementos descritos en este artículo son menos conocidos, pero aún así es muy útil conocerlos (no obstante, no es una lista completa de ninguna manera). Aquí aprenderás cómo marcar citas, listas de descripción, código de computadora y otro texto relacionado, subíndices y superíndices, información de contacto y mucho más.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Estar familiarizado con HTML, cubierto en {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}. Aplicación de formato a texto en documentos HTML, según lo expuesto en la sección {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Fundamentos de texto HTML")}}.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a utilizar elementos HTML menos conocidos para marcar características semánticas avanzadas.</td> + </tr> + </tbody> +</table> + +<h2 id="Listas_de_descripciones">Listas de descripciones</h2> + +<p>En los fundamentos del texto HTML, explicamos cómo {{web.link("/es/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Lists", "marcar listas básicas")}} en HTML, pero no mencionamos el tercer tipo de lista con la que te encontrarás ocasionalmente: <strong>listas de descripción</strong>. El propósito de estas listas es marcar un conjunto de elementos y sus descripciones asociadas, como términos y definiciones, o preguntas y respuestas. Veamos un ejemplo de un conjunto de términos y definiciones:</p> + +<pre class="brush: bash notranslate">soliloquio +En las obras dramáticas, corresponde a cuando un personaje se habla a sí mismo para representar sus pensamientos o sentimientos internos y, en el proceso, transmitirlos a la audiencia (pero no a otros personajes). +monólogo +En las obras dramáticas, corresponde a cuando un personaje habla de sus pensamientos en voz alta para compartirlos con el público y cualquier otro personaje presente. +aparte +En las obras dramáticas, corresponde a cuando un personaje comparte un comentario solo con la audiencia para dar efecto cómico o dramático. Suele ser un sentimiento, un pensamiento o información adicional.</pre> + +<p>Las listas de descripción utilizan un contenedor diferente al de los otros tipos de listas — {{HTMLElement("dl")}} («<em><b>d</b>escription <b>l</b>ist</em>» o lista de descripciones); además, cada término está envuelto en un elemento {{HTMLElement("dt")}} («<em><b>d</b>escription <b>t</b>erm</em>» o término a describir), y cada descripción está envuelta en un elemento {{HTMLElement("dd")}} («<em><b>d</b>escription <b>d</b>efinition</em>» o definición de descripción). Para redondear esta información veamos un ejemplo:</p> + +<div id="listas-de-descripciones-ejemplo-activo-1"> +<pre class="brush: html notranslate"><dl> + <dt>soliloquio</dt> + <dd>En las obras dramáticas, corresponde a cuando un personaje se habla a sí mismo para representar sus pensamientos o sentimientos internos y, en el proceso, transmitirlos a la audiencia (pero no a otros personajes).</dd> + <dt>monólogo</dt> + <dd>En las obras dramáticas, corresponde a cuando un personaje habla de sus pensamientos en voz alta para compartirlos con el público y cualquier otro personaje presente.</dd> + <dt>aparte</dt> + <dd>En las obras dramáticas, corresponde a cuando un personaje comparte un comentario solo con la audiencia para dar efecto cómico o dramático. Suele ser un sentimiento, un pensamiento o información adicional.</dd> +</dl></pre> +</div> + +<p>Los estilos predeterminados del navegador mostrarán listas de descripciones con las descripciones sangradas un poco más que los términos.</p> + +<p>{{ EmbedLiveSample('listas-de-descripciones-ejemplo-activo-1', '100%', '285px', '', '', 'hide-codepen-jsfiddle') }}</p> + +<p>Ten en cuenta que un solo término puede tener múltiples descripciones, por ejemplo:</p> + +<div id="listas-de-descripciones-ejemplo-activo-2"> +<pre class="brush: html notranslate"><dl> + <dt>aparte</dt> + <dd>En las obras dramáticas, corresponde a cuando un personaje comparte un comentario solo con la audiencia para dar efecto cómico o dramático. Suele ser un sentimiento, un pensamiento o información adicional.</dd> + <dd>Si la obra es impresa, es una sección de contenido que se relaciona con el tema, pero no encaja directamente en el flujo principal de contenido, de modo que se presenta por separado (a menudo en una caja de texto en el margen).</dd> +</dl></pre> +</div> + +<p>{{ EmbedLiveSample('listas-de-descripciones-ejemplo-activo-2', '100%', '193px', '', '', 'hide-codepen-jsfiddle') }}</p> + +<h3 id="Aprendizaje_activo_Marcar_un_conjunto_de_definiciones">Aprendizaje activo: Marcar un conjunto de definiciones</h3> + +<p>Es hora de practicar las listas de descripciones; agrega elementos al texto sin formato en el campo <em>Código editable</em> para que aparezca como una lista de descripción en el campo <em>Salida en vivo</em>. Puedes usar tus propios términos y descripciones si lo deseas.</p> + +<p>Si cometes un error, siempre puedes restablecer el código anterior pulsando el botón <em>Restablecer</em>. Si te quedas realmente encallado, pulsa el botón <em>Mostrar solución</em> para ver una buena propuesta.</p> + +<div class="hidden"> +<h6 id="Código_reproducible">Código reproducible</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 100px; width: 95%"> +Tocino +El pegamento que une al mundo. +Huevos +El pegamento que une el pastel. +Café +La bebida que hace que el mundo funcione por la mañana. +Un color marrón claro.</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">const textarea = document.getElementById('code'); +const reset = document.getElementById('reset'); +const solution = document.getElementById('solution'); +const output = document.querySelector('.output'); +const code = textarea.value; +const userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +const htmlSolution = '<dl>\n <dt>Tocino</dt>\n <dd>El pegamento que une al mundo.</dd>\n <dt>Huevos</dt>\n <dd>El pegamento que une el pastel.</dd>\n <dt>Café</dt>\n <dd>La bebida que hace que el mundo funcione por la mañana.</dd>\n <dd>Un color marrón claro.</dd>\n</dl>'; +const solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + const scrollPos = textarea.scrollTop; + const caretPos = textarea.selectionStart; + + const front = (textarea.value).substring(0, caretPos); + const back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible', 700, 350, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Citas">Citas</h2> + +<p>HTML también dispone de elementos para el marcado de citas; cual elemento utilices depende de si estás marcando la cita como un bloque o como un elemento en línea.</p> + +<h3 id="Cita_en_bloque_independiente_blockquote">Cita en bloque independiente (<em>blockquote</em>)</h3> + +<p>Si una sección de contenido a nivel de bloque (ya sea un párrafo, varios párrafos, una lista, etc.) se cita en otro lugar, debes envolverla dentro de un elemento {{HTMLElement("blockquote")}} para indicarlo, e incluye una URL que apunte a la fuente de la cita dentro de un atributo {{HTMLAttrxRef("cite", "blockquote")}}. Por ejemplo, el siguiente marcado tomado de la página del elemento <code><blockquote></code> de MDN:</p> + +<pre class="brush: html notranslate"><p>El <strong>elemento HTML <code>&lt;blockquote&gt;</code></strong> (o <em>elemento HTML de cita +en bloque independiente</em>) indica que el texto al que delimita es una cita ampliada.</p></pre> + +<p>Para convertir esto en una cita en bloque independiente, simplemente harías lo siguiente:</p> + +<div id="blockquote-ejemplo-en-vivo"> +<pre class="brush: html notranslate"><p>A continuación se muestra una cita en bloque independiente...</p> +<blockquote cite="https://developer.mozilla.org/es/docs/Web/HTML/Element/blockquote"> + <p>El <strong>elemento HTML <code>&lt;blockquote&gt;</code></strong> (o <em>elemento HTML de cita + en bloque independiente</em>) indica que el texto al que delimita es una cita ampliada.</p> +</blockquote></pre> +</div> + +<p>El estilo predeterminado del navegador lo mostrará como un párrafo con sangría, para indicar que se trata de una cita; el párrafo anterior a la cita sirve para demostrarlo.</p> + +<p>{{EmbedLiveSample('blockquote-ejemplo-en-vivo', '100%', '117px', '', '', 'hide-codepen-jsfiddle')}}</p> + +<h3 id="Citas_en_línea">Citas en línea</h3> + +<p>Las citas en línea funcionan exactamente de la misma manera, excepto que usan el elemento {{HTMLElement("q")}}. Por ejemplo, el siguiente fragmento de marcado contiene una cita <code><q></code> de la página MDN:</p> + +<pre class="brush: html notranslate"><p>El elemento de cita — <code>&lt;q&gt;</code> — se <q cite="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q">utiliza en +para citas breves que no requieren saltos de párrafo.</q></p></pre> + +<p>El estilo predeterminado del navegador lo representará como texto normal entre comillas para indicar una cita, así:</p> + +<p>{{ EmbedLiveSample('Citas_en_línea', '100%', '78px', '', '', 'hide-codepen-jsfiddle')}}</p> + +<h3 id="Citas_2">Citas</h3> + +<p>El contenido del atributo {{HTMLAttrxRef("cite", "blockquote")}} suena útil, pero desafortunadamente los navegadores, lectores de pantalla, etc. no hacen mucho con él. No hay forma de hacer que el navegador muestre el contenido de <code>cite</code> sin escribir tu propia solución usando JavaScript o CSS. Si deseas que la fuente de la cita esté disponible en la página, lo debes hacer en el texto a través de un enlace o de alguna otra forma apropiada.</p> + +<p>Hay un elemento {{HTMLElement("cite")}}, pero está destinado a contener el título del recurso que se cita, p. ej. el nombre del libro. Sin embargo, no hay razón por la que no puedas vincular el texto dentro de <code><cite></code> a la fuente de la cita de alguna manera:</p> + +<pre class="brush: html notranslate"><p>De acuerdo con <a href="https://developer.mozilla.org/es/docs/Web/HTML/Element/blockquote"> +<cite>página de citas en bloque independiente de MDN</cite></a>: +</p> + +<blockquote cite="https://developer.mozilla.org/es/docs/Web/HTML/Element/blockquote"> + <p>El <strong>elemento HTML <code>&lt;blockquote&gt;</code></strong> (o <em>elemento HTML de cita + en bloque independiente</em>) indica que el texto al que delimita es una cita ampliada.</p> +</blockquote> + +<p>El elemento de cita — <code>&lt;q&gt;</code> — se <q cite="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q">utiliza en +citas breves que no requieren saltos de párrafo.</q> -- <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/q"> +<cite>página q de MDN</cite></a>.</p></pre> + +<p>Las citas se escriben en cursiva de forma predeterminada.</p> + +<p>{{ EmbedLiveSample('Citas_2', '100%', '179px', '', '', 'hide-codepen-jsfiddle') }}</p> + +<h3 id="Aprendizaje_activo_¿Quién_dijo_eso">Aprendizaje activo: ¿Quién dijo eso?</h3> + +<p>¡Es hora de otro ejemplo de aprendizaje activo! En este ejemplo, nos gustaría que:</p> + +<ol> + <li>Conviertas el párrafo del medio en una cita en bloque independiente, que incluya un atributo <code>cite</code>.</li> + <li>Conviertas "La necesidad de eliminar el diálogo interno negativo" en el tercer párrafo en una cita en línea e incluya un atributo <code>cite</code>.</li> + <li>Envuelvas el título de cada fuente en etiquetas <code><cite></code> y conviertas cada una en un enlace a esa fuente.</li> +</ol> + +<p>Las fuentes de citación que necesitas son:</p> + +<ul> + <li>http://www.brainyquote.com/quotes/authors/c/confucius.html para la citas de Confucio</li> + <li>http://www.affirmationsforpositivethinking.com para "La necesidad de eliminar el diálogo interno negativo".</li> +</ul> + +<p>Si cometes un error, siempre puedes restablecer el código anterior pulsando el botón <em>Restablecer</em>. Si te quedas realmente encallado, pulsa el botón <em>Mostrar solución</em> para ver una buena propuesta.</p> + +<div class="hidden"> +<h6 id="Código_reproducible_2">Código reproducible 2</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 150px; width: 95%"> +<p>Hola y bienvenido a mi página de motivación. Como dice el sitio de citas de Confucio:</p> +<p>No importa qué tan lento vayas siempre que no te detengas.</p> +<p>También me encanta el concepto de pensamiento positivo y La necesidad de eliminar el diálogo interno negativo (como se menciona en Afirmaciones para el pensamiento positivo).</p> +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">const textarea = document.getElementById('code'); +const reset = document.getElementById('reset'); +const solution = document.getElementById('solution'); +const output = document.querySelector('.output'); +const code = textarea.value; +const userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +const htmlSolution = '<p>Hola y bienvenido a mi página de motivación. Como dice <a href="http://www.brainyquote.com/quotes/authors/c/confucius.html"><cite>el sitio de citas de Confucio:</cite></a>:</p>\n\n<blockquote cite="http://www.brainyquote.com/quotes/authors/c/confucius.html">\n<p>No importa qué tan lento vayas siempre que no te detengas.</p>\n</blockquote>\n\n<p>También me encanta el concepto de pensamiento positivo y <q cite="http://www.affirmationsforpositivethinking.com">La necesidad de eliminar el diálogo interno negativo</q> (como se menciona en <a href="http://www.affirmationsforpositivethinking.com"><cite>Afirmaciones para el pensamiento positivo</cite></a>).</p>'; +const solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + const scrollPos = textarea.scrollTop; + const caretPos = textarea.selectionStart; + + const front = (textarea.value).substring(0, caretPos); + const back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible_2', 700, 450, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Abreviaturas">Abreviaturas</h2> + +<p>Otro elemento bastante común que encontrarás cuando busques en la Web es {{HTMLElement("abbr")}} — se usa para envolver una abreviatura o acrónimo, y proporcionar una expansión completa del término (incluida dentro de un atributo {{HTMLAttrxRef("title")}}. Veamos un par de ejemplos:</p> + +<div id="ejemplo-de-abreviaturas-en-vivo"> +<pre class="brush: html notranslate"><p>Usamos <abbr title="Lenguaje de marcado de hipertexto">HTML</abbr> para estructurar nuestros documentos web.</p> + +<p>Creo que el <abbr title="Reverendo"">Rev.</abbr> Green lo hizo en la cocina con la motosierra.</p></pre> +</div> + +<p>Estos saldrán con un aspecto similar a este (la expansión aparecerá en una descripción emergente cuando se coloque el cursor sobre el término):</p> + +<p>{{EmbedLiveSample('ejemplo-de-abreviaturas-en-vivo', '100%', '94px', '', '', 'hide-codepen-jsfiddle')}}</p> + +<div class="note"> +<p><strong>Nota</strong>: Hay otro elemento, {{HTMLElement("acronym")}}, que básicamente hace lo mismo que <code><abbr></code>, y se diseñó específicamente para acrónimos en lugar de las abreviaturas. Sin embargo, este ha caído en desuso — no era compatible con los navegadores ni con <code><abbr></code>, y <code><abbr></code> tiene una función tan similar que se consideró inútil conservar ambos. Solo utiliza <code><abbr></code>.</p> +</div> + +<h3 id="Aprendizaje_activo_Marcar_una_abreviatura">Aprendizaje activo: Marcar una abreviatura</h3> + +<p>Para esta simple tarea de aprendizaje activo, nos gustaría que simplemente marcaras una abreviatura. Puedes usar el ejemplo que encontrarás a continuación o reemplazarla por una de tu elección. </p> + +<div class="hidden"> +<h6 id="Código_reproducible_3">Código reproducible</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 50px; width: 95%"> +<p>La NASA sin duda hace un interesante trabajo.</p> +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">const textarea = document.getElementById('code'); +const reset = document.getElementById('reset'); +const solution = document.getElementById('solution'); +const output = document.querySelector('.output'); +const code = textarea.value; +const userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +const htmlSolution = '<p>La <abbr title="Administración Nacional de Aeronáutica y del Espacio">NASA</abbr> sin duda hace un interesante trabajo.</p>'; +const solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + const scrollPos = textarea.scrollTop; + const caretPos = textarea.selectionStart; + + const front = (textarea.value).substring(0, caretPos); + const back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible_3', 700, 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Marcar_la_información_de_contacto">Marcar la información de contacto</h2> + +<p>HTML tiene un elemento para marcar la información de contacto — {{HTMLElement("address")}}. Este simplemente envuelve tus datos de contacto, por ejemplo:</p> + +<pre class="brush: html notranslate"><address> + <p>Chris Mills, Manchester, The Grim North, Reino Unido</p> +</address></pre> + +<p>También podrías incluir un marcado más complejo y otras formas de información de contacto, por ejemplo:</p> + +<pre class="brush: html notranslate"><address> + <p> + Chris Mills<br> + Manchester<br> + The Grim North<br> + Reino Unido + </p> + + <ul> + <li>Tel: 01234 567 890</li> + <li>Email: me@grim-north.co.uk</li> + </ul> +</address></pre> + +<p>Ten en cuenta que algo como esto también estaría bien, si la página vinculada contuviera la información de contacto:</p> + +<pre class="brush: html notranslate"><address> + <p>Página escrita por <a href="../authors/chris-mills/">Chris Mills</a>.</p> +</address></pre> + +<h2 id="Superíndice_y_subíndice">Superíndice y subíndice</h2> + +<p>En ocasiones, necesitarás utilizar superíndice y subíndice al marcar elementos como fechas, fórmulas químicas y ecuaciones matemáticas para que tengan el significado correcto. Los elementos {{HTMLElement("sup")}} y {{HTMLElement("sub")}} se ocupan de ello. Por ejemplo:</p> + +<pre class="brush: html notranslate"><p>Nací el 25<sup>th</sup> de mayo de 2001.</p> +<p>La fórmula química de la cafeína es C<sub>8</sub>H<sub>10</sub>N<sub>4</sub>O<sub>2</sub>.</p> +<p>If x<sup>2</sup> es 9, x debe ser igual 3 o -3.</p></pre> + +<p>La salida de este código se ve así:</p> + +<p>{{ EmbedLiveSample('Superíndice_y_subíndice', '100%', '141px', '', '', 'hide-codepen-jsfiddle') }}</p> + +<h2 id="Representación_del_código_informático">Representación del código informático</h2> + +<p>Hay una serie de elementos disponibles para marcar código informático usando HTML:</p> + +<ul> + <li>{{HTMLElement("code")}}: Para marcar fragmentos genéricos de código informático.</li> + <li>{{HTMLElement("pre")}}: Para respetar los espacios en blanco (en general, en los bloques de código) — si utilizas la sangría o diversos espacios en blanco consecutivos dentro de un texto, los navegadores los ignorarán y no se mostrarán en la página. Sin embargo, si delimitas el texto con las etiquetas <code><pre></pre></code>, los espacios en blanco se representarán de forma idéntica a como se ven en tu editor de texto.</li> + <li>{{HTMLElement("var")}}: Para marcar específicamente nombres de variables.</li> + <li>{{HTMLElement("kbd")}}: Para marcar entradas de teclado (y de otro tipo) en el ordenador.</li> + <li>{{HTMLElement("samp")}}: Para marcar la salida de un programa de ordenador.</li> +</ul> + +<p>Veamos algunos ejemplos. Deberías intentar jugar con estos (intenta obtener una copia de nuestro archivo de ejemplo <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/advanced-text-formatting/other-semantics.html">other-semantics.html</a>):</p> + +<pre class="brush: html notranslate"><pre><code>var para = document.querySelector('p'); + +para.onclick = function() { + alert('¡Guau!, ¡deja de apretar!'); +}</code></pre> + +<p>No debes utilizar elementos de presentación como <code>&lt;font&gt;</code> y <code>&lt;center&gt;</code>.</p> + +<p>En el ejemplo de JavaScript anterior, <var>para</var> representa un elemento de párrafo.</p> + + +<p>Selecciona todo el texto con <kbd>Ctrl</kbd>/<kbd>Cmd</kbd> + <kbd>A</kbd>.</p> + +<pre>$ <kbd>ping mozilla.org</kbd> +<samp>PING mozilla.org (63.245.215.20): 56 bytes de datos +64 bytes de 63.245.215.20: icmp_seq=0 ttl=40 time=158.233 ms</samp></pre></pre> + +<p>El código anterior se verá así:</p> + +<p>{{ EmbedLiveSample('Representación_del_código_informático','100%',300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Marcar_horas_y_fechas">Marcar horas y fechas</h2> + +<p>HTML también proporciona el elemento {{HTMLElement("time")}} para marcar horas y fechas en un formato legible por la máquina. Por ejemplo:</p> + +<pre class="brush: html notranslate"><time datetime="2016-01-20">20 Enero 2016</time> +</pre> + +<p>¿Por qué es útil esto? Bueno, hay muchas formas diferentes en que los humanos escriben las fechas. La fecha anterior se podría escribir como:</p> + +<ul> + <li>20 Enero 2016</li> + <li>20th January 2016</li> + <li>Ene 20 2016</li> + <li>20/01/16</li> + <li>01/20/16</li> + <li>El 20 del mes que viene</li> + <li><span lang="fr">20e Janvier 2016</span></li> + <li><span lang="ja">2016年1月20日</span></li> + <li>... y así sucesivamente ...</li> +</ul> + +<p>Pero estas diferentes formas no las pueden reconocer fácilmente las computadoras — ¿qué pasaría si quisieras tomar automáticamente las fechas de todos los eventos en una página e insertarlas en un calendario? El elemento {{HTMLElement("time")}} te permite adjuntar una fecha/hora inequívoca y legible por la máquina para este propósito.</p> + +<p>El ejemplo básico anterior solo proporciona una fecha simple legible por la máquina, pero hay muchas otras opciones que son posibles, por ejemplo:</p> + +<pre class="brush: html notranslate"><!-- Fecha simple estándar --> +<time datetime="2016-01-20">20 Enero 2016</time> +<!-- Solo año y mes --> +<time datetime="2016-01">Enero 2016</time> +<!-- Solo mes y día --> +<time datetime="01-20">20 Enero 2016</time> +<!-- Solo tiempo, horas y minutos --> +<time datetime="19:30">19:30</time> +<!-- ¡También puedes hacer segundos y milisegundos! --> +<time datetime="19:30:01.856">19:30:01.856</time> +<!-- Fecha y hora --> +<time datetime="2016-01-20T19:30">7.30pm, 20 Enero 2016</time> +<!-- Fecha y hora con desplazamiento de zona horaria --> +<time datetime="2016-01-20T19:30+01:00">7.30pm, 20 Enero 2016 es 8.30pm en Francia</time> +<!-- Llamar a un número de semana específico --> +<time datetime="2016-W04">La cuarta semana de 2016</time> +</pre> + +<h2 id="¡Pon_a_prueba_tus_habilidades!">¡Pon a prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo, pero ¿puedes recordar la información más importante? Puedes encontrar más pruebas para verificar que has retenido esta información antes de continuar; consulta {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Test_your_skills:_Advanced_HTML_text", "Pon a prueba tus habilidades: Texto HTML avanzado")}}.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Esto marca el final de nuestro estudio de la semántica del texto HTML. Ten en cuenta que lo que has visto durante este curso no es una lista exhaustiva de elementos de texto HTML — quisimos tratar de cubrir los aspectos esenciales y algunos de los más comunes que verás en la naturaleza, o al menos podrían resultarte interesantes. Para encontrar muchos más elementos HTML, puedes echarle un vistazo a nuestra {{web.link("/es/docs/Web/HTML/Element", "referencia de elementos HTML")}} (la {{web.link("/es/docs/Web/HTML/Element#Inline_text_semantics", "La sección Semántica de texto en línea")}} sería un gran lugar para comenzar). En el próximo artículo veremos los elementos HTML que usarás para estructurar las diferentes partes de un documento HTML.</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "¿Qué hay en el «head»? Metadatos en HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Fundamentos de texto HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Crear hipervínculos")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Formateo de texto avanzado")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Estructura web y documentación")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Depurar HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Marcado para una carta")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Estructuración del contenido de una página")}}</li> +</ul> diff --git a/files/es/learn/html/introduccion_a_html/creating_hyperlinks/index.html b/files/es/learn/html/introduccion_a_html/creating_hyperlinks/index.html new file mode 100644 index 0000000000..330bf0d7db --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/creating_hyperlinks/index.html @@ -0,0 +1,346 @@ +--- +title: Crear hipervínculos +slug: Learn/HTML/Introduccion_a_HTML/Creating_hyperlinks +tags: + - Aprender + - CodingScripting + - Guía + - HTML + - HTTP + - Novato + - Principiante + - Title + - URL + - enlace + - hiperenlaces + - hipervínculos + - href + - referencia absoluta + - referencia relativa + - título + - urls +translation_of: Learn/HTML/Introduction_to_HTML/Creating_hyperlinks +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">Los hipervínculos (o enlaces) son elementos verdaderamente importantes — son los que hacen que la web sea <em><strong>web</strong></em>. Este artículo expone la sintaxis necesaria para crear un enlace, además contiene un catálogo de buenas prácticas para crearlos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Estar familiarizado con HTML, cubierto en {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}. Aplicación de formato a texto en documentos HTML, según lo expuesto en la sección {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "fundamentos de texto HTML")}}.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a implementar un <em>hipervínculo</em> de forma efectiva y enlazar múltiples archivos.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_un_hipervínculo">¿Qué es un hipervínculo?</h2> + +<p>Los hipervínculos son una de las innovaciones más interesantes que ofrece la Web. Han formado parte de esta desde el principio, pero hacen que la web sea <em>web </em>: Los hipervínculos nos permiten vincular documentos a otros documentos o recursos, vincular a partes específicas de documentos o hacer que las aplicaciones estén disponibles en una dirección web. Prácticamente cualquier contenido web se puede convertir en un enlace que, al pulsarlo (activarlo), dirija el navegador a la dirección web a la que apunta el enlace ({{Glossary("URL")}}).</p> + +<div class="note"> +<p><strong>Nota</strong>: Una URL puede apuntar a archivos HTML, archivos de texto, imágenes, documentos de texto, archivos de audio o vídeo, y cualquier otra cosa que se pueda mostrar en la web. Si el navegador no sabe cómo manejar el archivo, te preguntará si lo quieres abrir (en cuyo caso la tarea de abrirlo y manejarlo se transferirá a la aplicación nativa instalada en el dispositivo) o si lo quieres descargar (en cuyo caso podrás ocuparte de él más tarde).</p> +</div> + +<p>El sitio web de la BBC, por ejemplo, contiene una gran cantidad de enlaces que apuntan a multitud de noticias en diferentes zonas de el sitio (funcionalidad de navegación), zonas de acceso/registro (herramientas de usuario) y otras.</p> + +<p><img alt="Portada de bbc.co.uk, que muestra muchas noticias y la funcionalidad del menú de navegación" src="https://mdn.mozillademos.org/files/12405/bbc-homepage.png" style="display: block; margin: 0 auto;"></p> + +<h2 id="Anatomía_de_un_enlace">Anatomía de un enlace</h2> + +<p>Un enlace básico se crea incluyendo el texto (o cualquier otro contenido, ve {{anch("Convertir bloques de contenido en enlaces")}}), que queramos convertir en un enlace usando un elemento ancla {{HTMLElement("a")}}, dándole un atributo {{HTMLAttrxRef("href", "a")}} (también conocido como «<strong><em>Hypertext Reference</em></strong>», «<strong><em>target</em></strong>» u <strong>objetivo</strong>) que contendrá la dirección web hacia dónde queremos que apunte el enlace.</p> + +<pre class="brush: html notranslate"><p>Crea un enlace a +<a href="https://www.mozilla.org/es-ES/">la página de inicio de Mozilla</a>. +</p></pre> + +<p>Este código producirá el siguiente resultado:</p> + +<p>Crea un enlace a <a class="ignore-external" href="https://www.mozilla.org/es-ES/">la página de inicio de Mozilla</a>.</p> + +<h3 id="Añadir_información_de_asistencia_con_el_atributo_title">Añadir información de asistencia con el atributo <code>title</code></h3> + +<p>Otro atributo que posiblemente quieras agregar a tus enlaces es <code>title</code>. El título contiene información adicional sobre el enlace, como qué tipo de información contiene la página o cosas que debes tener en cuenta en el sitio web.</p> + +<pre class="brush: html notranslate"><p>Crea un enlace a +<a href="https://www.mozilla.org/es-ES/" + title="El mejor lugar para encontrar más información acerca de la misión de Mozilla + y cómo contribuir">la página de inicio de Mozilla</a>. +</p></pre> + +<p>Este código producirá el siguiente resultado (el título se mostrará al pasar el ratón sobre el texto del enlace):</p> + +<p>Crea un enlace a <a class="ignore-external" href="https://www.mozilla.org/es-ES/" title="El mejor lugar para encontrar más información sobre la misión de Mozilla y cómo contribuir">la página de inicio de Mozilla</a>.</p> + +<div class="note"> +<p><strong>Nota</strong>: El título de un enlace solo será visible al pasar el ratón por encima, lo cual significa que los usuarios que naveguen usando los controles de sus teclados, o pantallas táctiles, tendrán dificultades para acceder a la información proporcionada por el título. Si la información del título es verdaderamente importante para el uso de la página, deberemos presentar el título de manera que sea accesible a todos los usuarios, por ejemplo incluyéndola como parte del texto del enlace.</p> +</div> + +<h3 id="Aprendizaje_activo_crea_tu_propio_ejemplo_de_enlace">Aprendizaje activo: crea tu propio ejemplo de enlace</h3> + +<p>Es momento del aprendizaje activo — crea un documento HTML con tu editor de código (nuestra <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">plantilla de aprendizaje</a> te hará la tarea más llevadera).</p> + +<ul> + <li>En el cuerpo del HTML (<code>body</code>), añade uno o más párrafos o cualquier otro tipo de contenido de los que ya conoces.</li> + <li>Convierte algún texto en enlaces.</li> + <li>Incluye atributos de título (<code>title</code>).</li> +</ul> + +<h3 id="Convertir_bloques_de_contenido_en_enlaces">Convertir bloques de contenido en enlaces</h3> + +<p>Como hemos mencionado anteriormente, puedes convertir cualquier contenido en un enlace, incluso {{web.link("/es/docs/Learn/HTML/Getting_started#Elementos_de_bloque_y_elementos_en_línea", "Elementos de bloque y elementos en línea")}}. Si quieres convertir una imagen en un enlace, simplemente usa el elemento {{HTMLElement("a")}} encerrando el elemento {{HTMLElement("img")}} entre <code><a></code> y <code></a></code>.</p> + +<pre class="brush: html notranslate"><a href="https://www.mozilla.org/es-ES/"> + <img src="mozilla-image.png" alt="Logotipo de Mozilla que dirige a la página inicial de Mozilla"> +</a></pre> + +<div class="note"> +<p><strong>Nota</strong>: Encontrarás mucho más sobre el manejo de imágenes en próximos artículos en esta web.</p> +</div> + +<h2 id="Primer_acercamiento_a_URLs_y_rutas">Primer acercamiento a URLs y rutas</h2> + +<p>Para comprender completamente a dónde apuntan los enlaces, necesitas conocer las URLs y las rutas. En esta sección encontrarás la información que necesitas sobre el tema.</p> + +<p>Una localizadora uniforme de recursos (URL, de las iniciales en inglés de «<em>Uniform Resource Locator</em>») es simplemente una secuencia de caracteres de texto que definen donde está situado algo en la web. Por ejemplo, la página de Mozilla está ubicada en <code>https://www.mozilla.org/es-ES/</code>.</p> + +<p>Las URLs utilizan rutas para encontrar los archivos. Las rutas especifican dónde se encuentra el archivo que buscas dentro del sistema de archivos. Veamos un ejemplo de una estructura de directorios (ve el directorio <a href="https://github.com/mdn/learning-area/tree/master/html/introduction-to-html/creating-hyperlinks">creating-hyperlinks</a>).</p> + +<p><img alt="Una estructura de directorios simple. El directorio principal se llama creating-hyperlinks y contiene dos archivos llamados index.html y contacts.html, y dos directorios llamados projects y pdfs, que contiene un archivo index.html y un archivo project-brief.pdf, respectivamente" src="https://mdn.mozillademos.org/files/12409/simple-directory.png" style="display: block; margin: 0 auto;"></p> + +<p>Al directorio <strong>raíz</strong> de esta estructura de directorios lo hemos llamado <code>creating-hyperlinks</code>. Al trabajar en modo local en una web, habrá un directorio que contendrá toda la información. En nuestro ejemplo, dentro de la raíz, encontramos el archivo <code>index.html</code> y el archivo <code>contacts.html</code>. En una web real, <code>index.html</code> es el punto de entrada a la web, lo que se conoce como <em>página de inicio</em>.</p> + +<p>Observamos también dos directorios dentro de nuestro directorio raíz que son: <code>pdfs</code> y <code>projects</code>. Cada uno de ellos tiene archivos en su interior — un archivo PDF (<code>project-brief.pdf</code>) y un archivo <code>index.html</code>, respectivamente. Observa que es posible tener sin problemas dos archivos <code>index.html</code> en un proyecto siempre y cuando se encuentren alojados en ubicaciones diferentes de nuestra estructura de archivos — muchos sitios web lo hacen. El segundo <code>index.html</code> será la página de inicio para la información relativa a los proyectos.</p> + +<ul> + <li> + <p><strong>En el mismo directorio</strong>: Si queremos incluir un hipervínculo dentro del archivo <code>index.html</code> (el <code>index.html</code> del nivel más alto) que apunte al archivo <code>contacts.html</code>, simplemente especificaremos el nombre del archivo al que hacemos referencia, porque se encuentra en el mismo directorio en el que se encuentra el archivo <code>index.html</code> desde donde lo queremos llamar. Por lo tanto, usamos la URL <code>contacts.html</code> — veamos el código:</p> + + <pre class="brush: html notranslate"><p>¿Quieres contactar con un miembro específico del personal? +Encuentra los detalles en nuestra <a href="contacts.html">página de contactos</a>.</p></pre> + </li> + <li> + <p><strong>Bajando por la estructura de subdirectorios</strong>: Si queremos incluir un hipervínculo dentro del archivo <code>index.html</code> (el <code>index.html</code> de nivel más alto) que apunta a <code>projects/index.html</code>, debemos bajar hasta el directorio <code>projects</code> antes de indicar al archivo al que queremos enlazar. Para ello especificamos el nombre del directorio y le añadimos una barra inclinada hacia adelante, y a continuación el nombre del archivo. Por lo tanto, utilizaremos la URL <code>projects/index.html</code>:</p> + + <pre class="brush: html notranslate"><p>Visita mi <a href="projects/index.html">página de inicio del proyecto</a>.</p></pre> + </li> + <li> + <p><strong>Subiendo por nuestro sistema de directorios</strong>: Si ahora queremos incluir un hipervínculo dentro del archivo <code>projects/index.html</code> que apunte a <code>pdfs/project-brief.pdf</code>, hay que subir un nivel en nuestro sistema de directorios, para luego bajar al directorio <code>pdf</code>. Para «Subir un nivel» utilizamos los dos puntos — (<code>..</code>) — por lo que usamos la URL <code>../pdfs/project-brief.pdf</code>:</p> + + <pre class="brush: html notranslate"><p>Un enlace a mi<a href="../pdfs/project-brief.pdf">resumen del proyecto</a>.</p></pre> + </li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Podemos combinar más de una instancia de estas características y generar URLs más complejas, si es necesario, por ejemplo: <code>../../../ruta/compleja/a/mi/archivo.html</code>.</p> +</div> + +<h3 id="Fragmentos_de_documento">Fragmentos de documento</h3> + +<p>Es posible apuntar hacia una parte concreta de un documento HTML en vez de a todo un documento. Para ello hay que asignar previamente un atributo {{HTMLAttrxRef("id")}} al elemento hacia el que apuntamos. Esto se debe hacer en el encabezado y quedará así:</p> + +<pre class="brush: html notranslate"><h2 id="Dirección_de_envío">Dirección de envío</h2></pre> + +<p>Posteriormente para hacer referencia a este <code>id</code> concreto, lo añadiremos al final de la URL precedido por una almohadilla — veamos el ejemplo:</p> + +<pre class="brush: html notranslate"><p>¿Quieres mandarnos una carta? Aquí tienes nuestra <a href="contacts.html#Dirección_de_envío">Dirección de envío</a>.</p></pre> + +<p>También podemos usar esta referencia a un fragmento de documento para apuntar hacia otra <em>parte del mismo documento</em>:</p> + +<pre class="brush: html notranslate"><p>La <a href="#Dirección_de_envío">Dirección de envío de la empresa</a> se encuentra al final de esta página.</p></pre> + +<h3 id="URLs_absolutas_y_relativas">URLs absolutas y relativas</h3> + +<p>Dos términos que encontrarás en la Web son <strong>URL absoluta</strong> y <strong>URL relativa:</strong></p> + +<p><strong>URL absoluta</strong>: Hace referencia a una dirección definida por su ubicación absoluta en la web, esta incluye el {{Glossary("protocol", "protocolo")}} y el {{Glossary("domain name", "nombre del dominio")}}. Por ejemplo, si subes una página de inicio <code>index.html</code> a un directorio llamado <code>projects</code> que se encuentra dentro de la raíz de un servidor web, y el dominio del sitio web es <code>http://www.example.com</code>, se podrá acceder a la página desde <code>http://www.example.com/projects/index.html</code> (o simplemente <code>http://www.example.com/projects/</code>, ya que la mayoría de los servidores web buscan la página de inicio <code>index.html</code> para cargarla por omisión si no se les especifica otra en la URL).</p> + +<p>Una URL absoluta siempre apuntará a la misma dirección, sin importar desde dónde se utilice.</p> + +<p>Una <strong>URL relativa</strong>: Hace referencia a una dirección que depende de la posición del archivo desde donde se utiliza — son las que vimos en la sección anterior. Por ejemplo, si desde un archivo ubicado en <code>http://www.example.com/projects/index.html</code> queremos enlazar hacia un archivo PDF ubicado en el mismo directorio, la URL sería simplemente el nombre del archivo (por ejemplo: <code>project-brief.pdf</code>) no necesitamos más información. Si el archivo PDF está situado en un subdirectorio dentro de <code>projects</code> llamado <code>pdfs</code>, la URL relativa es: <code>pdfs/project-brief.pdf</code> (la URL absoluta equivalente sería: <code>http://www.example.com/projects/pdfs/project-brief.pdf</code>).</p> + +<p>Una URL relativa hará referencia a diferentes direcciones según dónde se encuentre el archivo desde el cual se utiliza — por ejemplo, si movemos nuestro archivo <code>index.html</code> del directorio <code>projects</code> a la raíz del sitio web (el nivel más alto, no cualquiera de los otros directorios), la URL relativa <code>pdfs/project-brief.pdf</code> ahora hará referencia a <code>http://www.example.com/pdfs/project-brief.pdf</code>, en lugar de a <code>http://www.example.com/projects/pdfs/project-brief.pdf</code>.</p> + +<p>Por supuesto, la ubicación del archivo <code>pdfs/project-brief.pdf</code> y del directorio <code>pdfs</code> no cambian de repente cuando mueves el archivo <code>index.html</code>; esto hará que tus enlaces apunten a un sitio equivocado y no funcionarán correctamente al hacer clic en ellos. ¡Por lo tanto debes tener cuidado!</p> + +<h2 id="Buenas_prácticas_en_el_uso_de_los_enlaces">Buenas prácticas en el uso de los enlaces</h2> + +<p>Hay algunas buenas prácticas que debemos respetar cuando escribimos enlaces. Veamos cuáles son.</p> + +<ul> +</ul> + +<h3 id="Redacción_clara_del_enlace">Redacción clara del enlace</h3> + +<p>Es fácil rellenar de enlaces una página, sin más. Pero esto no basta. Hay que lograr que nuestros enlaces sean <em>accesibles</em> para todo tipo de lectores, sin importar el contexto o las herramientas que prefieran. Por ejemplo:</p> + +<ul> + <li>Los usuarios de lectores de pantalla suelen saltar de enlace a enlace en la página y los leen todos sin contexto.</li> + <li>Los motores de búsqueda utilizan el texto de los enlaces para indizar los archivos buscados, por lo que es una buena idea incluir palabras clave al definir el texto de los enlaces para describir de forma efectiva el sitio al que apuntan.</li> + <li>Los usuarios visuales suelen echar un vistazo rápido a la página y leen solo lo que les interesa, en lugar de leer todo el texto palabra por palabra, y sus miradas van directamente a las características destacadas de la página, como son los enlaces. Este tipo de usuarios encuentra útiles los textos descriptivos que estos contienen.</li> +</ul> + +<p>Veamos un ejemplo concreto:</p> + +<p><em><strong>Buen</strong> texto en un enlace</em>: <a href="https://firefox.com">Descargar Firefox</a></p> + +<pre class="brush: html notranslate"><p><a href="https://firefox.com/"> + Descargar Firefox +</a></p></pre> + +<p><em><strong>Mal</strong> texto en un enlace</em>: <a href="https://firefox.com/">Pulsar aquí</a> para descargar Firefox</p> + +<pre class="brush: html notranslate"><p><a href="https://firefox.com/"> + Haz clic aquí +</a> +para descargar Firefox</p> +</pre> + +<p>Otras indicaciones:</p> + +<ul> + <li>No repetir la URL como parte del texto — Las URLs suenan horrible, y todavía suenan peor si las lee un lector de pantalla, letra por letra.</li> + <li>No escribir «<em>link</em>» o «<em>link a</em>» o «enlace» o «enlace a» en el texto del enlace porque es redundante. Los lectores automáticos indican que hay un enlace al encontrarlo. Los usuarios también saben que hay un enlace, porque normalmente se suele cambiar el color del texto y se subraya (no hay que romper esta convención, porque los usuarios están acostumbrados a ella).</li> + <li>Redacta la etiqueta del enlace de la manera más breve y concisa posible — los textos de enlace largos son especialmente molestos para los usuarios que utilizan lectores automáticos, porque tienen que escuchar todo el texto del enlace.</li> + <li>Minimiza los casos en los que varias copias del mismo texto están vinculadas a diferentes lugares. Esto puede causar problemas a los usuarios de lectores de pantalla, si hay una lista de enlaces fuera de contexto que están etiquetados como "haz clic aquí", "haz clic aquí", "haz clic aquí".</li> +</ul> + +<h3 id="Utiliza_enlaces_relativos_siempre_que_sea_posible">Utiliza enlaces relativos siempre que sea posible</h3> + +<p>A partir de las indicaciones anteriores podemos llegar a pensar que es mejor utilizar referencias absolutas en todos los casos; después de todo, estas no se rompen cuando la página se traslada como ocurre con las referencias relativas. Sin embargo, debes utilizar enlaces relativos siempre que sea posible cuando enlaces a otras ubicaciones dentro del <em>mismo sitio web</em>. Cuando vinculas a otro sitio web, deberás utilizar un vínculo absoluto.</p> + +<ul> + <li>Primero, porque el código es mucho más fácil de leer — las URLs relativas suelen ser mucho más cortas que las absolutas, lo que hace que el código sea mucho más fácil de leer.</li> + <li>Segundo, resulta más eficiente utilizar URLs relativas cuando sea posible. Cuando usas una URL absoluta, el navegador comienza buscando la ubicación real del servidor en el Sistema de nombres de dominio ({{Glossary("DNS")}}), consulta {{web.link("/es/docs/Learn/Getting_started_with_the_web/How_the_Web_works", "Cómo funciona la web")}} para obtener más información). Entonces va a ese servidor y busca el archivo solicitado. En cambio, con una URL relativa, el navegador simplemente busca el archivo solicitado en el mismo servidor. Si usas URLs absolutas donde las URLs relativas lo harían, constantemente estás haciendo que tu navegador haga un trabajo adicional, lo cual significa que funcionará de manera menos eficiente.</li> +</ul> + +<h3 id="Indica_claramente_los_recursos_no_HTML">Indica claramente los recursos no HTML</h3> + +<p>Cuando damos referencias a recursos para descargarlos (como documentos en formato PDF o Word) o para reproducirlos (como archivos de audio o vídeo) o que tengan un efecto inesperado (una ventana emergente) hay que indicarlo para no confundir al usuario.</p> + +<p>Por ejemplo:</p> + +<ul> + <li>Si tienes una conexión con poco ancho de banda, pulsas un enlace y comienza a descargar un archivo pesado de forma inesperada.</li> + <li>Si no tienes instalado el reproductor Flash, pulsas un enlace y te conduce a una página que requiere Flash.</li> +</ul> + +<p>Veamos algunos ejemplos, para ver qué texto puede ser aconsejable en estos casos:</p> + +<pre class="brush: html notranslate"><p><a href="http://www.example.com/large-report.pdf"> + Descarga el informe de ventas (PDF, 10MB) +</a></p> + +<p><a href="http://www.example.com/video-stream/"> + Reproduce el vídeo (el flujo de datos se abre en una pestaña independiente, calidad HD) +</a></p> + +<p><a href="http://www.example.com/car-game"> + Juega al juego del automóvil (requiere Flash) +</a></p></pre> + +<h3 id="Utiliza_el_atributo_download_al_enlazar_una_descarga">Utiliza el atributo <code>download</code> al enlazar una descarga</h3> + +<p>Si queremos hacer referencia a una descarga en lugar de a algo que abra el navegador, disponemos del atributo <code>download</code> para proporcionar un nombre predeterminado al archivo a guardar. Veamos un ejemplo con un enlace a la descarga de la versión para Windows de Firefox:</p> + +<pre class="brush: html notranslate"><a href="https://download.mozilla.org/?product=firefox-latest-ssl&os=win64&lang=es-MX" + download="firefox-latest-64bit-installer.exe"> + Descarga la última versión de Firefox para Windows (64 bits) (Español, es-MX) +</a></pre> + +<h2 id="Aprendizaje_activo_crear_un_menú_de_navegación">Aprendizaje activo: crear un menú de navegación</h2> + +<p>Para este ejercicio, deberás crear lo que se conoce como <em>web multipágina</em>: un menú de navegación con enlaces a distintas páginas. Esta es una manera común de crear páginas web — usamos la misma estructura en todas las páginas, incluida la que contiene el menú de navegación. Cuando los usuarios pulsen los enlaces tendrán la sensación de que están en la misma página y que solo cambia el contenido mostrado.</p> + +<p>Tendrás que hacer copias locales, en el mismo directorio, de las cuatro siguientes páginas (revisa el directorio <a href="https://github.com/mdn/learning-area/tree/master/html/introduction-to-html/navigation-menu-start">navigation-menu-start</a> para el listado completo):</p> + +<ul> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/navigation-menu-start/index.html">index.html</a></li> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/navigation-menu-start/projects.html">projects.html</a></li> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/navigation-menu-start/pictures.html">pictures.html</a></li> + <li><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/navigation-menu-start/social.html">social.html</a></li> +</ul> + +<p>A continuación:</p> + +<ol> + <li>Añade una lista no ordenada en el lugar adecuado de la página, que contenga los nombres de las páginas a las que enlazas. Un menú de navegación normalmente es una lista de enlaces (<em>links</em>), por lo que esto es semánticamente correcto.</li> + <li>Convierte cada nombre en un enlace a esa página.</li> + <li>Copia el menú de navegación en cada una de las páginas.</li> + <li>En cada página, elimina solo el enlace que hace referencia a sí mismo (es confuso y no tiene sentido que una página se llame a sí misma, y la falta del enlace actúa como recordatorio de la página en la que se está en cada momento).</li> +</ol> + +<p>El ejercicio terminado debería crear una página como la siguiente:</p> + +<p><img alt="Un ejemplo de un menú de navegación HTML simple, con inicio, imágenes, proyectos y elementos del menú social" src="https://mdn.mozillademos.org/files/12411/navigation-example.png" style="display: block; margin: 0 auto;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Si ahora encallas, o no estás seguro de haberlo conseguido, revisa el directorio <a href="https://github.com/mdn/learning-area/tree/master/html/introduction-to-html/navigation-menu-marked-up">navigation-menu-marked-up</a> para ver la respuesta correcta.</p> +</div> + +<h2 id="Enlace_a_correo_electrónico">Enlace a correo electrónico</h2> + +<p>Es posible crear enlaces o botones que, cuando se pulsan, abren un nuevo correo saliente en lugar de enlazar a un recurso o página. Esto se consigue con el elemento ancla {{HTMLElement("a")}} y el elemento <code>mailto:</code> seguido del esquema de la URL.</p> + +<p>En su forma más básica, un enlace <code>mailto:</code> simplemente contiene la dirección de correo electrónico de los destinatarios. Por ejemplo:</p> + +<pre class="brush: html notranslate"><a href="mailto:nowhere@mozilla.org">Enviar correo electrónico a ninguna parte</a> +</pre> + +<p>Esto da como resultado un enlace que se ve así: <a href="mailto:nowhere@mozilla.org"> Enviar correo electrónico a ninguna parte</a>.</p> + +<p>De hecho, incluso el atributo con la dirección de correo electrónico es opcional. Si lo omites y tu ({{HTMLAttrxRef("href", "a")}} simplemente es "mailto:", aparecerá una nueva ventana de correo saliente en el gestor de correo sin la dirección del destinatario. Esto es útil cuando queremos compartir enlaces que los usuarios puedan pulsar para enviar un correo electrónico y elegir un destinatario posteriormente.</p> + +<h3 id="Especificar_detalles">Especificar detalles</h3> + +<p>Además de la dirección de correo electrónico, puedes proporcionar otra información. De hecho, puedes incluir cualquier campo estándar contenido en el encabezado de cualquier mensaje en la URL <code>mailto</code> que proporciones. Los más utilizados son el «<code>subject</code>» (asunto), «<code>cc</code>» (con copia a) o «<code>bcc</code>» (copia oculta), y «<code>body</code>» (cuerpo del mensaje, que no es realmente un campo de la cabecera, pero permite especificar un mensaje breve para el nuevo correo electrónico). Cada campo y su valor se especifican como un argumento de la consulta.</p> + +<p>Veamos un ejemplo que incluye estos campos:</p> + +<pre class="brush: html notranslate"><a href="mailto:nowhere@mozilla.org?cc=name2@rapidtables.com&bcc=name3@rapidtables.com&subject=The%20subject%20of%20the%20email&body=The%20body%20of%20the%20email"> + Enviar un correo electrónico cc, bcc, asunto y cuerpo +</a></pre> + +<div class="note"> +<p><strong>Nota</strong>: Los valores de cada campo deben tener la URL codificada, es decir, sin caracteres no imprimibles (caracteres invisibles, tabulaciones, retornos de carro y saltos de página) y espacios con codificación porcentual (%20) {{Interwiki("wikipedia", "Código porciento")}}. También hay que tener en cuenta el uso del signo de interrogación (?) para separar la URL principal de los valores de los campos, y el símbolo ampersand (&) para separar cada campo dentro del enlace <code>mailto:</code>. Esta es la notación de consulta URL estándar. Lee {{web.link("/es/docs/Learn/HTML/Forms/Sending_and_retrieving_form_data#The_GET_method", "el método GET")}} para comprender mejor qué notación de consulta URL se usa comúnmente.</p> +</div> + +<p>A continuación otros ejemplos de utilización de enlaces <code>mailto</code>:</p> + +<ul> + <li><a href="mailto:">mailto:</a></li> + <li><a href="mailto:nowhere@mozilla.org">mailto:nowhere@mozilla.org</a></li> + <li><a href="mailto:nowhere@mozilla.org,nobody@mozilla.org">mailto:nowhere@mozilla.org,nobody@mozilla.org</a></li> + <li><a href="mailto:nowhere@mozilla.org?cc=nobody@mozilla.org">mailto:nowhere@mozilla.org?cc=nobody@mozilla.org</a></li> + <li><a href="mailto:nowhere@mozilla.org?cc=nobody@mozilla.org&subject=This%20is%20the%20subject">mailto:nowhere@mozilla.org?cc=nobody@mozilla.org&subject=This%20is%20the%20subject</a></li> +</ul> + +<h2 id="¡Pon_a_prueba_tus_habilidades!">¡Pon a prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo, pero ¿puedes recordar la información más importante? Encuentra más ejercicios con los que comprobar que has retenido esta información antes de seguir adelante; consulta {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Test_your_skills:_Links", "Pon a prueba tus habilidades: Enlaces")}}.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Eso es todo en cuanto a enlaces, ¡por ahora! Volveremos a ellos más tarde en este curso cuando comencemos a usar estilos. Lo siguiente en HTML, será aprender la semántica de texto para usar algunas características avanzadas/inusuales que nos serán utilidad — Formato de texto avanzado será la próxima parada.</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "¿Qué hay en el «head»? Metadatos en HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Fundamentos de texto HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Crear hipervínculos")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Formateo de texto avanzado")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Estructura web y documentación")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Depurar HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Marcado para una carta")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Estructuración del contenido de una página")}}</li> +</ul> diff --git a/files/es/learn/html/introduccion_a_html/debugging_html/index.html b/files/es/learn/html/introduccion_a_html/debugging_html/index.html new file mode 100644 index 0000000000..114b93ff0f --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/debugging_html/index.html @@ -0,0 +1,171 @@ +--- +title: Depurar el HTML +slug: Learn/HTML/Introduccion_a_HTML/Debugging_HTML +tags: + - Error + - Guía + - HTML + - Principiante + - Validación + - Validador + - depurar + - programar +translation_of: Learn/HTML/Introduction_to_HTML/Debugging_HTML +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">Escribir HTML es fácil, pero ¿qué pasa si algo va mal y desconocemos dónde está el error de codificación? En este artículo veremos varias herramientas que nos ayudarán a arreglar errores en HTML.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Estar familiarizado con los principios básicos de HTML, como los vistos en el apartado <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/iniciar">Empezar con el HTML</a>, <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/texto">Conocimientos básicos de aplicación de formato a textos con HTML</a> y <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/Creating_hyperlinks">Creación de hiperenlaces</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender el funcionamiento básico de las herramientas de depuración de problemas de código en HTML.</td> + </tr> + </tbody> +</table> + +<h2 id="Depurar_no_debe_asustarnos">Depurar no debe asustarnos</h2> + +<p>Cuando escribimos cualquier tipo de código, normalmente todo va bien, hasta ese fatídico momento en el que ocurre un error, hemos hecho algo mal y el código no funciona, o no funciona del todo, no lo suficientemente bien. Por ejemplo, el dibujo siguiente muestra un error de {{glossary("compile","compilación")}} de un programa sencillo escrito en lenguaje <a href="https://www.rust-lang.org/">Rust</a>.</p> + +<p><img alt="A console window showing the result of trying to compile a rust program with a missing quote around a string in a print statement. The error message reported is error: unterminated double quote string." src="https://mdn.mozillademos.org/files/12435/error-message.png" style="display: block; height: 520px; margin: 0px auto; width: 711px;">En el ejemplo, el mensaje de error es fácilmente comprensible: "unterminated double quote string" (comillas sin cerrar en el texto). Si analizamos el listado de código, observamos que en <code>println!(Hello, world!");</code> faltan una comillas. Pero, los mensajes de error pueden complicarse con facilidad y su interpretación ser menos sencilla a medida que los programas aumentan en tamaño, e incluso casos sencillo pueden llegar a intimidar a alguien que no sabe nada de Rust.</p> + +<p>Sin embargo, la depuración no nos debe asustar; la clave para sentirnos cómodos con la escritura y la depuración de cualquier lenguaje o código es la familiaridad, tanto con el lenguaje como con las herramientas.</p> + +<h2 id="HTML_y_depuración">HTML y depuración</h2> + +<p>HTML no es tan complicado de entender como Rust; HTML no se compila por separado antes de que el navegador lo analice (se interpreta, no se compila). Y la sintaxis de los {{glossary("element","elementos")}} de HTML es mucho más sencilla de entender que la de cualquier lenguaje de programación real como Rust, {{glossary("JavaScript")}} o {{glossary("Python")}}. La forma en que los navegadores ejecutan HTML es más <strong>permisiva</strong> que la de los otros lenguajes, cosa que es buena y mala a la vez.</p> + +<h3 id="Código_permisivo">Código permisivo</h3> + +<p>¿Qué queremos decir con <em>permisivo</em>? Bien, normalmente cuando hacemos algo mal al codificar, suele haber dos tipos de error:</p> + +<ul> + <li><strong>Errores sintácticos</strong>: Son errores de escritura en el código que impiden que el programa funcione, como el error en Rust de arriba. Suelen ser fáciles de arreglar si estamos familiarizados con las herramientas adecuadas y sabemos el significado de los mensajes de error.</li> + <li><strong>Errores lógicos</strong>: En estos errores la sintaxis es correcta, pero el código no hace lo que debería, por lo que el programa funciona de forma incorrecta. Estos errores son, por lo general, más difíciles de solucionar que los sintácticos, porque no hay mensajes de error que nos avisen de ellos.</li> +</ul> + +<p>HTML en sí mismo no suele producir errores sintácticos porque los navegadores son permisivos con ellos; o sea, el código se sigue ejecutando ¡aun si hay errores! Los navegadores disponen de reglas internas para saber cómo interpretar los errores de marcado incorrecto que encuentran, y seguirán funcionando aunque no produzcan el resultado esperado. Esto puede también ser un problema, por supuesto.</p> + +<div class="note"> +<p><strong>Nota</strong>: La ejecución de HTML es permisiva porque cuando se creó la web por primera vez, se decidió que el hecho de permitir que la gente publicara su contenido era más importante que el hecho de que la sintaxis fuera totalmente correcta. La web no sería tan popular como lo es hoy en día si se hubiera sido más estricto desde el primer momento.</p> +</div> + +<h3 id="Aprendizaje_activo_Estudio_del_código_permisivo">Aprendizaje activo: Estudio del código permisivo</h3> + +<p>Es hora de estudiar la naturaleza permisiva del código HTML por nosotros mismos.</p> + +<ol> + <li>En primer lugar, hagamos una copia de nuestro <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/debugging-html/debug-example.html">ejemplo-demo a depurar</a> y guardémoslo de forma local. Está escrito para generar diversos errores que deberemos descubrir (se dice que el marcado de HTML está <strong>mal formado</strong>, en contraposición a un marcado <strong>bien formado</strong>).</li> + <li>A continuación, abrámoslo en un navegador; veremos lo siguiente:<img alt="A simple HTML document with a title of HTML debugging examples, and some information about common HTML errors, such as unclosed elements, badly nested elements, and unclosed attributes. " src="https://mdn.mozillademos.org/files/12437/badly-formed-html.png" style="display: block; margin: 0 auto;"></li> + <li>No parece que esté bien; veamos el código fuente para ver qué podemos hacer (solo mostramos el contenido del <body>): + <pre class="brush: html notranslate"><h1>HTML debugging examples</h1> + +<p>What causes errors in HTML? + +<ul> + <li>Unclosed elements: If an element is <strong>not closed properly, + then its effect can spread to areas you didn't intend + + <li>Badly nested elements: Nesting elements properly is also very important + for code behaving correctly. <strong>strong <em>strong emphasised?</strong> + what is this?</em> + + <li>Unclosed attributes: Another common source of HTML problems. Let's + look at an example: <a href="https://www.mozilla.org/>link to Mozilla + homepage</a> +</ul></pre> + </li> + <li>Veamos qué problemas podemos descubrir: + <ul> + <li>El elemento {{htmlelement("p")}} y el {{htmlelement("li")}} no tienen etiquetas de cierre. Si comprobamos el resultado, no parece que haya generado un efecto grave en la representación del lenguaje de marcado, porque es fácil deducir que donde un elemento acaba, debería comenzar otro.</li> + <li>El primer elemento {{htmlelement("strong")}} no tiene etiqueta de cierre. Este resulta ser un poco más problemático porque no es fácil deducir dónde se supone que termina el elemento. De hecho, el énfasis fuerte se ha aplicado al resto del texto.</li> + <li>Esta sección está mal anidada: <code><strong>strong <em>strong emphasised?</strong> what is this?</em></code>. No es fácil de explicar la forma en que ha sido interpretado, debido al problema anterior.</li> + <li>Al valor del atributo {{htmlattrxref("href","a")}} le faltan las comillas de cierre. Esto parece haber causado el problema más grave: el enlace ha desaparecido totalmente.</li> + </ul> + </li> + <li>Ahora veamos lo que el navegador ha mostrado en contraposición al código fuente. Para ello podemos usar las herramientas de desarrollo del navegador. Si no estamos familiarizados con el uso de estas herramientas, echemos un vistazo rápido a <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">Descubrir las herramientas de desarrollo del navegador</a>, y luego continuaremos.</li> + <li>En el inspector de objetos (DOM), puedes comprobar la apariencia de cada elemento: <img alt="The HTML inspector in Firefox, with our example's paragraph highlighted, showing the text "What causes errors in HTML?" Here you can see that the paragraph element has been closed by the browser." src="https://mdn.mozillademos.org/files/12439/html-inspector.png" style="display: block; margin: 0 auto;"></li> + <li>Vamos a explorar nuestro código en detalle con el inspector de objetos DOM para ver cómo el navegador ha arreglado nuestros errores de código HTML (lo hemos hecho con Firefox; otros navegadores modernos deberían conducir al mismo resultado): + <ul> + <li>Se han añadido etiquetas de cierre a los párrafos y las líneas de las listas.</li> + <li>Al no estar claro el final del elemento <code><strong></code>, el navegador lo ha aplicado individualmente a todos los bloques de texto siguientes, a cada uno le ha añadido su etiqueta <code>strong</code> propia, desde donde está ¡hasta el final del documento!</li> + <li>El navegador ha arreglado el anidamiento incorrecto del modo siguiente: + <pre class="brush: html notranslate"><strong>strong + <em>strong emphasised?</em> +</strong> +<em> what is this?</em></pre> + </li> + <li>El enlace a cuyo atributo le faltan las comillas del final ha sido ignorado. La última lista la ha dejado como sigue: + <pre class="brush: html notranslate"><li> + <strong>Unclosed attributes: Another common source of HTML problems. + Let's look at an example: </strong> +</li></pre> + </li> + </ul> + </li> +</ol> + +<h3 id="Validación_HTML">Validación HTML</h3> + +<p>Con el ejemplo anterior podemos asegurarnos de que nuestro HTML está bien formado, pero ¿cómo? En el ejemplo siguiente podemos comprobar que es bastante fácil buscar entre las líneas y encontrar los errores en documentos pequeños; pero, ¿qué pasa cuando trabajamos con documentos HTML grandes y complejos?</p> + +<p>La mejor estrategia es comenzar por pasar tu página HTML por el <a href="https://validator.w3.org/">servicio de validación de etiquetas</a>; fue creado y está mantenido por el W3C, organización que se encarga de definir las especificaciones de HTML, CSS y otras tecnologías web. Esta página web toma un documento HTML como entrada, lo procesa, y genera un informe de dónde están los errores en el documento.</p> + +<p><img alt="The HTML validator homepage" src="https://mdn.mozillademos.org/files/12441/validator.png" style="display: block; margin: 0 auto;"></p> + +<p>Para validar el HTML, podemos proporcionar al validador una dirección web a la que apuntar, subirle un archivo HTML, o directamente introducirle el código HTML que queremos que revise.</p> + +<h3 id="Aprendizaje_activo_Validación_de_un_documento_HTML">Aprendizaje activo: Validación de un documento HTML</h3> + +<p align="left">Vamos a probar de validar nuestro <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/debugging-html/debug-example.html">documento ejemplo</a>.</p> + +<ol> + <li>Primero, cargamos el <a href="https://validator.w3.org/">servicio de validación</a> en una pestaña del navegador, si no lo tenemos ya.</li> + <li>Hacemos clic en la subpestaña <a href="https://validator.w3.org/#validate_by_input">Validate by Direct Input</a>.</li> + <li>Copiamos el código del documento ejemplo (no solo el <code>body</code>) y lo pegamos en el cuadro de texto grande.</li> + <li>Hacemos clic en el botón <em>Check</em>.</li> +</ol> + +<p>Esto debería proporcionar una lista de errores y otras informaciones:</p> + +<p><img alt="A list of of HTML validation results from the W3C markup validation service" src="https://mdn.mozillademos.org/files/12443/validation-results.png" style="display: block; margin: 0 auto;"></p> + +<h4 id="Interpretación_de_los_mensajes_de_error">Interpretación de los mensajes de error</h4> + +<p>La lista de mensajes de error que nos presenta el validador suele ayudar, pero a veces, no resultan muy útiles; con un poco de práctica aprenderemos a interpretar la lista para arreglar nuestro código. Veamos los mensajes de error y su significado. Observamos que cada mensaje se presenta con un número de línea y de columna, para ayudar a localizar el error más fácilmente.</p> + +<ul> + <li>"<span>Consider adding a </span><code>lang</code><span> attribute to the </span><code>html</code><span> start tag to declare the language of this document.": No se trata de un error, sino de una advertencia (warning). La <a class="external external-icon" href="https://www.w3.org/International/questions/qa-html-language-declarations" rel="noopener">recomendación</a> es definir siempre un idioma, y este "warning" explica cómo hacerlo..</span></li> + <li>"End tag <code>li</code> implied, but there were open elements" (2 instancias): Estos mensajes indican que un elemento que ha sido abierto debe ser cerrado. La etiqueta de cierre se supone, pero no está ahí. La información de la línea/columna apunta a la primera línea después de donde debería estar la etiqueta de cierre; es una buena pista para ver qué pasa.</li> + <li>"Unclosed element <code>strong</code>": Un elemento {{htmlelement("strong")}} no ha sido cerrado, y la línea/columna apunta directamente al lugar del error.</li> + <li>"End tag <code>strong</code> violates nesting rules": Este apunta a elementos que están incorrectamente anidados, y la línea/columna nos indica donde están.</li> + <li>"End of file reached when inside an attribute value. Ignoring tag": Esta es bastante enigmática; se refiere al hecho de que el valor de un atributo no ha sido bien construido, posiblemente cerca del final del archivo porque el final aparece dentro del valor del atributo. El hecho de que el navegador no muestre el enlace nos debería dar una buena pista de qué elemento es el erróneo.</li> + <li>"End of file seen and there were open elements": Este es un poco ambiguo, pero básicamente se refiere al hecho de que hay elementos abiertos que necesitan ser cerrados adecuadamente. Los números de línea apuntan a las últimas líneas del archivo, y este mensaje de error viene con una línea de código que indica un ejemplo de un elemento abierto: + <pre class="notranslate">example: <a href="https://www.mozilla.org/>link to Mozilla homepage</a> ↩ </ul>↩ </body>↩</html></pre> + + <div class="note"> + <p><strong>Nota</strong>: Un atributo al que le falten las comillas de cierre puede ser un elemento abierto, porque el resto del documento será interpretado como si fuera parte de este atributo.</p> + </div> + </li> + <li>Unclosed element <code>ul</code>: Este no ayuda mucho, porque el elemento {{htmlelement("ul")}} está cerrado correctamente. Este error se debe a que el elemento {{htmlelement("a")}} no ha sido cerrado, ya que faltan las comillas de cierre.</li> +</ul> + +<p><span>No debemos preocuparnos si no podemos corregir todos los mensajes de error; es práctico tratar de arreglar unos pocos errores cada vez y volver a pasar el validador para ver los que quedan. A veces, al arreglar unos cuantos se arreglan automáticamente otros muchos; con frecuencia muchos errores los causa uno solo en un efecto dominó.</span></p> + +<p><span>Sabremos que todos los errores están arreglados cuando veamos el mensaje siguiente: </span></p> + +<p><img alt='Banner that reads "The document validates according to the specified schema(s) and to additional constraints checked by the validator."' src="https://mdn.mozillademos.org/files/12445/valid-html-banner.png" style="display: block; margin: 0 auto;"></p> + +<h2 id="Resumen">Resumen</h2> + +<p>Pues hasta aquí una introducción al depurado de HTML, que nos proporcionará habilidades para cuando comencemos a depurar CSS, JavaScript y otros lenguajes más adelante en nuestros trabajos. Este apartado también constituye el final de la introducción al módulo de artículos de aprendizaje de HTML; ahora podemos hacer los test de prueba: el primero de los cuales está en el enlace siguiente.</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}</p> diff --git a/files/es/learn/html/introduccion_a_html/estructura/index.html b/files/es/learn/html/introduccion_a_html/estructura/index.html new file mode 100644 index 0000000000..1f5f1e315c --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/estructura/index.html @@ -0,0 +1,298 @@ +--- +title: Estructura web y documentación +slug: Learn/HTML/Introduccion_a_HTML/estructura +tags: + - CodingScripting + - Composición + - Diseño + - Formato + - Guía + - HTML + - Presentación + - Principiante + - Sitio + - Sitio Web + - bloques + - pagina + - programar + - semántica +translation_of: Learn/HTML/Introduction_to_HTML/Document_and_website_structure +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">Además de definir partes individuales de tu página (como un párrafo o una imagen), {{Glossary("HTML")}} también dispone de elementos de bloque que se pueden utilizar para estructurar las distintas áreas de tu sito web (tal como el encabezado, el menú de navegación o la parte del contenido principal. En este artículo veras cómo planificar una estructura básica de página web y escribirás el HTML que representa esa estructura.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Estar familiarizado con HTML, cubierto en {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}. Aplicación de formato a texto en documentos HTML, según lo expuesto en la sección {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Fundamentos de texto HTML")}}. Funcionamiento de los hipervínculos, cubierto en {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Crear hipervínculos")}}.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a estructurar tu documento usando atributos semánticos y construir la estructura de una página web sencilla.</td> + </tr> + </tbody> +</table> + +<h2 id="Partes_básicas_de_un_documento">Partes básicas de un documento</h2> + +<p>Las páginas web pueden y se deben diferenciar las unas de las otras, pero todas tienden a contener elementos comunes parecidos, a menos que estén destinadas a mostrar un vídeo o un juego a pantalla completa, o que formen parte de un proyecto artístico concreto o, simplemente, que estén mal estructuradas; estos elementos comunes son:</p> + +<dl> + <dt>encabezado:</dt> + <dd>Normalmente formado por una gran franja que cruza la parte superior de la página con un <strong>gran título</strong>, un logotipo y quizás un lema. Esta parte suele permanecer invariable mientras navegas entre las páginas de un mismo sitio web.</dd> + <dt>barra de navegación:</dt> + <dd>Son los enlaces a las secciones principales del sitio web. Normalmente está formada por un menú con botones, enlaces o pestañas. Al igual que el <em>encabezado</em>, este contenido suele permanecer invariable en las diferentes páginas del sitio; tener un menú inconsistente en tu página web conducirá a los usuarios a la confusión y frustración. Muchos diseñadores web consideran que el menú de navegación forma parte del encabezado y que no posee un componente individual, aunque no es necesario que sea así; de hecho, algunos argumentan que tener ambos componentes por separado es mejor por motivos de {{web.link("/es/docs/Learn/Accessibility", "accesibilidad")}} porque los lectores de pantalla pueden leer mejor ambos elementos si están separados.</dd> + <dt>contenido principal:</dt> + <dd>Es la gran parte central de la página y contiene la mayor parte del contenido particular de una página web concreta; por ejemplo, el video que quieres ver, la narración que quieres leer, el mapa que quieres consultar, los titulares de las noticias, etc. ¡Esta es la parte que definitivamente debe variar mucho de una página a otra de tu sitio web!</dd> + <dt>barra lateral:</dt> + <dd>Suele incluir algún tipo de información adicional, enlaces, citas, publicidad, etc. Normalmente está relacionada con el contenido principal de la página (por ejemplo, en una página de noticias, la barra lateral podría contener la biografía del autor o enlaces a artículos relacionados), pero en otras ocasiones encontraras elementos recurrentes como un menú de navegación secundario.</dd> + <dt>pie de página:</dt> + <dd>Es la parte inferior de la página, que generalmente contiene la letra pequeña, el copyright o la información de contacto. Es el sitio donde se coloca la información común (al igual que en el encabezado), pero esta información no suele ser tan importante o es secundaria con respecto a la página en sí misma. El pie también se suele usar para propósitos {{Glossary("SEO")}}, e incluye enlaces de acceso rápido al contenido más popular.</dd> +</dl> + +<p>Una página web «típica» se podría parecer a esta:</p> + +<p><img alt="Un ejemplo de estructura de sitio web simple con un encabezado principal, menú de navegación, contenido principal, barra lateral y pie de página." src="https://mdn.mozillademos.org/files/12417/sample-website.png" style="display: block; margin: 0 auto;"></p> + +<h2 id="HTML_para_dar_estructura_al_contenido">HTML para dar estructura al contenido</h2> + +<p>El ejemplo no es muy atractivo, pero puede servir para ilustrar un ejemplo de diseño de una página web típica. Puedes encontrar sitios con más columnas, algunas mucho más complejas, pero esta servirá para hacerte una idea general sobre el tema. Con el CSS adecuado podrás usar muchos más elementos para decorar las distintas secciones y conseguir que queden como deses, pero como se comentó anteriormente, necesitas respetar ciertas normas semánticas, y <em>utilizar el elemento adecuado para cada tipo de sección</em>.</p> + +<p>La parte visual no lo es todo. Utilizarás diferentes fuentes y colores para llamar la atención de los usuarios sin discapacidad visual de las partes más importantes del contenido, como el menú de navegación y sus enlaces correspondientes, pero ¿qué ocurre con los usuarios con discapacidad visual que no pueden distinguir los colores llamativos o el tamaño grande de las fuentes?</p> + +<div class="note"> +<p><strong>Nota</strong>: Los daltónicos representan alrededor del <a href="http://www.color-blindness.com/2006/04/28/colorblind-population/">4% de la población mundial</a> (aproximadamente 1 de cada 12 hombres y 1 de cada 200 mujeres son daltónicos). Los invidentes y las personas con discapacidad visual representan aproximadamente el 4-5% de la población mundial (en 2012 había {{Interwiki("wikipedia", "Discapacidad visual")}} 285 millones de personas con alguna de estas características en el mundo, mientras que el total de la población estaba {{Interwiki("wikipedia", "World_human_population#/media/File:World_population_history.svg", "alrededor de los 7,000 millones")}}.</p> +</div> + +<p>En tu código HTML puedes crear secciones de contenido basadas en su <em>funcionalidad</em> — puedes usar elementos que representen sin ambigüedad las diferentes secciones de contenido descritas, de forma que las tecnologías de accesibilidad y los lectores de pantalla puedan reconocer esos elementos y asistir en tareas como «encontrar el menú de navegación», o «encontrar el contenido principal». Como se mencionó anteriormente en el curso, hay una serie de {{web.link("/es/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals#Por_qué_necesitamos_estructura", "consecuencias por no usar la estructura de elementos y semántica adecuada para hacer el trabajo correctamente")}}.</p> + +<p>HTML dispone de etiquetas adecuadas que puedes usar para establecer estas secciones semánticas, por ejemplo:</p> + +<ul> + <li><strong>encabezado</strong>: {{HTMLElement("header")}}.</li> + <li><strong>menú de navegación </strong>: {{HTMLElement("nav")}}.</li> + <li><strong>contenido principal</strong>: {{HTMLElement("main")}}, con varias subsecciones (además de la barra lateral) representadas por los elementos {{HTMLElement("article")}}, {{HTMLElement("section")}}, y {{HTMLElement("div")}}.</li> + <li><strong>barra lateral</strong>: {{HTMLElement("aside")}}; a menudo colocada dentro de {{HTMLElement("main")}}.</li> + <li><strong>pie de página</strong>: {{HTMLElement("footer")}}.</li> +</ul> + +<h3 id="Aprendizaje_activo_El_código_del_ejemplo_anterior">Aprendizaje activo: El código del ejemplo anterior</h3> + +<p>El ejemplo de página web que se muestra arriba se consigue a partir del siguiente código (disponible en el <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/document_and_website_structure/index.html">repositorio Github</a>). Observa el ejemplo anterior, y a continuación échale un vistazo al código de abajo para identificar las secciones marcadas en el ejemplo.</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + + <title>El título de mi página</title> + <link href="https://fonts.googleapis.com/css?family=Open+Sans+Condensed:300|Sonsie+One" rel="stylesheet" type="text/css"> + <link rel="stylesheet" href="style.css"> + + <!-- las tres siguientes líneas son un truco para obtener elementos semánticos de HTML5 que funcionan en versiones de Internet Explorer antiguas --> + <!--[if lt IE 9]> + <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.js"></script> + <![endif]--> + </head> + + <body> + <!-- Aquí empieza el encabezado principal que se mantendrá en todas las páginas del sitio web --> + + <header> + <h1>Encabezado</h1> + </header> + + <nav> + <ul> + <li><a href="#">Inicio</a></li> + <li><a href="#">Nuestro equipo</a></li> + <li><a href="#">Proyectos</a></li> + <li><a href="#">Contacto</a></li> + </ul> + + <!-- Un formulario de búsqueda es una forma no-lineal de hacer búsquedas en un sitio web. --> + + <form> + <input type="search" name="q" placeholder="Buscar"> + <input type="submit" value="¡Vamos!"> + </form> + </nav> + + <!-- Aquí está el contenido principal de nuestra página --> + <main> + + <!-- Contiene un artículo --> + <article> + <h2>Título del artículo</h2> + + <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Donec a diam lectus. Set sit amet ipsum mauris. Maecenas congue ligula as quam viverra nec consectetur ant hendrerit. Donec et mollis dolor. Praesent et diam eget libero egestas mattis sit amet vitae augue. Nam tincidunt congue enim, ut porta lorem lacinia consectetur.</p> + + <h3>Subsección</h3> + + <p>Donec ut librero sed accu vehicula ultricies a non tortor. Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aenean ut gravida lorem. Ut turpis felis, pulvinar a semper sed, adipiscing id dolor.</p> + + <p>Pelientesque auctor nisi id magna consequat sagittis. Curabitur dapibus, enim sit amet elit pharetra tincidunt feugiat nist imperdiet. Ut convallis libero in urna ultrices accumsan. Donec sed odio eros.</p> + + <h3>Otra subsección</h3> + + <p>Donec viverra mi quis quam pulvinar at malesuada arcu rhoncus. Cum soclis natoque penatibus et manis dis parturient montes, nascetur ridiculus mus. In rutrum accumsan ultricies. Mauris vitae nisi at sem facilisis semper ac in est.</p> + + <p>Vivamus fermentum semper porta. Nunc diam velit, adipscing ut tristique vitae sagittis vel odio. Maecenas convallis ullamcorper ultricied. Curabitur ornare, ligula semper consectetur sagittis, nisi diam iaculis velit, is fringille sem nunc vet mi.</p> + </article> + + <!-- el contenido aparte también se puede anidar dentro del contenido principal --> + <aside> + <h2>Relacionado</h2> + + <ul> + <li><a href="#">Oh, me gusta estar junto al mar</a></li> + <li><a href="#">Oh, me gusta estar junto al mar</a></li> + <li><a href="#">Aunque en el norte de Inglaterra</a></li> + <li><a href="#">Nunca deja de llover</a></li> + <li><a href="#">Oh, bueno...</a></li> + </ul> + </aside> + + </main> + + <!-- Y aquí está nuestro pie de página principal que se utiliza en todas las páginas de nuestro sitio web --> + + <footer> + <p>©Copyright 2050 de nadie. Todos los derechos revertidos.</p> + </footer> + + </body> +</html></pre> + +<p>Tómate tu tiempo para revisar el código y comprenderlo — Los comentarios en el código también te ayudarán a entenderlo. No te pedimos que hagas mucho más en este artículo, porque la clave para entender el diseño del documento es escribir una estructura HTML conocida y posteriormente desarrollar su apariencia con CSS. Estudiaremos el diseño CSS como parte del tema CSS.</p> + +<h2 id="Elementos_de_diseño_HTML_en_detalle">Elementos de diseño HTML en detalle</h2> + +<p>Es bueno entender el significado global de todos los elementos definitorios de las secciones HTML en detalle; es algo en que trabajarás gradualmente a medida que comiences a tener más experiencia en el desarrollo web. En el enlace {{web.link("/es/docs/Web/HTML/Element", "referencia de elementos HTML")}} podemos entrar en un gran nivel de detalle. Por el momento, estas son las definiciones principales que deberíamos tratar de entender:</p> + +<ul> + <li>{{HTMLElement('main')}} encierra el contenido particular a esta página. Utilizaremos <code><main></code> solamente una vez para cada página y lo situaremos directamente dentro del elemento {{HTMLElement('body')}}. Es mejor que no lo anidemos en otros elementos.</li> + <li>{{HTMLElement('article')}} encuadra un bloque de contenido que tiene sentido por sí mismo aparte del resto de la página (por ejemplo una entrada en un blog).</li> + <li>{{HTMLElement('section')}} es parecido al elemento <code><article></code>, pero se usa más para agrupar cada parte de la página que, por su funcionalidad, constituye una sección en sí misma (por ejemplo un minimapa o un conjunto de titulares y resúmenes). Se considera una buena práctica comenzar cada una de estas secciones con un título de encabezado ({{web.link("/es/Learn/HTML/Howto/Set_up_a_proper_title_hierarchy", "heading")}}); observa que podemos subdividir artículos (<code><article></code>) en distintas secciones (<code><section></code>), o también secciones en distintos artículos, dependiendo del contexto.</li> + <li>{{HTMLElement('aside')}} incluye contenido que no está directamente relacionado con el contenido principal, pero que puede aportar información adicional relacionada indirectamente con él (resúmenes, biografías del autor, enlaces relacionados, etc.).</li> + <li>{{HTMLElement('header')}} representa un grupo de contenido introductorio. Si este es «<em>hijo</em>» de un elemento {{HTMLElement('body')}}, se convertirá en el <strong>encabezado</strong> principal del sitio web, pero si es hijo de un elemento {{HTMLElement('article')}} o un elemento {{HTMLElement('section')}}, entonces simplemente será el <strong>encabezado</strong> particular de cada sección (por favor, no lo confundas con {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML#Añadir_un_título","títulos y encabezados")}}).</li> + <li>{{HTMLElement('nav')}} contiene la funcionalidad de navegación principal de la página. Los enlaces secundarios, etc., no entrarán en la navegación.</li> + <li>{{HTMLElement('footer')}} representa un grupo de contenido al final de una página.</li> +</ul> + +<h3 id="Envolturas_no_semánticas">Envolturas no semánticas</h3> + +<p>A veces hay situaciones en las que no encuentras un elemento semántico adecuado para agrupar ciertos elementos o englobar cierto contenido. Podrías querer agrupar ciertos elementos para referirte a ellos como una entidad que comparta cierto {{Glossary("CSS")}} o {{Glossary("JavaScript")}}. Para casos como esos, HTML dispone del elemento {{HTMLElement("div")}} y del elemento {{HTMLElement("span")}}. Preferentemente estos elementos se deberán utilizar con sus atributos ({{HTMLAttrxRef('class')}}), para conferirles algún tipo de etiquetado que permita determinarlos con facilidad.</p> + +<p>{{HTMLElement("span")}} es un elemento no-semántico que se utiliza en el interior de una línea. Se utiliza cuando no se nos ocurre el uso de ningún otro elemento semántico de texto en el que incluir el contenido, o si no se desea añadir ningún significado específico. Por ejemplo:</p> + +<pre class="brush: html notranslate"><p>El rey volvió ebrio a su habitación alrededor de la 01:00, y sin duda la cerveza no le ayudaba +cuando cruzó tambaleante la puerta <span class="editor-note">[nota del editor: en este instante de la +representación, deberían atenuarse las luces]</span>.</p></pre> + +<p>En este caso, la nota del editor solo proporciona información extra para el director de la obra; se supone que estos elementos no incluyen contenido extra importante. Para los usuarios sin discapacidad visual, quizás debamos usar CSS para diferenciar sutilmente estas notas del texto principal.</p> + +<p>{{HTMLElement("div")}} es un elemento de bloque no-semántico; lo utilizaras cuando no se te ocurra el uso de otro elemento semántico mejor, o si no deseas añadir ningún significado concreto. Por ejemplo, imagina un carrito de compras que puedes pulsar en cualquier momento durante tu estancia en una tienda virtual:</p> + +<pre class="brush: html notranslate"><div class="shopping-cart"> + <h2>Carrito de compras</h2> + <ul> + <li> + <p><a href=""><strong>Pendientes de plata</strong></a>: $99.95.</p> + <img src="../products/3333-0985/" alt="Pendientes de plata"> + </li> + <li> + ... + </li> + </ul> + <p>Importe total: $237.89</p> +</div></pre> + +<p>Este no es un elemento lateral (<code><aside></code>) porque no necesariamente está relacionado con el contenido principal de la página (en realidad quieres que se pueda ver desde cualquier página). Ni siquiera se puede incluir en una sección (<code><section></code>) porque su contenido no forma parte del contenido principal de la página. Por lo tanto, un elemento <code><div></code> es el adecuado en este caso. Hemos incluido un <strong>encabezado</strong> para indicar a los lectores de pantalla donde van a encontrarlo.</p> + +<div class="warning"> +<p><strong>Atención</strong>: Los elementos <code>div</code> son tan prácticos y simples que es fácil usarlos en exceso. Como no conllevan valor semántico, enmarañan el código HTML. Debemos tener cuidado de usarlos solo cuando no halles una solución mejor y reducir su uso al mínimo, porque de otro modo complicarás el mantenimiento y actualización de los documentos.</p> +</div> + +<h3 id="Saltos_de_línea_y_líneas_horizontales">Saltos de línea y líneas horizontales</h3> + +<p>Dos elementos que debes conocer y utilizarás ocasionalmente son {{HTMLElement("br")}} y {{HTMLElement("hr")}}:</p> + +<p>El elemento {{HTMLElement("br")}} genera un salto de línea en un párrafo; es la única manera de representar series de líneas cortas, como una dirección postal o un poema. Por ejemplo:</p> + +<div id="line-break-live-sample"> +<pre class="brush: html notranslate"><p>Había una vez un hombre llamado O'Dell<br> +A quién le encantaba escribir HTML<br> +Pero su estructura era mala, su semántica era triste<br> +y su marcado no se interpretó muy bien.</p></pre> +</div> + +<p>Sin el elemento {{HTMLElement("br")}}, todo el párrafo se habría presentado como una sola línea larga (como ya hemos dicho con anterioridad en este curso, {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started#Los_espacios_en_blanco_en_HTML", "HTML ignora la mayoría del espacio en blanco")}}); con estos elementos {{HTMLElement("br")}} en el código, las líneas quedan:</p> + +<p>{{EmbedLiveSample('line-break-live-sample', '100%', '125px', '', '', 'hide-codepen-jsfiddle')}}</p> + +<p>Los elementos {{HTMLElement("hr")}} generan una regla horizontal en el documento que denota un cambio en la temática del texto (como un cambio de tema o de escena). Visualmente tiene el aspecto de una línea horizontal. Por ejemplo:</p> + +<div id="Ejemplo_en_vivo_línea_horizontal"> +<pre class="brush: html notranslate"><p>Ron fue acorralado en una esquina por las bestias abisales que merodeaban. Asustado, pero decidido a proteger a sus amigos, levantó su varita y se preparó para la batalla, con la esperanza de que su llamada de socorro hubiera llegado a alguien.</p> +<hr> +<p>Mientras tanto, Harry estaba sentado en su casa, mirando su declaración de regalías y pensando en cuándo saldría la próxima serie derivada, cuando de pronto voló por su ventana una carta de socorro y aterrizó en su regazo. La leyó vagamente y suspiró; "Será mejor que vuelva al trabajo entonces", reflexionó.</p></pre> +</div> + +<p>Quedará así:</p> + +<p>{{EmbedLiveSample('Ejemplo_en_vivo_línea_horizontal', '100%', '185px', '', '', 'hide-codepen-jsfiddle')}}</p> + +<h2 id="Planificación_de_una_página_web_sencilla">Planificación de una página web sencilla</h2> + +<p>Una vez has planificado el contenido de una página web sencilla, el paso lógico siguiente es intentar trabajar en el contenido para todo el sitio web, las páginas que necesitas y la forma de disponer las conexiones entre ellas para producir la mejor experiencia de usuario a los visitantes. Esto se conoce con el nombre de ({{Glossary("Arquitectura de la información")}}). Una web grande y compleja necesitará mucha planificación, pero para una web sencilla compuesta por unas cuantas páginas, el proceso puede ser sencillo, ¡y divertido!.</p> + +<ol> + <li>Ten en cuenta que habrá varios elementos comunes en muchas (si no en todas las) páginas, tal como el menú de navegación y el contenido del pie de página. Si la web está dedicada a un negocio, por ejemplo, sería una buena idea disponer de la información de contacto en el pie de página en todas las páginas. Anota lo que deseas tener en común en cada página. <img alt="las características comunes del sitio de viajes para ir en cada página: título y logotipo, contacto, derechos de autor, términos y condiciones, selección de idioma, política de accesibilidad" src="https://mdn.mozillademos.org/files/12423/common-features.png" style="border-style: solid; border-width: 1px; display: block; height: 375px; margin: 0px auto; width: 600px;"></li> + <li>A continuación, esboza un esquema sencillo de cuál podría ser la estructura deseada de la apariencia de cada página (podría ser algo tan sencillo como el siguiente dibujo). Anota los bloques principales. <img alt="Un diagrama simple de una estructura de sitio de ejemplo, con un encabezado, un área de contenido principal, dos barras laterales opcionales y un pie de página" src="https://mdn.mozillademos.org/files/12429/site-structure.png" style="border-style: solid; border-width: 1px; display: block; height: 232px; margin: 0px auto; width: 600px;"></li> + <li>Ahora, elabora una lista completa con todo el resto del contenido de tu sitio web que no sea común a todas las páginas. <img alt="Una larga lista de todas las funciones que podrías incluir en tu sitio de viajes, desde buscar, hasta ofertas especiales e información específica del país" src="https://mdn.mozillademos.org/files/12425/feature-list.png" style="border-style: solid; border-width: 1px; display: block; height: 1066px; margin: 0px auto; width: 600px;"></li> + <li>A continuación, trata de ordenar todo este contenido por grupos, para hacerte una idea de las partes que podrían ir juntas en las diferentes páginas. Esto es muy similar a una técnica llamada {{Glossary("Clasificación de tarjetas")}}. <img alt="Los elementos que deberían aparecer en un sitio de vacaciones ordenados en 5 categorías: Búsqueda, Especiales, Información específica del país, Resultados de búsqueda y Compra cosas" src=" https://mdn.mozillademos.org/files/12421/card-sorting.png" style="border-style: solid; border-width: 1px; display: block; height: 579px; margin: 0px auto; width: 600px;"></li> + <li>Ahora trata de esquematizar un mapa de tu sitio — dibuja un globo para cada página de tu sitio web y dibuja líneas que identifiquen el flujo de datos entre las distintas páginas. La página de inicio normalmente estará ubicada en el centro y enlazará con el resto de páginas; la mayoría de las páginas de una web sencilla estarán enlazadas desde el menú de navegación principal, aunque puede haber excepciones. También puedes incluir notas sobre cómo se pueden presentar las cosas. <img alt="Un mapa del sitio que muestra la página de inicio, la página del país, los resultados de búsqueda, la página de ofertas especiales, la página de pago y la página de compra" src="https://mdn.mozillademos.org/files/12427/site-map.png" style="border-style: solid; border-width: 1px; display: block; height: 872px; margin: 0px auto; width: 600px;"></li> +</ol> + +<h3 id="Aprendizaje_activo_Creación_de_un_mapa_del_sitio_web">Aprendizaje activo: Creación de un mapa del sitio web</h3> + +<p>Intenta llevar a cabo el ejercicio anterior para crear tu propia página web. ¿Qué contenido le vas a dar a tu sitio web?</p> + +<div class="note"> +<p><strong>Nota</strong>: Guarda este esquema para utilizarlo más adelante.</p> +</div> + +<h2 id="¡Pon_a_prueba_tus_habilidades!">¡Pon a prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo, pero ¿puedes recordar la información más importante? Puedes encontrar una evaluación detallada que pruebe estas habilidades al final del módulo; consulta {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Estructurar el contenido de una página")}}. ¡Recuerda leer primero el siguiente artículo de la serie y no solo saltarlo!</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En este punto, deberías tener una mejor idea sobre cómo estructurar una página/sitio web. En el último artículo de este módulo, se explica cómo depurar HTML.</p> + +<h2 id="Ve_también">Ve también</h2> + +<ul> + <li>{{web.link("/es/docs/Web/Guide/HTML/Using_HTML_sections_and_outlines", "Uso de secciones y esquemas HTML")}}: Guía avanzada de elementos semánticos HTML5 y el algoritmo de esquema HTML5.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "¿Qué hay en el «head»? Metadatos en HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Fundamentos de texto HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Crear hipervínculos")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Formateo de texto avanzado")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Estructura web y documentación")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Depurar HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Marcado para una carta")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Estructuración del contenido de una página")}}</li> +</ul> diff --git a/files/es/learn/html/introduccion_a_html/estructuración_de_una_página_de_contenido/index.html b/files/es/learn/html/introduccion_a_html/estructuración_de_una_página_de_contenido/index.html new file mode 100644 index 0000000000..686940212e --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/estructuración_de_una_página_de_contenido/index.html @@ -0,0 +1,105 @@ +--- +title: Estructuración de una Página de contenido +slug: Learn/HTML/Introduccion_a_HTML/Estructuración_de_una_página_de_contenido +tags: + - Aprendizaje + - Diseño + - Escribir Código + - Estructuración + - Evaluación + - HTML + - Principiante + - Prototipado + - semántica +translation_of: Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}} </div> + +<p class="summary"><span id="result_box" lang="es"><span>La estructuración de una página de contenido lista para su uso mediante CSS es una habilidad muy importante para dominar, por lo que en esta evaluación verá su capacidad para pensar en cómo podría finalizar una página buscando y eligiendo la semántica estructural adecuada para construir</span> <span>un diseño en la parte superior.</span></span></p> + +<div id="gt-res-content"> +<div dir="ltr" style="zoom: 1;"> </div> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td><span id="result_box" lang="es"><span>Antes de intentar esta evaluación, usted debería haber trabajado ya en el resto del curso, con un énfasis particular en la </span></span><a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure">Estructura del Documento y del Sitio Web.</a><a href="https://developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML/estructura">.</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td><span id="result_box" lang="es"><span>Probar el conocimiento de las estructuras de páginas web y cómo representar un prototipado de diseño prospectivo en el marcado.</span></span></td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Para comenzar esta evaluación, debería tomar el <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/structuring-a-page-of-content-start/assets.zip?raw=true"> archivo zip que contiene todos los activos de inicio</a>. El archivo zip contiene:</p> + +<ul> + <li>El HTML que necesitas para añadir marcado estructural.</li> + <li>CSS para dar el estilo a tu marcado.</li> + <li>Las imágenes que serán utilizadas en la página.</li> +</ul> + +<p>Crée el ejemplo en su ordenador personal, o como alternativa utilize un sitio como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> o <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> para hacer su evaluación.</p> + +<h2 id="Breve_Proyecto">Breve Proyecto</h2> + +<p>Para este proyecto, su tarea es tomar el contenido de la página principal de un sitio web de observación de aves y añadir elementos estructurales a la misma para que pueda tener un diseño de página aplicado a ella. Necesita tener:</p> + +<ul> + <li> Un encabezado que abarca todo el ancho del sitio que contiene el título principal de la página, el logotipo del sitio y el menú de navegación. El título y el logotipo aparecen lado a lado una vez que se aplica el estilo, y la navegación aparece debajo de esos dos elementos.</li> + <li> Un área de contenido principal que contiene dos columnas: un bloque principal para contener el texto de bienvenida y una barra lateral para contener miniaturas de imágenes.</li> + <li> Un pie de página que contiene información sobre derechos de autor y créditos.</li> +</ul> + +<p>Debe agregar una presentación adecuada para:</p> + +<ul> + <li>El encabezado</li> + <li>El menú de navegación</li> + <li>El contenido principal</li> + <li>El texto de bienvenida</li> + <li>La barra lateral de imágenes</li> + <li>El pié de página</li> +</ul> + +<p>También debería:</p> + +<ul> + <li> Aplicar el CSS proporcionado a la página agregando otro elemento {{htmlelement ("link")}} justo debajo del existente que se proporciona al principio.</li> +</ul> + +<h2 id="Consejos">Consejos</h2> + +<ul> + <li>Utilize el <a href="https://validator.w3.org/">validador de HTML W3C </a> para validar su HTML; Obtendrá puntos de bonificación si valida tanto como sea posible (la línea "googleapis" es una línea utilizada para importar fuentes personalizadas en la página del servicio Google Fonts, no se valida, así que no te preocupes. )</li> + <li>No necesita saber CSS para hacer esta evaluación; Sólo tiene que poner el CSS proporcionado dentro de un elemento HTML.</li> + <li>El CSS proporcionado está diseñado para que cuando se agreguen los elementos estructurales correctos al marcado, aparezcan verdes en la página representada.</li> + <li>Si se está quedando atascado y no puede imaginar ni qué elementos poner ni donde ponerlos , a menudo ayuda a dibujar un diagrama de bloques simple del diseño de página, y escribir en los elementos que usted piensa que debe envolver cada bloque.</li> +</ul> + +<h2 id="Ejemplo">Ejemplo</h2> + +<p>La siguiente captura de pantalla muestra un ejemplo de cómo podría verse la letra después de haber sido marcada.</p> + +<p><img alt='The finished example for the assessment; a simple webpage about birdwatching, including a heading of "Birdwatching", bird photos, and a welcome message' src="https://mdn.mozillademos.org/files/12449/example-page.png" style="display: block; margin: 0 auto;"></p> + +<h2 id="Evaluación">Evaluación</h2> + +<p>Si está siguiendo esta evaluación como parte de un curso organizado, debe ser capaz de dar su trabajo a su maestro / mentor para el marcado. Si usted está aprendiendo por si mismo, entonces puede obtener la guía de marcado con bastante facilidad preguntando sobre ello en la lista de correo<a href="https://lists.mozilla.org/listinfo/dev-mdc"> dev-mdc</a> , o en el canal IRC <a href="irc://irc.mozilla.org/mdn">#mdn</a> en <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Pruebe a hacer el ejercicio primero - ¡No hay nada que ganar por hacer trampa!</p> + +<p>{{PreviousMenu("Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Learn/HTML/Introduction_to_HTML")}}</p> + +<div class="s3gt_translate_tooltip" id="s3gt_translate_tooltip" style="position: absolute; left: 61px; top: 1812px; opacity: 0.7;"> +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_logo" title="Traducir texto seleccionado"> </div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_sound" title="Reproducir"> </div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_copy" title="Copy text to Clipboard"> </div> +</div> diff --git a/files/es/learn/html/introduccion_a_html/index.html b/files/es/learn/html/introduccion_a_html/index.html new file mode 100644 index 0000000000..64c70649cb --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/index.html @@ -0,0 +1,77 @@ +--- +title: Introducción a HTML +slug: Learn/HTML/Introduccion_a_HTML +tags: + - CodingScripting + - Enlaces + - Estructura + - HTML + - Introducción a HTML + - Texto + - semántica +translation_of: Learn/HTML/Introduction_to_HTML +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">En su corazón, {{glossary("HTML")}} es un lenguaje muy sencillo compuesto de {{Glossary("Element", "elementos")}}, que se pueden aplicar a piezas de texto para darles un significado diferente en un documento (¿Esto es un párrafo? ¿Esto es una lista con viñetas? ¿Esto es parte de una tabla?), estructura un documento en secciones lógicas (¿Tiene una cabecera? ¿Tres columnas de contenido? ¿Un menú de navegación?), e incrusta contenido como imágenes y vídeos en una página. Este módulo introducirá los dos primeros de estos, e introduce conceptos fundamentales y la sintaxis que necesitas para entender HTML.</p> + +<div class="in-page-callout webdev"> +<h3 id="¿Quieres_transformarte_en_un_desarrollador_de_la_interfaz_de_usuario_web">¿Quieres transformarte en un desarrollador de la interfaz de usuario web?</h3> + +<p>Hemos elaborado un curso que incluye toda la información esencial que necesitas para trabajar hacia tu objetivo.</p> + +<p><a class="cta primary" href="/docs/Learn/Front-end_web_developer">Empieza aquí</a></p> +</div> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Antes de empezar este módulo, no necesitas conocimientos previos de HTML, pero deberías estar, por lo menos, familiarizado con el uso básico de computadoras, y usar la Web pasivamente (es decir, sólo revisándola y consumiendo el contenido). Debes tener configurado un entorno de trabajo básico (como se detalla en {{web.link("/es/docs/Learn/Getting_started_with_the_web/Installing_basic_software", "Instalación de software básico")}}), y comprender cómo crear y administrar archivos (como se detalla en {{web.link("/es/docs/Learn/Getting_started_with_the_web/Dealing_with_files", "Manejo de archivos")}}). Ambos son parte de nuestro módulo completo {{web.link("/es/docs/Learn/Getting_started_with_the_web", "Introducción a la web")}} para principiantes.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si estás trabajando en una computadora, tablet u otro dispositivo en donde no tengas la capacidad de crear tus propios archivos, podrías probar (en su mayoría) el código de los ejemplos en un programa para escribir código en línea como <a href="http://jsbin.com/">JSBin</a> o <a href="">Glitch</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<p>Este módulo contiene los siguientes artículos, que te llevarán a través de toda la teoría básica de HTML, y te proporcionarán una amplia oportunidad de probar algunas habilidades.</p> + +<dl> + <dt><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started">Empezar con HTML</a></dt> + <dd>Cubre las bases absolutas de HTML, para que puedas empezar — definimos elementos, atributos, y todas los otros términos importantes que puedas haber escuchado, y en donde encajan en el lenguaje. También mostramos cómo está estructurado un elemento HTML, cómo está estructurada una página HTML típica, y explica otras características importantes. <span id="result_box" lang="es">En el camino, vamos a tener un juego con algo de HTML, ¡para alimentar tu intereses!</span></dd> + <dt><a href="/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">¿Qué hay en la cabecera? Metadatos en HTML</a></dt> + <dd>La cabecera de un documento HTML es la parte que <strong>no</strong> se muestra en el navegador web cuando se carga una página. Esta contiene información como el título ({{htmlelement("title")}}) de la página, enlaces a {{glossary("CSS")}} (si quieres estilizar tu contenido HTML con CSS), enlaces a favicons personalizados, y metadatos (que son los datos sobre el HTML, como quién lo escribió, y palabras clave que describen el documento).</dd> + <dt><a href="/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">Fundamentos de texto HTML</a></dt> + <dd>Uno de los principales trabajos de HTML es darle significado al texto (también conocido como <strong>semántica</strong>) para que el navegador sepa cómo mostrarlo correctamente. Este artículo trata cómo usar HTML para convertir un bloque de texto en una estructura de encabezados y párrafos, agregar énfasis o importancia a las palabras, crear listas y más.</dd> + <dt><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">Creando hipervínculos</a></dt> + <dd>Los hipervínculos realmente son importantes — estos son los que hacen la Web. Este artículo muestra la sintaxis requerida para hacer un enlace, y explica las mejores prácticas sobre enlaces.</dd> + <dt><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">Formateo de texto avanzado</a></dt> + <dd>Hay muchos otros elementos en HTML para formatear texto, que no hemos tratado en los artículos {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "fundamentos de texto HTML")}}. Los siguientes elementos son menos conocidos, pero sigue siendo útil conocerlos. Aquí aprenderás sobre el marcado de citas, listas de descripción, código de computadoras y otros textos relacionados, <span id="result_box" lang="es"><span> subíndices y superíndices, información de contacto, y mucho más</span>.</span></dd> + <dt>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Estructura web y documentación")}}</dt> + <dd>Así como definimos las partes individuales de tu página (como "un párrafo" o "una imagen"), HTML también se usa para definir las áreas de tu sitio web (como "la cabecera", "el menú de navegación", "la columna de contenido principal"). Este artículo trata sobre cómo planear una estructura básica del sitio web, y escribir el HTML para representar esa estructura.</dd> + <dt><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">Depurar HTML</a></dt> + <dd>Escribir HTML está bien, pero ¿Qué pasa si algo está mal, y no puedes encontrar en dónde está el error en el código? Este artículo introducirá algunas herramientas que te podrán ayudar.</dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<p>Las siguientes evaluaciones probarán tu entendimiento de las bases de HTML cubiertas en las guías anteriores.</p> + +<dl> + <dt>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Marcando para una carta")}}</dt> + <dd><span id="result_box" lang="es">Todos aprendemos a escribir una carta, tarde o temprano; ¡Este también es un ejemplo útil para poner a prueba nuestras habilidades de formato de texto! Así que en esta evaluación se te dará una carta a la cual le tendrás que dar un marcado HTML.</span></dd> + <dt>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Estructuración del contenido de una página")}}</dt> + <dd>Esta evaluación prueba tu capacidad para usar HTML para estructurar el contenido de una sencilla página, esta tiene una cabecera, pie de página, menú de navegación, contenido principal, y una barra lateral.</dd> +</dl> + +<h2 id="Ve_también">Ve también</h2> + +<dl> + <dt><a href="https://teach.mozilla.org/activities/web-lit-basics/">Bases de la alfabetización Web 1</a></dt> + <dd>Un curso excelente de la fundación Mozilla que explora y pone a prueba muchas de las habilidades sobre las cuales hablamos en el módulo de <em>Introducción a HTML</em>. Los estudiantes se familiarizan con la lectura, escritura y participan de la web en este módulo de seis partes. Descubre los fundamentos de la web a través de la producción y colaboración.</dd> +</dl> + +<div class="note"> +<h2 id="Retroalimentación">Retroalimentación</h2> + +<p>Ayúdanos a mejorar nuestras guías y tutoriales como esta respondiendo {{web.link("https://www.surveygizmo.com/s3/4871248/MDN-Guides-Survey", "nuestra encuesta aquí")}}.</p> +</div> diff --git a/files/es/learn/html/introduccion_a_html/iniciar/index.html b/files/es/learn/html/introduccion_a_html/iniciar/index.html new file mode 100644 index 0000000000..c05aa6a9f0 --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/iniciar/index.html @@ -0,0 +1,767 @@ +--- +title: Empezar con HTML +slug: Learn/HTML/Introduccion_a_HTML/iniciar +tags: + - Atributos + - Elemento + - Guía + - HTML + - Principiante + - comentários +translation_of: Learn/HTML/Introduction_to_HTML/Getting_started +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">En este artículo vamos a exponer lo más básico del HTML. Para comenzar definiremos elementos, atributos y el resto de términos importantes que quizá ya te suenen y qué función cumplen dentro del lenguaje. También explica dónde encajan estos en HTML. Aprenderás cómo se estructuran los elementos HTML, cómo se estructura una página HTML típica y otras características básicas importantes del lenguaje. Por el camino, también iremos practicando con algo de HTML.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, {{web.link("/es/docs/Learn/Getting_started_with_the_web/Installing_basic_software", "tener instalado el software básico")}} y conocimientos básicos de cómo {{web.link("/es/docs/Learn/Getting_started_with_the_web/Dealing_with_files", "trabajar con archivos")}}.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarte con el lenguaje HTML, y adquirir algo de práctica escribiendo unos pocos elementos HTML.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_el_HTML">¿Qué es el HTML?</h2> + +<p>{{Glossary("HTML")}} ("<em>Hypertext Markup Language</em>") no es un lenguaje de programación. Es un <em>lenguaje de marcado</em> que le dice a los navegadores web cómo estructurar las páginas web que estás visitando. Puede ser tan complejo o tan simple como desee el desarrollador web. El HTML consiste en una serie de {{Glossary("Element", "elementos")}}, que puedes utilizar para encerrar, delimitar o <em>marcar</em> diferentes partes del contenido para hacer que aparezcan de una cierta manera, o actúen de determinada forma. Las {{Glossary("Tag", "etiquetas")}} que delimitan un fragmento de contenido pueden hacer que dicho contenido enlace con otra página, ponga una palabra en cursiva, etcétera. Por ejemplo, dada la siguiente línea de contenido:</p> + +<pre class="brush: bash notranslate">Mi gato es muy gruñón</pre> + +<p>Si queremos que la línea sea independiente de otras, podemos especificar que es un párrafo encerrándola con una etiqueta de elemento de párrafo ({{htmlelement("p")}}):</p> + +<pre class="brush: html notranslate"><p>Mi gato es muy gruñón</p></pre> + +<div class="note"> +<p><strong>Nota</strong>: Las etiquetas en HTML no distinguen entre mayúsculas y minúsculas. Así que se pueden escribir tanto en mayúsculas como en minúsculas. Por ejemplo, una etiqueta {{htmlelement("title")}} se puede escribir como <code><title></code>, <code><TITLE></code>, <code><Title></code>, <code><TiTle></code>, etc., y funcionará correctamente. La mejor práctica, sin embargo, es escribir todas las etiquetas en minúsculas para mantener la coherencia y legibilidad, entre otros motivos.</p> +</div> + +<h2 id="Anatomía_de_un_elemento_HTML">Anatomía de un elemento HTML</h2> + +<p>Exploremos un poco el elemento párrafo:</p> + +<p><img alt="Anatomía de los elementos HTML" src="https://mdn.mozillademos.org/files/11913/htmlexp.png" style="display: block; height: 255px; margin: 0px auto; width: 821px;"></p> + +<p>Las principales partes de nuestro elemento son:</p> + +<ul> + <li>La <strong>etiqueta de apertura</strong>: consiste en el nombre del elemento (en este caso, <code>p</code>), encerrado entre <strong>paréntesis angulares</strong> de apertura y cierre. Esta etiqueta de apertura marca dónde comienza el elemento o comienza a tener efecto. En este ejemplo, precede al comienzo del texto del párrafo.</li> + <li>El <strong>contenido</strong>: Este es el contenido del elemento. En este ejemplo, es el texto del párrafo.</li> + <li>La <strong>etiqueta de cierre</strong>: Es lo mismo que la etiqueta de apertura, excepto que incluye una barra diagonal antes del nombre del elemento. Esto indica dónde termina el elemento; en este caso, dónde finaliza el párrafo. No incluir una etiqueta de cierre es un error común de principiante, y puede conducir a extraños resultados.</li> +</ul> + +<p>El <strong>elemento</strong> lo conforman la etiqueta de apertura, seguida del contenido, seguido de la etiqueta de cierre.</p> + +<h3 id="Aprendizaje_activo_crear_tu_primer_elemento_HTML">Aprendizaje activo: crear tu primer elemento HTML</h3> + +<p>Edita la siguiente línea en el área <em>Entrada</em> envolviéndola con las etiquetas <code><em></code> y <code></em></code>. Para <em>abrir el elemento</em>, coloca la etiqueta de apertura <code><em></code> al principio de la línea. Para <em>cerrar el elemento</em>, coloca la etiqueta de cierre <code></em></code> al final de la línea. ¡Obtienes una línea en cursiva! Puedes ver tus cambios actualizados automáticamente en la caja de texto de <em>Salida</em>.</p> + +<p>Si te equivocas, siempre puedes volver al código anterior mediante el botón <em>Restablecer</em>. Si te quedas realmente atascado, pulsa el botón <em>Mostrar la solución</em> para ver la solución.</p> + +<div class="hidden"> +<h6 id="Código_reproducible">Código reproducible</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="playable-code" style="min-height: 100px;width: 95%"> + Este es mi texto. +</textarea> + +<div class="controls"> + <input id="reset" type="button" value="Restablecer" /> + <input id="solution" type="button" value="Mostrar solución" /> +</div> +</pre> + +<pre class="brush: css notranslate">html { + font-family: 'Open Sans Light',Helvetica,Arial,sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +} +</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +var htmlSolution = '<em>Este es mi texto.</em>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Elementos_anidados">Elementos anidados</h3> + +<p>Se pueden poner elementos dentro de otros elementos. Esto se llama <strong>anidamiento</strong>. Si quisiéramos decir que nuestro gato es <strong>muy</strong> gruñón, podríamos encerrar la palabra <em>muy</em> en un elemento {{htmlelement("strong")}} para que aparezca destacada.</p> + +<pre class="brush: html notranslate"><p>Mi gato es <strong>muy</strong> gruñón.</p></pre> + +<p>Hay una forma correcta e incorrecta de anidar. En el ejemplo anterior, primero abrimos el elemento <code>p</code>, luego abrimos el elemento <code>strong</code>. Para un anidamiento adecuado, primero debemos cerrar el elemento <code>strong</code>, antes de cerrar el <code>p</code>.</p> + +<p>El siguiente es un ejemplo de la forma <em>incorrecta</em> de anidar:</p> + +<pre class="example-bad brush: html notranslate"><p>Mi gato es <strong>muy gruñón.</p></strong></pre> + +<p>Los elementos tienen que abrirse y cerrarse correctamente para que estén claramente dentro o fuera el uno del otro. Con el tipo de superposición en el ejemplo anterior, el navegador tiene que adivinar tu intención. Este tipo de adivinanzas puede producir resultados inesperados.</p> + +<h3 id="Elementos_de_bloque_y_elementos_en_línea">Elementos de bloque y elementos en línea</h3> + +<p>Hay dos categorías importantes de elementos en HTML — Estos son los elementos de bloque y los elementos en línea.</p> + +<ul> + <li>Los elementos de bloque forman un bloque visible en la página. Aparecerán en una línea nueva después de cualquier contenido anterior. Cualquier contenido que vaya después también aparecerá en una línea nueva. Los elementos a nivel de bloque suelen ser elementos estructurales de la página. Por ejemplo, un elemento a nivel de bloque puede representar encabezados, párrafos, listas, menús de navegación o pies de página. Un elemento a nivel de bloque no estaría anidado dentro de un elemento en línea, pero podría estar anidado dentro de otro elemento a nivel de bloque.</li> + <li>Los elementos en línea están contenidos dentro de elementos de bloque y delimitan solo pequeñas partes del contenido del documento; (no párrafos enteros o agrupaciones de contenido) Un elemento en línea no hará que aparezca una nueva línea en el documento. Suele utilizarse con texto. Por ejemplo es el caso de un elemento {{htmlelement("a")}} (hipervínculo) o elementos de énfasis como {{htmlelement("em")}} o {{htmlelement("strong")}}.</li> +</ul> + +<p>Considera el siguiente ejemplo:</p> + +<pre class="brush: html notranslate"><em>primero</em><em>segundo</em><em>tercero</em> + +<p>cuarto</p><p>quinto</p><p>sexto</p> +</pre> + +<p>{{htmlelement("em")}} es un elemento en línea. Así, como puedes observar, los tres primeros elementos se sitúan en la misma línea, uno tras otro sin espacio entre ellos. Por otro lado, {{htmlelement("p")}} es un elemento a nivel de bloque. Cada elemento <em>p</em> aparece en una nueva línea, con un espacio arriba y abajo. (El espaciado se debe al {{web.link("/es/docs/Learn/CSS/Introduction_to_CSS", "estilo CSS")}} predeterminado que el navegador aplica a los párrafos).</p> + +<p>{{ EmbedLiveSample('Elementos_de_bloque_y_elementos_en_línea', 700, 200, "", "") }}</p> + +<div class="note"> +<p><strong>Nota</strong>: HTML5 redefinió las categorías de elementos: consulta <a href="https://html.spec.whatwg.org/multipage/indices.html#element-content-categories">Categorías de contenido de elementos</a>. Si bien estas definiciones son más precisas y menos ambiguas que sus predecesoras, las nuevas definiciones son mucho más complicadas de entender que <em>block</em> e <em>inline </em>. Este artículo seguirá con estos dos términos.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Los términos «en bloque» (block) y «en línea» (inline), tal como se usan en este tema, no se deberían confundir con {{web.link("/es/docs/Learn/CSS/Introduction_to_CSS/Box_model#Types_of_CSS_boxes", "los tipos de casillas de CSS")}} que se conocen con el mismo nombre. Aunque de manera predeterminada están relacionados, el hecho de cambiar el tipo de aspecto visual del CSS no cambia la categoría del elemento ni afecta a aquellos elementos que pueda contener. Una de las razones por las que HTML5 abandonó el uso de estos términos fue para evitar este tipo de confusión.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar referencias útiles que incluyen listas de elementos de bloque y elementos en línea. Consulta {{web.link("/es/docs/Web/HTML/Block-level_elements", "Elementos en bloque")}} y {{web.link("/es/docs/Web/HTML/Elementos_en_línea", "Elementos en línea")}}.</p> +</div> + +<h3 id="Elementos_vacíos">Elementos vacíos</h3> + +<p>No todos los elementos siguen el patrón de etiqueta de apertura, contenido y etiqueta de cierre. Algunos elementos consisten solo en una etiqueta única, que se utiliza generalmente para insertar/incrustar algo en el documento en el lugar donde se le quiere incluir. Por ejemplo, el elemento {{htmlelement("img")}} inserta una imagen en la página:</p> + +<pre class="brush: html notranslate"><img src="https://raw.githubusercontent.com/mdn/beginner-html-site/gh-pages/images/firefox-icon.png"></pre> + +<p>Este texto mostrará lo siguiente en tu página:</p> + +<p>{{ EmbedLiveSample('Elementos_vacíos', 700, 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Los elementos vacíos en ocasiones también se llaman elementos <em>nulos</em> o <em>vanos</em> (<em>void elements</em>).</p> +</div> + +<h2 id="Atributos">Atributos</h2> + +<p>Los elementos también pueden tener atributos. Los atributos tienen este aspecto:</p> + +<p><img alt="atributo html" src="https://mdn.mozillademos.org/files/11915/htmlatributos.png" style="display: block; height: 156px; margin: 0px auto; width: 1287px;"></p> + +<p>Los atributos contienen información extra sobre el elemento que no se mostrará en el contenido. En este caso, el atributo <code>class</code> asigna al elemento un identificador que se puede utilizar para dotarlo de información de estilo.</p> + +<p>Un atributo debería tener:</p> + +<ul> + <li>Un espacio entre este y el nombre del elemento. (Para un elemento con más de un atributo, los atributos también deben estar separados por espacios).</li> + <li>El nombre del atributo, seguido por un signo igual.</li> + <li>Un valor del atributo, rodeado de comillas de apertura y cierre.</li> +</ul> + +<h3 id="Aprendizaje_activo_Añadir_atributos_a_un_elemento">Aprendizaje activo: Añadir atributos a un elemento</h3> + +<p>Otro ejemplo de un elemento es {{htmlelement("a")}}. Esto significa <em>ancla</em>. Una ancla puede convertir el texto que encierra en un hipervínculo. Las anclas pueden tener varios atributos, pero varios son como sigue:</p> + +<ul> + <li><strong><code>href</code></strong>: El valor de este atributo indica la dirección web a la que se quiere que apunte el enlace, que será hacia donde nos lleve el navegador cuando se haga clic sobre el elemento. Por ejemplo, <code>href="https://www.mozilla.org/"</code>.</li> + <li><strong><code>title</code></strong>: El atributo <code>title</code> añade información adicional sobre el enlace, como puede ser el título de la página que vinculas. Por ejemplo, <code>title="La página de inicio de Mozilla"</code>. Esta información aparecerá cuando se le pase el ratón por encima.</li> + <li><strong><code>target</code></strong>: El atributo <code>target</code> especifica el contexto de navegación que va a usar para mostrar el enlace. Por ejemplo, <code>target="_blank"</code> abrirá el enlace en una nueva pestaña. Si quieres mostrar el enlace en la pestaña activa, simplemente omite este atributo.</li> +</ul> + +<p>Edita la línea de abajo en el área de <em>Entrada</em> para convertirlo en un enlace a tu sitio web favorito.</p> + +<ol> + <li>Añade el elemento <code><a></code>.</li> + <li>Añade el atributo <code>href</code> y el atributo <code>title</code>.</li> + <li>Especifica el atributo <code>target</code> para abrir el enlace en una nueva pestaña.</li> +</ol> + +<p>Los cambios se actualizarán inmediatamente en la zona de <em>Salida</em>. Deberías ver un enlace que mostrará el contenido del atributo <code>title</code> cuando pases el ratón encima, y que te llevará a la dirección web indicada por el atributo <code>href</code> cuando hagas clic. Recuerda que debes incluir un espacio entre el nombre del elemento y cada atributo.</p> + +<p>Si te equivocas, siempre puedes restablecer el código anterior pulsando el botón <em>Restablecer</em>. Si te quedas realmente atascado, pulsa el botón <em>Mostrar la solución</em> para ver la solución.</p> + +<div class="hidden"> +<h6 id="Código_reproducible_2">Código reproducible 2</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 100px;width: 95%"> + &lt;p&gt;Un enlace a mi sitio web favorito.&lt;/p&gt; +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +var htmlSolution = '<p>Un enlace a mi <a href="https://www.mozilla.org/" title="La página de inicio de Mozilla" target="_blank">sitio web favorito</a>.</p>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible_2', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Atributos_booleanos">Atributos booleanos</h3> + +<p>En ocasiones puedes ver atributos escritos sin valor. Esto está permitido. Estos se denominan atributos booleanos. Los atributos booleanos solo pueden tener un valor, que generalmente es el mismo que el nombre del atributo. Por ejemplo, considera el atributo {{htmlattrxref("disabled", "input")}}, que puedes asignar a los elementos de entrada del formulario. (Usa esto para <em>deshabilitar</em> los elementos de entrada del formulario para que el usuario no pueda realizar entradas. Los elementos desactivados suelen tener una apariencia atenuada). Por ejemplo:</p> + +<pre class="brush: bash notranslate"><input type="text" disabled="disabled"></pre> + +<p>De manera abreviada, también es posible escribirlo como se describe a continuación (además, se ha incluido un elemento de entrada de formulario no desactivado como referencia, para dar una idea más precisa de lo que sucede):</p> + +<pre class="brush: html notranslate"><!-- el uso del atributo deshabilitado evita que el usuario final introduzca texto en el cuadro de entrada --> +<input type="text" disabled> + +<!-- se permite la entrada de texto, ya que no contiene el atributo deshabilitado --> +<input type="text"> +</pre> + +<p>Como referencia, el ejemplo anterior también incluye un elemento de entrada de formulario no deshabilitado. El HTML del ejemplo anterior produce este resultado:</p> + +<p>{{ EmbedLiveSample('Atributos_booleanos', 700, 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Omitir_comillas_en_valores_de_atributos">Omitir comillas en valores de atributos</h3> + +<p>Cuando observas diferentes páginas web, puedes encontrarte con todo tipo de estilos de etiquetado extraños, que incluyen valores de atributos sin comillas. Esto se permite en ciertas circunstancias, pero interrumpirá la edición en otras. Por ejemplo, si volvemos a revisar el ejemplo del enlace, sería posible escribir una versión básica con solo el atributo <code>href</code>, así:</p> + +<pre class="brush: html notranslate"><a href=https://www.mozilla.org/>mi sitio web favorito</a></pre> + +<p>Sin embargo, las cosas no funcionarán cuando a este estilo se añada el atributo <code>title</code>:</p> + +<pre class="example-bad brush: html notranslate"><a href=https://www.mozilla.org/ title=The Mozilla homepage>mi sitio web favorito</a></pre> + +<p>En este punto el navegador interpretará mal el cambio y pensará que el atributo <code>title</code> corresponde a tres atributos: un atributo <code>title</code> con el valor <em>The</em> y dos atributos booleanos: <code>Mozilla</code> y <code>homepage</code>. ¡Obviamente, esta no es la intensión! Causará errores o comportamientos inesperados, como puedes ver en el ejemplo en vivo a continuación. ¡Intenta colocar el cursor sobre el enlace para ver el texto del título!</p> + +<p>{{ EmbedLiveSample('Omitir_comillas_en_valores_de_atributos', 700, 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Incluye <strong>siempre</strong> las comillas de atributos. Evita tales problemas y da como resultado un código más legible.</p> + +<h3 id="¿Comillas_simples_o_dobles">¿Comillas simples o dobles?</h3> + +<p>En este artículo todos los atributos se han incluido en comillas dobles. Sin embargo, se pueden ver comillas simples en algún código HTML. Es una cuestión de estilo. Puedes elegir libremente cuál prefieres. Ambas líneas de código son equivalentes:</p> + +<pre class="brush: html notranslate"><a href="http://www.ejemplo.com">Un enlace a mi ejemplo.</a> + +<a href='http://www.ejemplo.com'>Un enlace a mi ejemplo.</a></pre> + +<p>Asegúrate de no mezclar ambos tipos de comillas. El siguiente ejemplo muestra un tipo de mezcla de comillas que saldrá mal:</p> + +<pre class="example-bad brush: html notranslate"><a href="http://www.ejemplo.com'>Un enlace a mi ejemplo.</a></pre> + +<p>Si utilizas un tipo de comillas en tu documento HTML, puedes incluir el otro tipo de comillas para tus valores de atributo sin que esto te cause problemas:</p> + +<pre class="brush: html notranslate"><a href="http://www.ejemplo.com" title="¿A que es 'divertido'">Un enlace a mi ejemplo.</a></pre> + +<p>Sin embargo, si deseas anidar unas comillas dentro de otras del mismo tipo (ya sea simples o dobles), tendrás que utilizar entidades HTML para las comillas. Por ejemplo, el siguiente código no va a funcionar:</p> + +<pre class="example-bad brush: html notranslate"><a href='http://www.ejemplo.com' title='¿A que es 'divertido'?'>Un enlace a mi ejemplo.</a></pre> + +<p>Así que tendrás que hacer esto:</p> + +<pre class="brush: html notranslate"><a href='http://www.ejemplo.com' title='¿A que es &apos;divertido&apos;?'>Un enlace a mi ejemplo.</a></pre> + +<h2 id="Anatomía_de_un_documento_HTML">Anatomía de un documento HTML</h2> + +<p>Los elementos HTML no son muy útiles por sí mismos. Ahora veremos cómo combinar los elementos individuales para formar una página HTML completa:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Mi página de prueba</title> + </head> + <body> + <p>Esta es mi página</p> + </body> +</html></pre> + +<p>Aquí tenemos:</p> + +<ol> + <li><code><!DOCTYPE html></code>: El elemento <em>doctype</em>. En sus inicios, cuando el HTML llevaba poco tiempo (alrededor de 1991-1992), los <em>doctypes</em> servían como enlaces al conjunto de reglas que la página HTML debía seguir para que fuera considerado buen HTML. Un elemento <em>doctype</em> de aquella época podía parecerse a esto: + + <pre class="brush: bash notranslate"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" +"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"></pre> + En la actualidad se ignora y se considera un legado histórico que hay que incluir para que todo funcione correctamente. <code><!DOCTYPE html></code> es la secuencia de caracteres más corta que se acepta como elemento <em>doctype</em> válido. Eso es lo único que realmente necesitas saber.</li> + <li><code><html></html></code>: El elemento <code><html></code>. Este elemento envuelve todo el contenido de la página. A veces se lo conoce como el elemento raíz.</li> + <li><code><head></head></code>: El elemento <code><{{htmlelement("head")}}></code> (cabecera). Este elemento actúa como contenedor para todos los parámetros que quieras incluir en el documento HTML que <em>no serán</em> visibles a los visitantes de la página. Incluye cosas como palabras clave y la descripción de la página que quieras mostrar en los resultados de búsqueda, así como la hoja de estilo para formatear nuestro contenido, declaraciones de codificación de caracteres y más. Aprenderás más acerca de esto en el siguiente artículo de la serie.</li> + <li><code><meta charset="utf-8"></code>: Este elemento establece que tu documento HTML usará la codificación UTF-8, que incluye la gran mayoría de caracteres de todos los idiomas humanos escritos. En resumen: puede gestionar cualquier contenido textual que pongas en tu documento. No hay razón para no configurar este valor y te puede ayudar a evitar problemas más adelante.</li> + <li><code><title></title></code>: El elemento {{htmlelement("title")}}. Este establece el título de la página, que es el título que aparece en la pestaña del navegador en la que se carga la página. El título de la página también se utiliza para describir la página cuando se marca como favorita.</li> + <li><code><body></body></code>: El elemento <code><body></code>. Contiene todo el contenido que quieres mostrar a los usuarios cuando visitan tu página, ya sea texto, imágenes, vídeos, juegos, pistas de audio reproducibles o cualquier otra cosa.</li> +</ol> + +<h3 id="Aprendizaje_activo_Añadir_algunas_características_a_un_documento_HTML">Aprendizaje activo: Añadir algunas características a un documento HTML</h3> + +<p>Si quieres escribir algo de HTML en tu ordenador local para experimentar, puedes:</p> + +<ol> + <li>Copiar el ejemplo de la página HTML del punto anterior.</li> + <li>Crear un archivo nuevo en un editor de texto.</li> + <li>Pegar el código en el nuevo archivo de texto.</li> + <li>Guardar el archivo como <code>index.html</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: También puedes encontrar esta plantilla básica de HTML en el <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/getting-started/index.html">repositorio GitHub del Área MDN Learning</a>.</p> +</div> + +<p>Ahora puedes abrir este archivo en un navegador web para ver cómo se ve el código renderizado. Edita el código y actualiza el navegador para ver cuál es el resultado. En principio se verá algo así:</p> + +<p><img alt="Una sencilla página HTML que dice esta es mi página" src="https://mdn.mozillademos.org/files/12279/template-screenshot.png" style="display: block; height: 365px; margin: 0px auto; width: 595px;">En este ejercicio, puedes editar el código en tu ordenador como se indica arriba, o puedes editarlo en la ventana editable que tienes a continuación (la ventana editable representa solo el contenido del elemento {{htmlelement("body")}}, en este caso). Intenta reproducir los siguientes pasos:</p> + +<ul> + <li>Justo debajo de la etiqueta de apertura {{htmlelement("body")}}, añade un título principal para el documento. Este deberá estar dentro de una etiqueta de apertura <code><h1></code> y una etiqueta de cierre <code></h1></code>.</li> + <li>Edita el contenido del párrafo e incluye algún texto sobre algo que te interese.</li> + <li>Pon las palabras importantes dentro de etiquetas <code><strong></code> de apertura y <code></strong></code> de cierre para que destaquen en negrita.</li> + <li>Añade un enlace a tu párrafo, como se ha explicado {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started#Active_learning_Adding_attributes_to_an_element", "anteriormente en este mismo artículo")}}.</li> + <li>Agrega una imagen a tu documento. Colócala debajo del párrafo, como {{web.link("/es/Learn/HTML/Introduction_to_HTML/Getting_started#Empty_elements", "se explicó anteriormente en el artículo")}}. Ganarás puntos extra si consigues enlazar a una imagen diferente (de tu propio ordenador o de cualquier otro lugar de la web).</li> +</ul> + +<p>Si te equivocas, siempre puedes restablecer el código anterior pulsando el botón <em>Restablecer</em>. Si te quedas realmente atascado, pulsa el botón <em>Mostrar la solución</em> para ver la solución.</p> + +<div class="hidden"> +<h6 id="Código_reproducible_3">Código reproducible 3</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 100px;width: 95%"> + &lt;p&gt;Esta es mi página&lt;/p&gt; +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h1 { + color: blue; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +img { + max-width: 100%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +var htmlSolution = '<h1>Un poco de música</h1><p>Realmente disfruto <strong>tocar la batería</strong>. Uno de mis bateristas favoritos es Neal Peart, que toca en la banda <a href="https://en.wikipedia.org/wiki/Rush_%28band%29" title="artículo de Wikipedia de">Rush</a>.\ Mi álbum favorito de Rush actualmente es <a href="http://www.deezer.com/album/942295">Fotografías de la película</a>.</p>\ <img src="http://www.cygnus-x1.net/links/rush/images/albums/sectors/sector2-movingpictures-cover-s.jpg">'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible_3', 700, 600, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Los_espacios_en_blanco_en_HTML">Los espacios en blanco en HTML</h3> + +<p>En los ejemplos anteriores se han incluido espacios en blanco y saltos de línea en el código. Esto realmente no es necesario. Los dos siguientes fragmentos de código son equivalentes:</p> + +<pre class="brush: html notranslate"><p>Los perros son tontos.</p> + +<p>Los perros son + tontos.</p></pre> + +<p>No importa cuántos espacios en blanco se utilicen (incluye tanto caracteres de espacio como saltos de línea) el intérprete de HTML reduce cada secuencia de espacio en blanco a un único espacio al interpretar el código. Entonces, ¿por qué utilizar espacios en blanco? La respuesta está en la legibilidad.<br> + <br> + Es más fácil comprender lo que está sucediendo en tu código si lo tienes bien formateado. En nuestro HTML cada elemento anidado está sangrado dos espacios más con respecto al exterior. Depende de ti qué estilo de formato utilizas (cuántos espacios para cada nivel de sangría, por ejemplo) pero debes plantearte el uso de algún tipo de formato.</p> + +<h2 id="Referencias_a_entidades_Inclusión_de_caracteres_especiales_en_HTML">Referencias a entidades: Inclusión de caracteres especiales en HTML</h2> + +<p>En HTML, los caracteres <code><</code>, <code>></code>,<code>"</code>,<code>'</code> y <code>&</code> son caracteres especiales. Forman parte de la sintaxis HTML. Entonces, ¿cómo incluye uno de estos caracteres especiales en tu texto? Por ejemplo, si deseas utilizar un signo comercial o menor que, y no hacer que se interprete como código.</p> + +<p>Haces esto con referencias de caracteres. Estos son códigos especiales que representan caracteres, para ser usados en estas circunstancias exactas. Cada referencia de caracter comienza con un signo de ampersand (&) y finaliza con un punto y coma (;).</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Caracter literal</th> + <th scope="col">Equivalente de referencia de caracteres</th> + </tr> + </thead> + <tbody> + <tr> + <td><</td> + <td>&lt;</td> + </tr> + <tr> + <td>></td> + <td>&gt;</td> + </tr> + <tr> + <td>"</td> + <td>&quot;</td> + </tr> + <tr> + <td>'</td> + <td>&apos;</td> + </tr> + <tr> + <td>&</td> + <td>&amp;</td> + </tr> + </tbody> +</table> + +<p>El equivalente de referencia de caracter podría recordarse fácilmente porque el texto que utiliza se puede ver como menor que para '&lt;' , cita para ' &quot; ' y de manera similar para otros. Para obtener más información sobre la referencia de entidad, consulta {{interwiki("wikipedia", "Anexo:Referencias a entidades de caracteres XML y HTML")}} en (Wikipedia).<br> + <br> + Considera los dos siguientes párrafos:</p> + +<pre class="brush: html notranslate"><p>En HTML, defines un párrafo con el elemento <p>.</p> + +<p>En HTML, defines un párrafo con el elemento &lt;p&gt;.</p></pre> + +<p>En la salida en vivo de abajo, puedes ver que el primer párrafo salió mal. El navegador interpreta la segunda instancia de <code><p></code> como el inicio de un nuevo párrafo. El segundo párrafo se ve bien porque hemos remplazado <code><</code> y <code>></code> por sus referencias correspondientes.</p> + +<p>{{ EmbedLiveSample('Referencias_a_entidades_Inclusión_de_caracteres_especiales_en_HTML', 700, 200) }}</p> + +<div class="note"> +<p><strong>Nota</strong>: En la Wikipedia se puede localizar un listado de todas las referencias de entidades de caracteres HTML disponibles: {{interwiki("wikipedia", "Anexo:Referencias a entidades de caracteres XML y HTML")}}. Observa que no necesitas usar ninguna referencia de entidad más para ningún otro de estos símbolos porque los navegadores modernos gestionan estos símbolos correctamente siempre y cuando en tu HTML hayas {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "establecido la codificación de el juego de caracteres universal UTF-8", "#Specifying_your_document's_character_encoding")}}.</p> +</div> + +<h2 id="Comentarios_HTML">Comentarios HTML</h2> + +<p>En HTML hay un mecanismo para escribir comentarios en el código. Los comentarios son ignorados por el navegador y, por tanto, son invisibles para el usuario. El propósito de los comentarios es permitirte incluir notas en el código para explicar tu lógica o codificación. Esto es muy útil si regresas a un código base después de estar ausente el tiempo suficiente como para no recordarlo por completo. Del mismo modo, los comentarios son invaluables ya que diferentes personas están realizando cambios y actualizaciones.</p> + +<p>Para convertir en un comentario una sección de contenido de tu archivo HTML, debes delimitarlo con los marcadores especiales <code><!--</code> y <code>--></code>. Por ejemplo:</p> + +<pre class="brush: html notranslate"><p>No soy un comentario</p> + +<!-- <p>¡Yo sí!</p> --></pre> + +<p>Como puedes ver a continuación, el primer párrafo aparece, pero el segundo no.</p> + +<p>{{ EmbedLiveSample('Comentarios_HTML', 700, 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Has llegado al final del artículo. Espero que hayas disfrutado del recorrido los conceptos básicos del HTML.<br> + En este punto ya deberías entender el lenguaje, cómo funciona en un nivel básico y deberías poder escribir algunos elementos y atributos. También deberías poder escribir algunos elementos y atributos. Los artículos posteriores de este módulo profundizan en algunos de los temas aquí presentados, además de presentar otros conceptos del lenguaje.</p> + +<div class="note"> +<p><strong>Nota</strong>: En este punto, a medida que empieces a aprender más sobre HTML, es posible que también desees comenzar a explorar los conceptos básicos de las Hojas de estilo en cascada (<em>Cascading style sheets</em>) o {{web.link("/es/docs/Learn/CSS", "CSS")}}. CSS, es el lenguaje utilizado para estilizar páginas web. (por ejemplo, cambiar fuentes o colores, o alterar el diseño de la página) HTML y CSS funcionan bien juntos, como pronto descubrirás.</p> +</div> + +<h2 id="Ve_también">Ve también</h2> + +<ul> + <li>{{web.link("/es/docs/Web/HTML/Applying_color", "Aplicación de color a elementos HTML mediante CSS")}}</li> +</ul> + +<div>{{NextMenu("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML")}}</div> + +<div></div> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started">Empezar con HTML</a></li> + <li><a href="/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">¿Qué hay en la cabecera? Metadatos en HTML</a></li> + <li><a href="/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">Fundamentos de texto HTML</a></li> + <li><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">Creando hipervínculos</a></li> + <li><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">Formateo de texto avanzado</a></li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Estructura web y documentación")}}</li> + <li><a href="/es/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML">Depurar HTML</a></li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Marcando para una carta")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Estructuración del contenido de una página")}}</li> +</ul> diff --git a/files/es/learn/html/introduccion_a_html/marking_up_a_letter/index.html b/files/es/learn/html/introduccion_a_html/marking_up_a_letter/index.html new file mode 100644 index 0000000000..e53bb01826 --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/marking_up_a_letter/index.html @@ -0,0 +1,88 @@ +--- +title: Marcando una Carta +slug: Learn/HTML/Introduccion_a_HTML/Marking_up_a_letter +tags: + - Cabecera + - Codificación + - Enlaces + - Evaluación + - Principiante + - Texto +translation_of: Learn/HTML/Introduction_to_HTML/Marking_up_a_letter +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">Todos aprendemos a escribir una carta más tarde o más temprano; es también práctico practicar con nuestras habilidades para dar forma a los textos. En esta prueba deberás demostrar tus habilidades para dar forma a textos, incluyendo enlaces, además pondremos a prueba tu familiaridad con algunos contenidos de encabezamiento <code><head></code> en HTML.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Antes de intentar este examen deberías haber trabajado los artículos <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started">Getting started with HTML</a>, <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">What's in the head? Metadata in HTML</a>, <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals">HTML text fundamentals</a>, <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">Creating hyperlinks</a>, y <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">Advanced text formatting</a>.</td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Probar las habilidades básicas y avanzadas de formateo de texto e hyperlinks, y el conocimiento de los encabezamientos en HTML.</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Para comenzar esta prueba, deberemos copiar <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/marking-up-a-letter-start/letter-text.txt">el texto que deberemos trabajar</a>, y el <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/marking-up-a-letter-start/css.txt">CSS que necesitaremos incluir</a> en nuestro HTML. Crearemos un archivo nuevo <code>.html</code> usando nuestro editor de texto (o alternativamente usaremos otros como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> o <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> para hacer nuestra prueba).</p> + +<h2 id="Resumen_del_proyecto_a_desarrollar">Resumen del proyecto a desarrollar</h2> + +<p>En este proyecto tu tarea será publicar una carta que debe estar alojada en la intranet de una universidad. La carta es la respuesta de un compañero investigador a un posible estudiante de postgrado en relación a su deseo de trabajar en la universidad.</p> + +<p>Semánticas de bloque/estructurales:</p> + +<ul> + <li>Estructura el documento completo incluyendo los elementos (doctype), {{htmlelement("html")}}, {{htmlelement("head")}} y {{htmlelement("body")}}.</li> + <li>Incluye los elementos correspondientes de marcado en la carta tales como párrafos y títulos, a excepción de los siguientes. Hay un título principal (la línea que comienza por "Re:") y tres títulos secundarios.</li> + <li>Las fechas de comienzo de los semestres, las materias y los bailes exóticos deben ser marcados con los correspondientes tipos de lista.</li> + <li>Colocar las dos direcciones dentro de elementos {{htmlelement("address")}}. Cada línea de la dirección debe comenzar en una línea nueva, pero no en un párrafo nuevo.</li> +</ul> + +<p>Semánticas intralínea:</p> + +<ul> + <li>Los nombres de remitente y destinatario (también "Tel" e "Email") deben ser marcado con importancia (strong).</li> + <li>Deberás usar los elementos apropiados en las cuatro fechas contenidas en el documento para que puedan ser leidas por los motores de lectura automática.</li> + <li>La primera dirección y la primera fecha en la carta deben ser asignadas a un atributo de clase llamado "sender-column"; el código CSS lo añadirás posteriormente para que quede bien alineado, como debe ser en un formato de carta clásico.</li> + <li>Deberás utilizar el elemento apropiado para los cinco acrónimos/abreviaciones contenidos en el texto principal, proporcionándoles las extensiones correspondientes.</li> + <li>Marca apropiadamente los seis sub/superíndices.</li> + <li>Los símbolos de los grados, los mayor que y los símbolos de multiplicar deben ser marcados usando las referencias correctas.</li> + <li>Marca al menos dos palabras en el texto con fuerte importancia/énfasis.</li> + <li>Hay dos lugares donde deberíamos añadir hyperlinks; añádelos con títulos. Como sitio donde apuntan simplemente usa: http://example.com.</li> + <li>Marca con el elemento apropiado el lema de la universidad y la cita del autor.</li> +</ul> + +<p>El encabezamiento del documento:</p> + +<ul> + <li>El juego de caracteres del documento deberá ser utf-8 usando una etiqueta meta adecuada.</li> + <li>El autor de la carta debe estar especificado con la etiqueta meta correspondiente.</li> + <li>El CSS proporcionado deberá estar incluido dentro de la etiqueta adecuada.</li> +</ul> + +<h2 id="Pistas_y_recomendaciones">Pistas y recomendaciones</h2> + +<ul> + <li>Utiliza el <a href="https://validator.w3.org/">Validador de HTML W3C HTML</a> para validar tu HTML; recibirás puntos de bonificación si se valida.</li> + <li>No necesitas conocer CSS para hacer este ejercicio; solo debes poner el CSS proporcionado en el elemento HTML adecuado.</li> +</ul> + +<h2 id="Example">Example</h2> + +<p>The following screenshot shows an example of what the letter might look like after being marked up.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/12291/letter-screengrab.png" style="border: 1px solid black; display: block; margin: 0px auto;"></p> + +<h2 id="Evaluación">Evaluación</h2> + +<p>Si estás haciendo esta prueba como parte de un curso organizado, deberías entregar tu trabajo al profesor para que lo corrija. Si estás auto-aprendiendo puedes conseguir la guía de corrección fácilmente pidiendola en el <a href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">Hilo del area de aprendizaje</a>, o en el canal IRC de <a href="irc://irc.mozilla.org/mdn">#mdn</a> en <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Intenta hacerlo primero — no ganarás nada haciendo trampas.</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Learn/HTML/Introduction_to_HTML")}}</p> diff --git a/files/es/learn/html/introduccion_a_html/metados_en/index.html b/files/es/learn/html/introduccion_a_html/metados_en/index.html new file mode 100644 index 0000000000..6fc5f94ab0 --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/metados_en/index.html @@ -0,0 +1,299 @@ +--- +title: ¿Qué hay en la cabecera? Metadatos en HTML +slug: Learn/HTML/Introduccion_a_HTML/Metados_en +tags: + - Cabecera + - CodingScripting + - Guía + - HTML + - Meta + - Metadatos + - Novato + - Principiante + - favicon + - head + - lang + - metadata +translation_of: Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Getting_started", "Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">El elemento {{Glossary("Head", "head")}} de un documento HTML es la parte que no se muestra en el navegador cuando se carga la página. Contiene información como el título ({{htmlelement("title")}}) de la página, enlaces al {{Glossary("CSS")}} (si quieres aplicar estilo a tu contenido HTML con CSS), enlaces para personalizar <code>favicon</code>, y otros metadatos (datos sobre el HTML, como quién lo escribió y palabras claves importantes que describen el documento). En este artículo abarcaremos todo esto y más, para darte bases sólidas en el manejo del marcado y otro código que debería estar presente en tu cabecera.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Estar familiarizado con el HTML básico, que se expone en {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con el HTML")}}.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender acerca de la cabecera HTML {{Glossary("Head", "head")}}, cuál es su propósito, los elementos más importantes que puede contener, y qué efecto puede tener sobre el documento HTML.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_hay_en_la_cabecera_HTML">¿Qué hay en la cabecera HTML?</h2> + +<p>Vamos a revisar el {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started#Anatomy_of_an_HTML_document", "documento HTML que se revisó en el artículo anterior")}}:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Mi página de prueba</title> + </head> + <body> + <p>Esta es mi página</p> + </body> +</html></pre> + +<p>La cabecera HTML es el contenido del elemento {{htmlelement("head")}} — a diferencia del contenido del elemento {{htmlelement("body")}} (que sí se muestra en la página cuando se carga en el navegador), el contenido de la cabecera no se muestra en la página. Por el contrario, la función de la cabecera es contener los {{Glossary("Metadata", "metadatos")}} del documento. En el ejemplo anterior, la cabecera es bastante reducida:</p> + +<pre class="brush: html notranslate"><head> + <meta charset="utf-8"> + <title>Mi página de prueba</title> +</head> </pre> + +<p>En páginas más grandes, sin embargo, la cabecera puede llegar a contener bastantes elementos. Prueba a ir a algunos de tus sitios web favoritos y comprueba el contenido de la cabecera usando las {{web.link("/es/docs/Learn/Common_questions/What_are_browser_developer_tools", "herramientas para el desarrollador")}}. Nuestro objetivo aquí no es mostrarte cómo usar todo lo que puedes incluir en la cabecera, sino enseñarte cómo usar los elementos principales que vas a incluir en la cabecera y que te familiarices con ellos. Empecemos.</p> + +<h2 id="Añadir_un_título">Añadir un título</h2> + +<p>Ya hemos visto el elemento {{htmlelement("title")}} en acción — se puede usar para poner un título al documento. Sin embargo, esto se puede confundir con el elemento {{htmlelement("h1")}}, que se utiliza para poner un encabezado de nivel superior al cuerpo de tu contenido — esto también se conoce como el título de la página. ¡Pero son cosas diferentes!</p> + +<ul> + <li>El elemento {{htmlelement("h1")}} aparece en la página cuando se carga en el navegador — en general debería haber uno solo por página, para especificar el título del contenido de tu página (el título de tu historia, el título de la noticia, o de lo que sea apropiado según el uso que le des).</li> + <li>El elemento {{htmlelement("title")}} es un metadato que representa el título de todo el documento HTML (no del contenido del documento).</li> +</ul> + +<h3 id="Aprendizaje_activo_Análisis_de_un_ejemplo_sencillo">Aprendizaje activo: Análisis de un ejemplo sencillo</h3> + +<ol> + <li>Para comenzar este aprendizaje activo, te proponemos ir a nuestro repositorio de GitHub y descargues una copia de nuestra página <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/the-html-head/title-example.html">title-example.html</a>. Lo puedes hacer de las siguientes maneras: + + <ol> + <li>Copia y pega el código de la página en un archivo de texto nuevo en tu editor de código, luego guárdalo en un lugar conveniente.</li> + <li>Presiona el botón "Raw" en la página de GitHub, lo cual hace que aparezca el código sin procesar (posiblemente en una nueva pestaña del navegador). A continuación, en el menú de tu navegador elige <em>Archivo → Guardar página como...</em> y selecciona un lugar adecuado para guardar el archivo.</li> + </ol> + </li> + <li>Ahora abre el archivo en tu navegador. Deberías ver algo como esto: + <p><img alt="Una sencilla página web con el título configurado a <title> element, y el <h1> configurado a <h1> element." src="https://mdn.mozillademos.org/files/12323/title-example.png" style="display: block; margin: 0 auto;">Ahora debería quedar claro dónde aparece el contenido de <code><h1></code> y dónde aparece el contenido de <code><title></code>.</p> + </li> + <li>También podrías probar a abrir el código en tu editor de código, editar el contenido de estos elementos y luego actualizar la página en tu navegador. Juega un poco con ello.</li> +</ol> + +<p>El contenido del elemento <code><title></code> también se usa de otras formas. Por ejemplo, si intentas marcar la página como favorita (<strong>Marcadores → Marcar esta página</strong>, o el icono en forma de estrella de Firefox), verás que el nombre que se sugiere para el marcado es el contenido del elemento <code><title></code>.</p> + +<p><img alt="Se está marcando una página web en Firefox; el nombre del marcador se ha completado automáticamente con el contenido del elemento <title>" src="https://mdn.mozillademos.org/files/12337/bookmark-example.png" style="display: block; margin: 0 auto;"></p> + +<p>El contenido de <code><title></code> también se usa en el resultado de las búsquedas, como verás a continuación.</p> + +<h2 id="Metadatos_el_elemento_<meta>">Metadatos: el elemento <meta></h2> + +<p>Los metadatos son datos que describen datos, y HTML tiene una forma «oficial» de introducir metadatos en un documento — el elemento {{htmlelement("meta")}}. Por supuesto, el resto de los elementos de los que hablaremos en este artículo también se podrían considerar metadatos. Hay muchos diferentes tipos de elementos <code><meta></code> que se pueden incluir en el <head> de tu página, pero no vamos a intentar explicarlos todos en esta etapa porque resultaría demasiado confuso. En lugar de ello vamos a explicar algunas cuestiones con las que seguramente te vas a encontrar, solo para que te hagas una idea.</p> + +<h3 id="La_codificación_de_caracteres_de_tu_documento">La codificación de caracteres de tu documento</h3> + +<p>El ejemplo que vimos arriba incluía esta línea:</p> + +<pre class="brush: html notranslate"><meta charset="utf-8"></pre> + +<p>Este elemento simplemente especifica la codificación de caracteres del documento — es decir, el conjunto de caracteres que el documento puede usar. <code>utf-8</code> es un conjunto de caracteres universal que incluye casi todos los caracteres de casi cualquier idioma humano. Esto significa que tu página web podrá gestionar la visualización de cualquier idioma; por lo tanto, resulta una buena idea configurarlo en cada página web que crees. Por ejemplo, tu página podría gestionar inglés y japonés sin problemas:</p> + +<p><img alt="Una página web que contiene caracteres en inglés y japonés, con la codificación de caracteres establecida en universal o utf-8. Ambos idiomas se muestran bien." src=" https://mdn.mozillademos.org/files/12343/correct-encoding.png" style="display: block; margin: 0 auto;">Si configuras tu codificación de caracteres en <code>ISO-8859-1</code>, por ejemplo (el juego de caracteres para el alfabeto latino), la representación de tu página puede aparecer desordenada:</p> + +<p><img alt="una página web que contiene caracteres en inglés y japonés, con la codificación de caracteres configurada en latín. Los caracteres japoneses no se muestran correctamente" src="https://mdn.mozillademos.org/files/12341/bad-encoding.png" style="display: block; height: 365px; margin: 0px auto; width: 604px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Algunos navegadores (Chrome, por ejemplo) automáticamente arreglan la codificación de caracteres incorrecta, de modo que según el navegador que uses, puede que no te topes con este problema. Aun así, deberías incluir una codificación de caracteres <code>utf-8</code> en tu página web para evitar que se presenten potenciales problemas con otros navegadores.</p> +</div> + +<h3 id="Aprendizaje_activo_Experimenta_con_la_codificación_de_caracteres">Aprendizaje activo: Experimenta con la codificación de caracteres</h3> + +<p>Para probar esto, vuelve a visitar la plantilla HTML simple que obtuviste en la sección anterior sobre <code><title></code> (la página <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/the-html-head/title-example.html">title-example.html</a>) e intenta cambiar el valor de la propiedad <code>meta charset</code> por <code>ISO-8859-1</code> y añade el japonés a tu página. Este es el código que usamos:</p> + +<pre class="brush: html notranslate"><p>Ejemplo en japonés: ご飯が熱い。</p></pre> + +<h3 id="Añadir_un_autor_y_descripción">Añadir un autor y descripción</h3> + +<p>Muchos elementos <code><meta></code> incluyen atributos <code>name</code> y <code>content</code>:</p> + +<ul> + <li><code>name</code> especifica el tipo de metadato del que se trata; es decir, qué tipo de información contiene.</li> + <li><code>content</code> especifica el contenido del metadato en sí.</li> +</ul> + +<p>Dos de esos metadatos que resultan útiles de incluir en tu página definen al autor de la página y proporcionan una descripción concisa de la página. Veamos un ejemplo:</p> + +<pre class="brush: html notranslate"><meta name="author" content="Chris Mills"> +<meta name="description" content="El área de aprendizaje de MDN pretende +proporcionar a los recién llegados a la web todo lo que deben +saber para empezar a desarrollar páginas web y aplicaciones web."></pre> + +<p>Especificar un autor resulta ventajoso por diversos motivos: es útil saber quién escribió la página para poder ponerte en contacto con el autor si tienes preguntas sobre el contenido. Algunos sistemas de gestión de contenido tienen herramientas para extraer automáticamente la información del autor de la página y ponerla a disposición para tales fines.</p> + +<p>Especificar una descripción que incluya palabras clave relacionadas con el contenido de tu página resulta útil porque tiene el potencial de hacer que la página aparezca más arriba en las búsquedas relevantes que efectúan los motores de búsqueda (tales actividades se denominan optimizaciones del motor de búsqueda ({{web.link("/es/docs/Glossary/SEO", "Optimización de motores de búsqueda")}}) o {{Glossary("SEO")}}.)</p> + +<h3 id="Aprendizaje_activo_El_uso_de_la_descripción_en_los_motores_de_búsqueda">Aprendizaje activo: El uso de la descripción en los motores de búsqueda</h3> + +<p>La descripción también se usa en las páginas de resultados del motor de búsqueda. Repasemos un ejercicio para explorar esto:</p> + +<ol> + <li>Ve a la página de inicio de <a href="https://developer.mozilla.org/es/">Mozilla Developer Network</a>.</li> + <li>Observa el código fuente de la página (<kbd>Ctrl</kbd>+clic o clic con el botón derecho en la página y selecciona la opción del menú <strong>Ver código fuente de la página</strong>).</li> + <li>Encuentra la etiqueta del metadato <strong>description</strong>. Se verá más o menos así (aunque puede cambiar con el tiempo): + <pre class="brush: html notranslate"><meta name="description" content="The Mozilla Developer + Network (MDN) proporciona información sobre tecnologías + de código abierto que incluyen HTML, CSS y APIs tanto para sitios web como para aplicaciones HTML5. + También documenta productos Mozilla como el sistema operativo Firefox."></pre> + </li> + <li>Ahora busca "Mozilla Developer Network" en tu motor de búsqueda favorito (nosotros hemos utilizado Google). Observarás que efectivamente merece la pena que tener el contenido de la descripción <code><meta></code> y el elemento <code><title></code> que se utiliza en la búsqueda. + <p><img alt='Resultado de búsqueda en Yahoo para "Mozilla Developer Network"' src="https://mdn.mozillademos.org/files/16074/mdn-search-result.png" style="border-style: solid; border-width: 1px; display: block; height: 982px; margin: 0px auto; width: 1302px;"></p> + </li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: En Google verás algunas subpáginas relevantes de MDN enumeradas debajo del enlace principal a la página principal de MDN (se trata de los llamados <strong>sitelinks</strong> y se pueden configurar con las <a href="http://www.google.com/webmasters/tools/">Herramientas de administrador de Google</a>), una forma de mejorar los resultados para tu sitio con el motor de búsqueda de Google.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Muchas características <code><meta></code> ya no se usan. Por ejemplo, los motores de búsqueda ignoran el elemento <code><meta></code> (<code><meta name="keywords" content="pon, tus, palabras clave, aquí"></code>), que se supone que facilita palabras clave para motores de búsqueda de forma que se determine la relevancia de esa página según diferentes términos de búsqueda, porque los <strong>spammers</strong> rellenaban la lista de palabras clave con cientos de palabras clave que sesgaban los resultados.</p> +</div> + +<h3 id="Otros_tipos_de_metadatos">Otros tipos de metadatos</h3> + +<p>Al navegar por la web también puedes encontrar otros tipos de metadatos. Muchas de las funciones que verás en los sitios web son creaciones propietarias diseñadas para proporcionar a ciertos sitios (como los sitios de redes sociales) información específica que puedan usar.</p> + +<p>Por ejemplo, <a href="http://ogp.me/">Open Graph Data</a> es un protocolo de metadatos que Facebook inventó para proveer metadatos más ricos para los sitios web. En las fuentes de código de MDN, encontrarás esto:</p> + +<pre class="brush: html notranslate"><meta property="og:image" content="https://developer.cdn.mozilla.net/static/img/opengraph-logo.dc4e08e2f6af.png"> +<meta property="og:description" content="The Mozilla Developer Network (MDN) proporciona información +sobre tecnologías Open Web, incluidas HTML, CSS y APIs para ambos sitios web +y aplicaciones HTML5. También documenta productos Mozilla, como el sistema operativo Firefox."> +<meta property="og:title" content="Mozilla Developer Network"></pre> + +<p>Un efecto de esto es que cuando desde Facebook enlazas a un MDN, el enlace aparece con una imagen y una descripción, lo que resulta en una experiencia más enriquecedora para los usuarios.</p> + +<p><img alt="Datos abiertos del protocolo de gráficos de la página de inicio de MDN como se muestra en Facebook, mostrando una imagen, título y descripción." src="https://mdn.mozillademos.org/files/12349/facebook-output.png" style="display: block; margin: 0 auto;"></p> + +<p>Twitter también tiene sus metadatos propios, las <a href="https://developer.twitter.com/en/docs/tweets/optimize-with-cards/overview/abouts-cards">Twitter Cards</a>, que tienen un efecto similar cuando la URL del sitio se muestra en twitter.com. Por ejemplo:</p> + +<pre class="brush: html notranslate"><meta name="twitter:title" content="Mozilla Developer Network"></pre> + +<h2 id="Agregar_iconos_personalizados_a_tu_sitio">Agregar iconos personalizados a tu sitio</h2> + +<p>Para enriquecer un poco más el diseño de tu sitio puedes añadir en tus metadatos referencias a iconos personalizados, que se mostrarán en determinados contextos. El más común de ellos es el <strong>favicon</strong> (abreviatura de <strong><em>favorite icon</em></strong> —<strong>icono </strong>«<strong>favorito</strong>», referido al uso que se le da en las listas de «favoritos» o de marcadores («<strong>bookmarks</strong>»).</p> + +<p>El humilde <code>favicon</code> ha existido durante muchos años. Es el primer icono de este tipo: un icono cuadrado de 16 píxeles que se utiliza en varios lugares. Es posible que veas (según el navegador) <code>favicon</code>s que se muestran en la pestaña del navegador que contiene cada página abierta y junto a las páginas marcadas en el panel de marcadores.</p> + +<p>Para añadir un <code>favicon</code> a tu página:</p> + +<ol> + <li>Guárdalo en el mismo directorio que la página <strong>index</strong> de tu sitio, en formato <code>.ico</code> (la mayoría de los buscadores admiten <code>favicon</code> en los formatos más comunes como <code>.gif</code> o <code>.png</code>, pero usar el formato <em>ICO</em> garantiza que funcionará hasta en Internet Explorer 6.)</li> + <li>Añade la siguiente línea de referencia en el {{HTMLElement("head")}} de tu HTML: + <pre class="brush: html notranslate"><link rel="shortcut icon" href="favicon.ico" type="image/x-icon"></pre> + </li> +</ol> + +<p>Los navegadores modernos usan <code>favicon</code>s en diversos lugares, como en la etiqueta de la página que está abierta y en el panel de favoritos cuando la añades a tu lista de páginas favoritas:</p> + +<p><img alt="El panel de marcadores de Firefox, que muestra un ejemplo marcado con un favicon junto a él." src="https://mdn.mozillademos.org/files/12351/bookmark-favicon.png" style="display: block; margin: 0 auto;"></p> + +<p>Hoy día hay un montón de otros tipos de iconos a tener presentes. Por ejemplo, los encontrarás en el código fuente de la página de inicio de MDN:</p> + +<pre class="brush: html notranslate"><!-- iPad de tercera generación con pantalla de alta resolución: --> +<link rel="apple-touch-icon-precomposed" sizes="144x144" href="https://developer.cdn.mozilla.net/static/img/favicon144.a6e4162070f4.png"> +<!-- iPhone con pantalla de alta resolución: --> +<link rel="apple-touch-icon-precomposed" sizes="114x114" href="https://developer.cdn.mozilla.net/static/img/favicon114.0e9fabd44f85.png"> +<!-- iPad de primera y segunda generación: --> +<link rel="apple-touch-icon-precomposed" sizes="72x72" href="https://developer.cdn.mozilla.net/static/img/favicon72.8ff9d87c82a0.png"> +<!-- Dispositivos iPhone sin pantalla Retina, iPod Touch y Android 2.1+: --> +<link rel="apple-touch-icon-precomposed" href="https://developer.cdn.mozilla.net/static/img/favicon57.a2490b9a2d76.png"> +<!-- favicon básico --> +<link rel="shortcut icon" href="https://developer.cdn.mozilla.net/static/img/favicon32.e02854fdcf73.png"></pre> + +<p>Los comentarios explican para qué se usa cada icono (estos elementos abarcan situaciones como aportar un buen icono de alta resolución para usarlo cuando la página web se guarda en la página de inicio de un iPad).</p> + +<p>No te preocupes demasiado sobre la implementación de todos estos tipos de iconos por el momento; se trata de una característica bastante avanzada y no se espera que tengas conocimientos de ello para avanzar en el curso. El propósito principal aquí es darte a conocer estos elementos por si te los encuentras mientras examinas el código fuente de otros sitios web.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si tu sitio web utiliza una política de seguridad de contenido (<em>content security policy o CSP</em>) para mejorar la seguridad, la política afecta al <code>favicon</code>. Si te encuentras con problemas como que el <code>favicon</code> no se carga, comprueba que la respuesta a {{HTTPHeader("Content-Security-Policy")}} del <code>header</code> <a href="">Content-Security-Policy</a> para la <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/img-src"> directriz <code>img-src</code></a> en la cabecera no impide el acceso a este.</p> +</div> + +<h2 id="Aplicar_CSS_y_JavaScript_a_HTML">Aplicar CSS y JavaScript a HTML</h2> + +<p>Prácticamente todos los sitios web usan {{Glossary("CSS")}} para darles un buen aspecto y {{Glossary("JavaScript")}} para añadir funcionalidades interactivas, como reproductores de vídeo, mapas, juegos y demás. La manera más habitual de añadir CSS y JavaScript a una página web es con los elementos <code><link></code> y el elemento <code><script></code>, respectivamente.</p> + +<ul> + <li> + <p>El elemento {{HTMLElement("link")}} siempre debe ir dentro del {{HTMLElement("header")}} de tu documento. Este toma dos atributos, <code>rel="stylesheet"</code>, que indica que es la hoja de estilo del documento, y <code>href</code>, que contiene la ruta al archivo de la hoja de estilo:</p> + + <pre class="brush: html notranslate"><link rel="stylesheet" href="my-css-file.css"></pre> + </li> + <li> + <p>El elemento <code><script></code> también debería ir en el <code>head</code>, y debería incluir un atributo <code>src</code> con la ruta al JavaScript que quieres cargar, y <code>defer</code>, que básicamente le dice al navegador que cargue el JavaScript al mismo tiempo que el HTML de la página. Esto es útil porque hace que todo el HTML se cargue antes de ejecutar el JavaScript, para que no haya errores porque el JavaScript ha intentado acceder a un elemento HTML que todavía no existe. De hecho hay múltiples formas de gestionar la carga del JavaScript en una página, pero esta es «a prueba de bombas» para los navegadores modernos (para el resto de las formas, lee el artículo {{web.link("/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript#Script_loading_strategies", "Estrategias de carga de scripts")}}).</p> + + <pre class="brush: html notranslate"><script src="my-js-file.js"></script></pre> + + <div class="blockIndicator note"> + <p><strong>Nota</strong>: El elemento <code><script></code> puede parecer un elemento vacío pero no lo es, y por lo tanto necesita una etiqueta de cierre. En vez de apuntar a un archivo de <code>script</code> externo, también puedes colocar tu código dentro del elemento <code><script></code>.</p> + </div> + </li> +</ul> + +<h3 id="Aprendizaje_activo_aplicar_CSS_y_JavaScript_a_una_página">Aprendizaje activo: aplicar CSS y JavaScript a una página</h3> + +<ol> + <li>Para iniciar este aprendizaje activo, haz una copia de nuestros archivos <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/the-html-head/meta-example.html">meta-example.html</a>, <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/the-html-head/script.js">script.js</a> y <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/the-html-head/style.css">style.css</a>, y guárdalos en un mismo directorio de tu ordenador. Asegúrate de que se guardan con los nombres y extensiones correctas.</li> + <li>Abre el archivo HTML tanto en tu navegador como en tu editor de texto.</li> + <li>Sigue la información facilitada anteriormente y añade los elementos <code><link></code> y <code><script></code> a tu HTML para aplicarle CSS y JavaScript.</li> +</ol> + +<p>Si lo has hecho correctamente, al guardar tu HTML y actualizar tu navegador, deberías poder ver que las cosas han cambiado:</p> + +<p><img alt="Ejemplo que muestra una página con CSS y JavaScript aplicados. El CSS ha hecho que la página se vuelva verde, mientras que JavaScript ha agregado una lista dinámica a la página" src="https://mdn.mozillademos.org/files/12359/js-and-css.png" style="display: block; margin: 0 auto;"></p> + +<ul> + <li>El JavaScript ha añadido una lista vacía a la página. Ahora, cuando haces clic en cualquier sitio de la lista, aparece un cuadro de diálogo que te solicita que introduzcas el texto para un nuevo elemento de la lista. Cuando pulsas el botón OK, se añade a la lista el elemento con el texto nuevo. Cuando haces clic a un elemento de la lista aparece un cuadro de diálogo que te permite cambiar el texto del elemento.</li> + <li>El CSS ha pintado el fondo de verde y ha agrandado el texto. También ha aplicado estilo a algún contenido que el JavaScript ha añadido a la página (la barra roja con el borde negro es el estilo que el CSS ha aplicado a la lista generada con JavaScript).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Si te encallas en este ejercicio y no logras ejecutar los archivos CSS/JS, comprueba tu página de ejemplo <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/the-html-head/css-and-js.html">css-and-js.html</a>.</p> +</div> + +<h2 id="Establecer_el_idioma_principal_del_documento">Establecer el idioma principal del documento</h2> + +<p>Por último, merece la pena mencionar que puedes (y realmente deberías) especificar el idioma de tu página. Esto se puede hacer añadiendo el atributo {{web.link("/es/docs/Web/HTML/Global_attributes/lang", "lang")}} a la etiqueta de apertura del HTML (como se ve en el <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/the-html-head/meta-example.html">meta-example.html</a> y se muestra abajo).</p> + +<pre class="brush: html notranslate"><html lang="es-MX"></pre> + +<p>Esto resulta útil en muchos sentidos. Los motores de búsqueda indizarán tu documento HTML de modo más efectivo si estableces el idioma (permitiendo, por ejemplo, que aparezca correctamente en los resultados del idioma especificado), y resulta útil para que las personas con discapacidad visual que utilizan los lectores de pantalla (por ejemplo, la palabra «six» existe tanto en francés como en inglés, pero su pronunciación es diferente).</p> + +<p>También puedes establecer que las subsecciones de tu documento se reconozcan en diferentes idiomas. Por ejemplo, podemos establecer que nuestra sección de japonés se reconozca como japonés, de la siguiente manera:</p> + +<pre class="brush: html notranslate"><p>Ejemplo Japonés: <span lang="ja">ご飯が熱い。</span>.</p></pre> + +<p>El estándar {{interwiki("wikipedia", "ISO_639-1")}} define estos códigos. Puedes encontrar más información sobre ello en <a href="https://www.w3.org/International/articles/language-tags/">Etiquetas de idioma en HTML y XML</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Esto marca el final de nuestra guía rápida del {{Glossary("head")}} de HTML — aún hay muchas más cosas que puedes hacer aquí, pero una guía exhaustiva puede ser aburrida y confusa a estas alturas, ¡y nosotros queremos darte una idea de las cuestiones más comunes con las que te encontrarás aquí por ahora! En el siguiente artículo veremos los fundamentos de texto de HTML.</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/Getting_started", "Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "¿Qué hay en el «head»? Metadatos en HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Fundamentos de texto HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Creando hipervínculos")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Formateo de texto avanzado")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Estructura web y documentación")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Depurar HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Marcado para una carta")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Estructuración del contenido de una página")}}</li> +</ul> diff --git a/files/es/learn/html/introduccion_a_html/prueba_tus_habilidades_colon__enlaces/index.html b/files/es/learn/html/introduccion_a_html/prueba_tus_habilidades_colon__enlaces/index.html new file mode 100644 index 0000000000..0e8dc1bfaf --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/prueba_tus_habilidades_colon__enlaces/index.html @@ -0,0 +1,99 @@ +--- +title: 'Prueba tus habilidades: Enlaces' +slug: 'Learn/HTML/Introduccion_a_HTML/Prueba_tus_habilidades:_Enlaces' +translation_of: 'Learn/HTML/Introduction_to_HTML/Test_your_skills:_Links' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta pueba de habilidad es evaluar si has comprendido nuestro artículo <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks">Creando hipervínculos</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes intentar resolver esta prueba en los editores interactivos más abajo, sin embargo, puede ser útil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, o <a href="https://glitch.com/">Glitch</a> para trabajar en las tareas.<br> + <br> + Si te atascas, pide ayuda — mira la sección {{anch("Evaluación o ayuda adicional")}} al final de esta página.</p> +</div> + +<h2 id="Enlaces_1">Enlaces 1</h2> + +<p>En esta tarea necesitamos tu ayuda para completar los enlaces en nuestra página de información sobre Ballenas:</p> + +<ul> + <li>El primer enlace debería estar vinculado a una página llamada <code>whales.html</code>, que está en el mismo directorio que la página actual.</li> + <li>También queremos agregarle un cuadro de información ("tooltip") cuando pase el puntero sobre el enlace, que le diga al usuario que la página incluye informacion sobre las Ballenas azules y las Ballenas blancas.</li> + <li>El segundo enlace deberá convertirse en un vínculo que abra un correo electrónico en la aplicación de correo por defecto del usuario, con el destinatario "whales@example.com".</li> + <li>Conseguirás un punto de bonificación si tambien configuras que la línea del asunto del correo electrónico tenga como texto predeterminado "Preguntas sobre Ballenas".</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota:</strong> El primer enlace en el ejemplo tiene el atributo <code>target="_blank"</code> , así que cuando haces click en él, abre la página en una pestaña nueva. Esto no es estrictamente una buena práctica, pero lo hemos hecho aquí para que la página no se abra en el <code><iframe></code> incrustado, ¡eliminando el código de ejemplo en el proceso!</p> +</div> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/introduction-to-html/tasks/links/links1.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/tasks/links/links1-download.html">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Enlaces_2">Enlaces 2</h2> + +<p>En esta tarea queremos que completes los cuatro enlaces para que se dirijan al lugar apropiado:</p> + +<ul> + <li>El primer enlace debería vincular a una imagen llamada <code>blue-whale.jpg</code>, que se encuentra en una carpeta llamada <code>blue</code> dentro de la carpeta actual.</li> + <li>El segundo enlace debería vincular a una imagen llamada <code>narwhal.jpg</code>, que se encuentra en una carpeta llamada <code>narwhal</code>, que se encuentra en un nivel de carpetas sobre la carpeta actual.</li> + <li>El tercer enlace deberia vincular al sitio de búsqueda de imágenes de Google del Reino Unido. La URL base es <code>https://www.google.co.uk</code>, y la búsqueda de imágenes se ubica en un subdirectorio llamado <code>imghp</code>.</li> + <li>El cuarto enlace debería vincular al párrafo más al final de la página actual. Que tiene la ID <code>bottom</code>.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota:</strong> Los primeros tres enlaces en el ejemplo tienen el atributo <code>target="_blank"</code> especificado en ellos, abren la página enlazada en una nueva pestaña del navegador. Esto no es estrictamente una buena práctica, pero hemos hecho esto aquí para que las páginas no se abran dentro del <code><iframe></code> incrustado, ¡eliminando el código de ejemplo en el proceso!</p> +</div> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/introduction-to-html/tasks/links/links2.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/tasks/links/links2-download.html">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Enlaces_3">Enlaces 3</h2> + +<p>Los siguientes enlaces dirigen a una página informativa acerca de los Narvales, una dirección de correo electrónico de soporte, y un documento PDF cuyo tamaño es 4MB. En esta tarea queremos que:</p> + +<ul> + <li>Tomes los párrafos existentes con enlaces pobremente escritos, y los reescribas para que tengan un buen texto de enlace.</li> + <li>Agregues una advertencia a cualquier enlace que necesite una advertencia.</li> +</ul> + +<div class="blockIndicator note"> +<p><strong>Nota:</strong> Los primeros tres enlaces en el ejemplo tienen el atributo <code>target="_blank"</code> especificado en ellos, abren la página enlazada en una nueva pestaña del navegador. Esto no es estrictamente una buena práctica, pero hemos hecho esto aquí para que las páginas no se abran dentro del <code><iframe></code> incrustado, ¡eliminando el código de ejemplo en el proceso!</p> +</div> + +<p>Intenta actualizar el código en vivo más abajo para mostrar el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/introduction-to-html/tasks/links/links3.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/tasks/links/links3-download.html">Descarga el inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Puedes practicar estos ejemplos en los editores interactivos que se encuentran más arriba.</p> + +<p>Si deseas que tu trabajo sea evaluado, o estás atorado y quieres solicitar ayuda:</p> + +<ol> + <li>Pon tu trabajo en un editor en línea con capacidad de compartir como <a href="https://codepen.io/" rel="noopener">CodePen</a>, <a href="https://jsfiddle.net/" rel="noopener">jsFiddle</a>, o <a href="https://glitch.com/" rel="noopener">Glitch</a>. Puedes escribir el código por ti mismo, o usar los archivos de punto de inicio enlazados en las secciones superiores.</li> + <li>Escribe una publicación solicitando evaluacion y/o ayuda en el <a href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Tu publicación debería incluir: + <ul> + <li>Un título descriptivo como "Solicito evaluacion para la prueba de habilidad de texto básico HTML 1".</li> + <li>Detalles de lo que ya has intentado, y que te gustaría que hiciéramos, por ejemplo, si estas atascado y necesitas ayuda, o quieres una evaluación.</li> + <li>Un enlace al ejemplo que quieres que sea evaluado o por el que necesitas ayuda en un editor en linea con capacidad de compartir (como se mencionó en el paso 1 más arriba). Esta es una buena práctica - Es muy dificil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la tarea o página de evaluacion actual, para que podamos encontrar la pregunta con la cual necesitas ayuda.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/html/introduccion_a_html/prueba_tus_habilidades_colon__texto_básico_html/index.html b/files/es/learn/html/introduccion_a_html/prueba_tus_habilidades_colon__texto_básico_html/index.html new file mode 100644 index 0000000000..f35a083987 --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/prueba_tus_habilidades_colon__texto_básico_html/index.html @@ -0,0 +1,72 @@ +--- +title: 'Prueba tus habilidades: Texto básico HTML' +slug: 'Learn/HTML/Introduccion_a_HTML/Prueba_tus_habilidades:_Texto_básico_HTML' +tags: + - Aprendizaje + - HTML + - Principiante + - Prueba tus habilidades + - Texto +translation_of: 'Learn/HTML/Introduction_to_HTML/Test_your_skills:_HTML_text_basics' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta prueba de habilidad es evaluar si has comprendido el artículo <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/texto">Fundamentos de texto en HTML</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota:</strong> Puedes intentar resolverlo en los editores interactivos de más abajo, sin embargo puede ser muy úytil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, o <a href="https://glitch.com/">Glitch</a> para trabajar en las tareas.<br> + <br> + Si te atascas, entonces pídenos ayuda — busca en la sección {{anch("Assessment or further help")}} al final de esta página.</p> +</div> + +<h2 id="Texto_básico_HTML_1">Texto básico HTML 1</h2> + +<p>En esta tarea queremos que etiquetes el HTML entregado utilizando elementos semánticos de encabezado y párrafo. Intenta actualizando el código más abajo para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/introduction-to-html/tasks/basic-text/basic-text1.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/tasks/basic-text/basic-text1-download.html">Descarga el punto de inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Texto_básico_HTML_2">Texto básico HTML 2</h2> + +<p>En esta tarea necesitamos que cambies la primera lista no marcada en una lista no ordenada, y la segunda en una lista ordenada.</p> + +<p>Intenta actualizando el código más abajo para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/introduction-to-html/tasks/basic-text/basic-text2.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/tasks/basic-text/basic-text2-download.html">Descarga el punto de inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Texto_básico_HTML_3">Texto básico HTML 3</h2> + +<p>En esta tarea se te entrega un párrafo, y tu objetivo es usar algunos elementos en línea para marcar algunas palabras con importancia, y otras con énfasis</p> + +<p>Intenta actualizando el código más abajo para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/html/introduction-to-html/tasks/basic-text/basic-text3.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/tasks/basic-text/basic-text3-download.html">Descarga el punto de inicio de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Puedes practicar estos ejemplos en los editores interactivos que se encuentran más arriba.</p> + +<p>Si deseas que tu trabajo sea evaluado, o estás atorado y quieres solicitar ayuda:</p> + +<ol> + <li>Pon tu trabajo en un editor en línea con capacidad de compartir como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, o <a href="https://glitch.com/">Glitch</a>. Puedes escribir el código por ti mismo, o usar los archivos de punto de inicio enlazados en las secciones superiores.</li> + <li>Escribe una publicación solicitando evaluacion y/o ayuda en el <a class="external external-icon" href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. Tu publicación debería incluir: + <ul> + <li>Un título descriptivo como "Solicito evaluacion para la prueba de habilidad de texto básico HTML 1".</li> + <li>Detalles de lo que ya has intentado, y que te gustaría que hiciéramos, por ejemplo, si estas atascado y necesitas ayuda, o quieres una evaluación.</li> + <li>Un enlace al ejemplo que quieres que sea evaluado o por el que necesitas ayuda en un editor en linea con capacidad de compartir (como se mencionó en el paso 1 más arriba). Esta es una buena práctica - Es muy dificil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la tarea o página de evaluacion actual, para que podamos encontrar la pregunta con la cual necesitas ayuda.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/html/introduccion_a_html/test_your_skills_colon__advanced_html_text/index.html b/files/es/learn/html/introduccion_a_html/test_your_skills_colon__advanced_html_text/index.html new file mode 100644 index 0000000000..f29638eb81 --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/test_your_skills_colon__advanced_html_text/index.html @@ -0,0 +1,67 @@ +--- +title: 'Pon a prueba tus habilidades: texto HTML avanzado' +slug: 'Learn/HTML/Introduccion_a_HTML/Test_your_skills:_Advanced_HTML_text' +translation_of: 'Learn/HTML/Introduction_to_HTML/Test_your_skills:_Advanced_HTML_text' +--- +<div>{{learnsidebar}}</div> + +<p><span class="tlid-translation translation" lang="es"><span title="">El objetivo de esta prueba de habilidad es evaluar si ha entendido nuestras </span></span> <u><a href="/es/docs//en-US/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting">formato de texto avanzado</a></u> articulo.</p> + +<div class="blockIndicator note"> +<p><strong>NOTA</strong>:<span class="tlid-translation translation" lang="es"><span title="">Puede probar soluciones en los editores interactivos a continuación;</span> <span title="">sin embargo, puede resultar útil descargar el código y utilizar una herramienta en línea como</span></span> <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, o <a href="https://glitch.com/">Glitch </a><span class="tlid-translation translation" lang="es"><span title="">trabajar en las tareas.</span></span><br> + <br> + <span class="tlid-translation translation" lang="es"><span title="">Si se atasca, pídanos ayuda; consulte la</span></span> {{anch("Assessment or further help")}} section at the bottom of this page.</p> +</div> + +<h2 id="Texto_HTML_avanzado_1"><span class="tlid-translation translation" lang="es"><span title="">Texto HTML avanzado 1</span></span></h2> + +<p><span class="tlid-translation translation" lang="es"><span title="">En esta tarea, queremos que convierta los animales proporcionados y sus definiciones en una lista de descripción.</span><br> + <br> + <span title="">Intente actualizar el código en vivo a continuación para recrear el ejemplo terminado:</span></span></p> + +<p>{{EmbedGHLiveSample("learning-area/html/introduction-to-html/tasks/advanced-text/advanced-text1.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="/es/docs/https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/tasks/advanced-text/advanced-text1-download.html">Descarga el puno de partida para esta tarea</a> to work in your own editor or in an online editor.</p> +</div> + +<h2 id="Texto_HTML_avanzado_2"><span class="tlid-translation translation" lang="es"><span title="">Texto HTML avanzado 2</span></span></h2> + +<p><span class="tlid-translation translation" lang="es"><span title="">En esta tarea, queremos que agregue algo de semántica al HTML proporcionado de la siguiente manera:</span></span></p> + +<ul> + <li><span class="tlid-translation translation" lang="es"><span title="">Convierta el segundo párrafo en una cita a nivel de bloque e indique semánticamente que la cita se toma de</span></span> <a href="/en-US/docs/Learn/Accessibility">Accesibilidad</a>.</li> + <li><span class="tlid-translation translation" lang="es"><span title="">Marque semánticamente "HTML" y "CSS" como acrónimos, proporcionando expansiones como información sobre herramientas.</span></span></li> + <li><span class="tlid-translation translation" lang="es"><span title="">Asocia semánticamente fechas legibles por máquina con las fechas en el texto.</span></span></li> + <li><span class="tlid-translation translation" lang="es"><span title="">Utilice subíndice y superíndice para proporcionar la semántica correcta para las fórmulas químicas y fechas, y hacer que se muestren correctamente.</span></span></li> +</ul> + +<p><span class="tlid-translation translation" lang="es"><span title="">Intente actualizar el código en vivo a continuación para recrear el ejemplo terminado:</span></span></p> + +<p>{{EmbedGHLiveSample("learning-area/html/introduction-to-html/tasks/advanced-text/advanced-text2.html", '100%', 700)}}</p> + +<div class="blockIndicator note"> +<p><a href="/es/docs/https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/tasks/advanced-text/advanced-text2-download.html">Descarga el punto de partida para esta tarea </a><span class="tlid-translation translation" lang="es"><span title="">para trabajar en su propio editor o en un editor en línea.</span></span></p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional"><span class="tlid-translation translation" lang="es"><span title="">Evaluación o ayuda adicional</span></span></h2> + +<div class="text-wrap tlid-copy-target"> +<div class="result-shield-container tlid-copy-target"><span class="tlid-translation translation" lang="es"><span title="">Puede practicar estos ejemplos en los editores interactivos anteriores.</span><br> +<br> +<span title="">Si desea que se evalúe su trabajo, o está atascado y desea pedir ayuda:</span></span></div> + +<div class="result-shield-container tlid-copy-target"></div> +</div> + +<ol> + <li><span class="tlid-translation translation" lang="es"><span title="">Pon tu trabajo en un editor que se pueda compartir en línea, como</span></span> <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, o <a href="https://glitch.com/">Glitch</a>. <span class="tlid-translation translation" lang="es"><span title="">Puede escribir el código usted mismo o utilizar los archivos de punto de inicio vinculados en las secciones anteriores.</span></span></li> + <li><span class="tlid-translation translation" lang="es"><span title="">Escriba una publicación solicitando evaluación y / o ayuda en el</span></span> <a class="external external-icon" href="https://discourse.mozilla.org/c/mdn/learn" rel="noopener">MDN Discourse forum Learning category</a>. <span class="tlid-translation translation" lang="es"><span title="">Tu publicación debe incluir:</span></span> + <ul> + <li><span class="tlid-translation translation" lang="es"><span title="">Un título descriptivo como "Se busca evaluación para la prueba de habilidad de texto avanzado HTML 1".</span></span></li> + <li><span class="tlid-translation translation" lang="es"><span title="">Detalles de lo que ya ha probado y lo que le gustaría que hiciéramos, p. Ej.</span> <span title="">si está atascado y necesita ayuda, o quiere una evaluación.</span></span></li> + <li><span class="tlid-translation translation" lang="es"><span title="">Un enlace al ejemplo que desea evaluar o con el que necesita ayuda, en un editor que se puede compartir en línea (como se mencionó en el paso 1 anterior).</span> <span title="">Esta es una buena práctica para entrar: es muy difícil ayudar a alguien con un problema de codificación si no puede ver su código.</span></span></li> + <li><span class="tlid-translation translation" lang="es"><span title="">Un enlace a la página de la tarea o evaluación real, para que podamos encontrar la pregunta con la que desea ayuda.</span></span></li> + </ul> + </li> +</ol> diff --git a/files/es/learn/html/introduccion_a_html/texto/index.html b/files/es/learn/html/introduccion_a_html/texto/index.html new file mode 100644 index 0000000000..912acb7dfe --- /dev/null +++ b/files/es/learn/html/introduccion_a_html/texto/index.html @@ -0,0 +1,970 @@ +--- +title: Fundamentos de texto en HTML +slug: Learn/HTML/Introduccion_a_HTML/texto +tags: + - CodingScripting + - Encabezados + - Estructuras + - Guía + - HTML + - Introducción a HTML + - Novato + - Principiante + - Párrafos + - Texto + - aprende + - semántica +translation_of: Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML")}}</div> + +<p class="summary">Una de las principales funciones de HTML es dar al texto estructura y significado (también conocido como {{Glossary("semantics", "semántica")}}), de forma que un navegador pueda mostrarlo correctamente. Este articulo explica la forma en que se puede usar {{Glossary("HTML")}} para estructurar una página de texto añadiendo encabezados y párrafos, enfatizando palabras, creando listas y más.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Estar familiarizado con el HTML básico, que se expone en {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a marcar una página de texto básica para darle estructura y significado, incluidos párrafos, encabezados, listas, efectos de énfasis y citas.</td> + </tr> + </tbody> +</table> + +<h2 id="Conceptos_básicos_Encabezados_y_párrafos">Conceptos básicos: Encabezados y párrafos</h2> + +<p>La mayor parte del texto estructurado está compuesto por encabezados y párrafos, independientemente de si lees una historia, un periódico, un libro de texto, una revista, etc.</p> + +<p><img alt="Un ejemplo de la portada de un periódico, que muestra el uso de un encabezado, subtítulos y párrafos de nivel superior." src="https://mdn.mozillademos.org/files/12371/newspaper_small.jpg" style="display: block; margin: 0 auto;"></p> + +<p>El contenido estructurado simplifica la experiencia en la lectura y se disfruta más.</p> + +<p>En HTML, cada párrafo tiene que estar delimitado por un elemento {{HTMLElement("p")}}, como en este ejemplo:</p> + +<pre class="brush: html notranslate"><p>Soy un párrafo, ¡desde luego que lo soy!</p></pre> + +<p>Cada sección tiene que estar delimitada por un elemento de encabezado:</p> + +<pre class="brush: html notranslate"><h1>Yo soy el título de la historia</h1></pre> + +<p>Hay seis elementos de encabezado: {{HTMLElement("h1")}}, {{HTMLElement("h2")}}, {{HTMLElement("h3")}}, {{HTMLElement("h4")}}, {{HTMLElement("h5")}} y {{HTMLElement("h6")}}. Cada elemento representa un nivel de contenido diferente en el documento; <code><h1></code> representa el título principal, <code><h2></code> representa el subtítulo, <code><h3></code> representa el subtítulo del subtítulo, y así sucesivamente.</p> + +<h3 id="Cómo_establecer_la_estructura_jerárquica">Cómo establecer la estructura jerárquica</h3> + +<p>Por ejemplo, en esta historia, <code><h1></code> representa el título de la historia, <code><h2></code> representará el título de cada capítulo y <code><h3></code> las diferentes secciones del capítulo, y así sucesivamente.</p> + +<pre class="brush: html notranslate"><h1>El agujero aplastante</h1> + +<p>Por Chris Mills</p> + +<h2>Capítulo 1: La oscura noche</h2> + +<p>Era una noche oscura. En algún lugar, un búho ululó. La lluvia azotó el ...</p> + +<h2>Capítulo 2: El silencio eterno</h2> + +<p>Nuestro protagonista ni susurrar pudo al ver esa sombría figura ...</p> + +<h3>El espectro habla</h3> + +<p>Habían pasado varias horas más, cuando de repente el espectro se incorporó y exclamó: "¡Por favor, ten piedad de mi alma!"</p></pre> + +<p>Realmente es a tu elección lo que cada elemento involucrado represente, siempre y cuando la jerarquía tenga sentido. Solo es necesario que tengas en cuenta unas pocas buenas prácticas mientras creas la estructura:</p> + +<ul> + <li>Preferentemente debes usar solo un <code><h1></code> por página; este es el nivel de título superior, y todos los demás se sitúan por debajo de él en la jerarquía.</li> + <li>Asegúrate de que usas los títulos en el orden correcto en la jerarquía. No uses los <code><h3></code> para representar subtítulos, seguidos de los <code><h2></code> para representar los subtítulos de los subtítulos; eso no tiene sentido y provocará resultados extraños.</li> + <li>De los seis niveles de títulos disponibles, debes procurar no usar más de tres por página, a menos que creas que es realmente necesario. Los documentos con muchos niveles (es decir, una jerarquía de títulos muy profunda) son de difícil manejo y navegación. En esos casos se recomienda, si es posible, separar el contenido en varias páginas.</li> +</ul> + +<h3 id="¿Por_qué_necesitamos_estructura">¿Por qué necesitamos estructura?</h3> + +<p>Para responder a esta cuestión, echemos un vistazo a <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/html-text-formatting/text-start.html">text-start.html</a>; el apartado inicial de nuestro ejemplo en curso para este artículo (una buena receta de hummus). Debes guardar una copia de este archivo en tu ordenador porque después la necesitarás para los ejercicios prácticos. El cuerpo (<code><body></code>) de este documento incluye varios elementos de contenido que no están marcados de ninguna manera pero están separados por saltos de línea (se ha pulsado <strong>Intro</strong>/<strong>Retorno</strong> para continuar en la siguiente línea).</p> + +<p>Sin embargo, cuando abres el documento en tu navegador, verás que el texto aparece... ¡como una masa enorme!</p> + +<p><img alt="Una página web que muestra un muro de texto sin formato, porque no hay elementos en la página para estructurarlo." src="https://mdn.mozillademos.org/files/12972/text-no-formatting.png" style="display: block; height: 420px; margin: 0px auto; width: 594px;"></p> + +<p>Esto se debe a que no hay elementos que den estructura al contenido, por lo que el navegador no sabe qué es un encabezado y qué es un párrafo. Además:</p> + +<ul> + <li>Los usuarios que miran una página web tienden a escanearla rápidamente para encontrar el contenido relevante que hay en ella y a menudo empiezan por leer los encabezados para comenzar. (Solemos <a href="http://www.nngroup.com/articles/how-long-do-users-stay-on-web-pages/">pasar muy poco tiempo en una página web</a>). Si no pueden ver nada útil en unos segundos, es probable que se sientan frustrados y se vayan a otro sitio.</li> + <li>Los motores de búsqueda que indizan tu página consideran el contenido de los títulos como palabras clave importantes e influyen en la puntuación de búsqueda de la página. Sin encabezados, tu página tendrá un rendimiento bajo en términos de optimización de motores de búsqueda {{Glossary("SEO")}}.</li> + <li>Las personas con discapacidad visual severa no suelen leer páginas web: en lugar de ello, las escuchan. Lo hacen con un software llamado {{interwiki("wikipedia", "Lector de pantalla")}}. Este software proporciona acceso rápido a un contenido textual dado. Entre las diversas técnicas que emplean, leen los encabezados para proporcionar un esquema del documento que permite a los usuarios encontrar rápidamente la información que quieren. Si no hay encabezados disponibles, se ven obligados a escuchar el documento entero. </li> + <li>Para aplicar estilos al contenido con {{Glossary("CSS")}}, o para que haga cosas interesantes con {{Glossary("JavaScript")}}, necesitas tener elementos que delimiten el contenido relevante para que CSS/JavaScript se puedan focalizar en este efectivamente.</li> +</ul> + +<p>Por lo tanto, debemos dar a nuestro contenido una estructura definida.</p> + +<h3 id="Aprendizaje_Activo_Dar_estructura_a_nuestro_contenido">Aprendizaje Activo: Dar estructura a nuestro contenido</h3> + +<p>Pasemos directamente a un ejemplo real. En el ejemplo de abajo, añade elementos al texto en bruto en el campo <em>Código editable</em> para que en el campo <em>Salida en vivo</em> aparezcan como un encabezado y dos párrafos.</p> + +<p>Si te equivocas, siempre puedes restablecer el código anterior pulsando el botón <em>Restablecer</em>. Si encallas, pulsa el botón <em>Mostrar solución</em> para ver la respuesta...</p> + +<div class="hidden"> +<h6 id="Código_reproducible">Código reproducible</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 100px; width: 95%">Mi breve relato Soy estadístico y mi nombre es Trish. + +Mis piernas son de cartón y estoy casada con un pez.</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +var htmlSolution = '<h1>Mi breve relato</h1>\n<p>Soy estadístico y mi nombre es Trish.</p>\n<p>Mis piernas son de cartón y estoy casada con un pez.</p>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="¿Por_qué_necesitamos_semántica">¿Por qué necesitamos semántica?</h3> + +<p>Contamos con la semántica para todo lo que nos rodea. Nos basamos en experiencias previas para conocer la función de cada objeto cotidiano; cuando miramos un objeto, sabemos cuál debe ser su función. Entonces, por ejemplo, esperamos que un semáforo en rojo signifique "alto" y que un semáforo en verde signifique "avance". Las cosas se pueden complicar muy rápidamente si se aplica la semántica incorrecta. (¿Algún país usa rojo para significar "avance"? Esperemos que no).</p> + +<p>De manera similar, debemos asegurarnos de que utilizamos los elementos adecuados y damos a nuestro contenido el significado y función correctos y la apariencia adecuada. En este mismo sentido, el elemento {{HTMLElement("h1")}} es un elemento semántico que da al texto al que delimita la función (o significado) de un <em>titular de primer nivel en tu página</em>.</p> + +<pre class="brush: html notranslate"><h1>Este es un titular de primer nivel</h1></pre> + +<p>De manera predeterminada, el navegador le asignará una fuente de gran tamaño para darle el aspecto de un titular (aunque se le podrá dar el estilo que se quisiera usando CSS). Lo más importante es que su valor semántico se va a usar de diferente manera, por ejemplo, por los motores de búsqueda y los lectores de pantalla (como se mencionó antes).</p> + +<p>Por otra parte, podrías hacer que cualquier elemento <em>parezca</em> un titular de primer rango. Considera lo siguiente:</p> + +<pre class="brush: html notranslate"><span style="font-size: 32px; margin: 21px 0;">¿Es este un titular de primer rango?</span></pre> + +<p>Este es un elemento {{HTMLElement("span")}}. No tiene semántica. Se usa para delimitar contenido cuando se le quiere aplicar CSS (o tratarlo con JavaScript) sin proporcionarle ningún significado extra (encontrarás más información sobre este tipo de elemento más adelante en el curso). Hemos aplicado CSS a este elemento para que parezca un titular de primer nivel, pero al no tener valor semántico, no tiene ninguna de las ventajas añadidas que hemos descrito antes. Es una buena idea usar el elemento HTML apropiado para cada tarea.</p> + +<h2 id="Listas">Listas</h2> + +<p>Ahora volvamos nuestra atención hacia las listas. Las listas están en todos los aspectos de nuestra vida: desde la lista de compras a la lista de instrucciones que sigues inconscientemente para llegar a casa todos los días, o las listas de instrucciones que sigues en estos tutoriales. Las listas están en todos lados en la web también y hay tres diferentes tipos de las que nos vamos a ocupar.</p> + +<h3 id="Listas_no_ordenadas">Listas no ordenadas</h3> + +<p>Las listas no ordenadas se usan para marcar listas de artículos cuyo orden no es importante. Tomemos como ejemplo una lista de compras:</p> + +<pre class="brush: bash notranslate">leche +huevos +pan +hummus</pre> + +<p>Cada lista desordenada comienza con un elemento {{HTMLElement("ul")}} («<em>unordered list</em>») que delimita todos los elementos de la lista:</p> + +<pre class="brush: html notranslate"><ul> +leche +huevos +pan +hummus +</ul></pre> + +<p>El siguiente paso es delimitar cada artículo de la lista con un elemento {{HTMLElement("li")}} («<em>list item</em>»).</p> + +<pre class="brush: html notranslate"><ul> + <li>leche</li> + <li>huevos</li> + <li>pan</li> + <li>hummus</li> +</ul></pre> + +<h4 id="Aprendizaje_activo_marcar_una_lista_no_ordenada">Aprendizaje activo: marcar una lista no ordenada</h4> + +<p>Edita el siguiente ejemplo para crear tu propia lista HTML no ordenada.</p> + +<div class="hidden"> +<h6 id="Código_reproducible_2">Código reproducible</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 100px; width: 95%">leche +huevos +pan +hummus</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +var htmlSolution = '<ul>\n<li>leche</li>\n<li>huevos</li>\n<li>pan</li>\n<li>hummus</li>\n</ul>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible_2', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Listas_ordenadas">Listas ordenadas</h3> + +<p>Las listas ordenadas son aquellas en las que el orden de los elementos <em>sí</em> importa. Tomemos como ejemplo una lista de instrucciones para seguir un itinerario:</p> + +<pre class="brush: bash notranslate">Conduce hasta el final de la calle +Gira a la derecha +Sigue derecho por las dos primeras glorietas +Gira a la izquierda en la tercer glorieta +El colegio está a la derecha, 300 metros más adelante</pre> + +<p>La estructura de marcado es la misma que para las listas no ordenadas, excepto que debes delimitar los elementos de la lista con una etiqueta {{HTMLElement("ol")}} («ordered list»), en lugar de <code><ul></code>:</p> + +<pre class="brush: html notranslate"><ol> + <li>Conduce hasta el final de la calle</li> + <li>Gira a la derecha</li> + <li>Sigue derecho por las dos primeras glorietas</li> + <li>Gira a la izquierda en la tercer glorieta</li> + <li>El colegio está a tu derecha, 300 metros más adelante</li> +</ol></pre> + +<h4 id="Aprendizaje_activo_Marcar_una_lista_ordenada">Aprendizaje activo: Marcar una lista ordenada</h4> + +<p>Edita el siguiente ejemplo para crear tu propia lista ordenada en HTML.</p> + +<div class="hidden"> +<h6 id="Código_reproducible_3">Código reproducible</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 200px; width: 95%">Conduce hasta el final de la calle +Gira a la derecha +Sigue derecho por las dos primeras glorietas +Gira a la izquierda en la tercer glorieta +La escuela está a tu derecha, 300 metros por más adelante</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +var htmlSolution = '<ol>\n<li>Conduce hasta el final de la calle</li>\n<li>Gira a la derecha</li>\n<li>Sigue derecho por las dos primeras glorietas</li>\n<li>Gira a la izquierda en la tercer glorieta</li>\n<li>La escuela está a tu derecha, 300 metros más adelante</li>\n</ol>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible_3', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Aprendizaje_activo_marcar_la_página_de_tu_receta">Aprendizaje activo: marcar la página de tu receta</h3> + +<p>Llegados a este punto del artículo, tienes toda la información necesaria para marcar la página de ejemplo con tu receta. Puedes escoger entre guardar una copia local del archivo inicial <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/html-text-formatting/text-start.html">text-start.html</a> y trabajar en él, o hacerlo sobre el ejemplo editable de abajo. Probablemente sea mejor trabajar en tu copia local porque podrás guardar tu progreso, mientras que si lo haces sobre el ejemplo editable, los cambios se perderán la próxima vez que cargues la página. Ambos métodos tienen pros y contras.</p> + +<div class="hidden"> +<h6 id="Código_reproducible_4">Código reproducible</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 200px; width: 95%">Receta rápida de hummus + + Esta receta hace un hummus rápido y sabroso, sin ensuciar. Ha sido adaptada de varias recetas diferentes que he leído a lo largo de los años. + + El hummus es una deliciosa pasta espesa que se usa mucho en platos griegos y del Medio Oriente. Es muy sabroso con ensalada, carne a las brasas y pan de pitta. + + Ingredientes + + 1 lata (400g) de garbanzos (garbanzos) + 175g de tahini + 6 tomates secos + Medio pimiento rojo + Una pizca de pimienta de cayena + 1 diente de ajo + Una pizca de aceite de oliva + + Instrucciones + + Retira la piel del ajo y pica en trozos grandes. + Retira todas las semillas y el tallo del pimiento y pica en trozos grandes. + Agrega todos los ingredientes en un procesador de alimentos. + Procesa todos los ingredientes en una pasta + Si deseas un hummus "grueso", procésalo corto tiempo + Si deseas un hummus "suave", procésalo por más tiempo + + Para un sabor diferente, puedes intentar mezclar en una pequeña medida de limón y cilantro, ají, lima y chipotle, harissa y menta, o espinacas y queso feta. Pruébalo y confirma que esté en su punto. + + Almacenamiento + + Refrigera el hummus terminado en un recipiente sellado. Deberías poder usarlo durante aproximadamente una semana después de haberlo hecho. Si comienza a burbujear, definitivamente debes desecharlo. + + El hummus es apto para congelar; debes descongelarlo y usarlo en un par de meses.</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +var htmlSolution = '<h1>Receta rápida de hummus</h1>\n\n<p>Esta receta hace un hummus rápido y sabroso, sin ensuciar. Ha sido adaptada de varias recetas diferentes que he leído a lo largo de los años.</p>\n\n<p>El hummus es una deliciosa pasta espesa que se usa mucho en platos griegos y del Medio Oriente. Es muy sabroso con ensalada, carne a las brasas y pan de pitta.</p>\n\n<h2>Ingredientes</h2>\n\n<ul>\n<li>1 lata (400g) de garbanzos (garbanzos)</li>\n<li>175g de tahini</li>\n<li>6 tomates secos</li>\n<li>Medio pimiento rojo</li>\n<li>Una pizca de pimienta de cayena</li>\n<li>1 diente de ajo</li>\n<li>Una pizca de aceite de oliva</li>\n</ul>\n\n<h2>Instrucciones</h2>\n\n<ol>\n <li>Retira la piel del ajo y pica en trozos grandes.</li>\n<li>Retira todas las semillas y el tallo del pimiento, y pica en trozos grandes.</li>\n<li>Agrega todos los ingredientes en un procesador de alimentos.</li>\n<li>Procesa todos los ingredientes en una pasta.</li>\n<li>Si deseas un hummus "grueso", procésalo corto tiempo.</li>\n<li>Si deseas un hummus "suave", procésalo por más tiempo.</li>\n</ol>\n\n<p>Para un sabor diferente, puedes intentar mezclar una pequeña medida de limón y cilantro, ají, lima y chipotle, harissa y menta, o espinacas y queso feta. Pruébalo y confirma que esté en su punto.</p>\n\n<h2>Almacenamiento</h2>\n\n<p>Refrigera el hummus terminado en un recipiente sellado. Deberías poder usarlo durante aproximadamente una semana después de haberlo hecho. Si comienza a burbujear, definitivamente debes desecharlo.</p>\n\n<p>El hummus es adecuado para congelar; debes descongelarlo y usarlo en un par de meses.</p>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible_4', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Si encallas, siempre puedes pulsar el botón <em>Mostrar solución</em> o comprobar el ejemplo completo <a href="https://github.com/mdn/learning-area/blob/master/html/introduction-to-html/html-text-formatting/text-complete.html">text-complete.html</a> en nuestro repositorio de Github.</p> + +<h3 id="Listas_anidadas">Listas anidadas</h3> + +<p>Es perfectamente correcto anidar una lista dentro de otra. Posiblemente quieras tener subelementos bajo elementos de rango superior. Tomemos la segunda lista de nuestro ejemplo de la receta:</p> + +<pre class="brush: html notranslate"><ol> + <li>Pela el ajo y picarlo en trozos gruesos.</li> + <li>Retira las semillas y el tallo del pimiento, y cortarlo en trozos gruesos.</li> + <li>Mete todos los alimentos en un procesador de alimentos.</li> + <li>Pica todos los ingredientes hasta conseguir una pasta.</li> + <li>Si deseas un hummus "grueso", procésalo corto tiempo.</li> + <li>Pica durante más tiempo si se desea obtener un hummus "suave".</li> +</ol></pre> + +<p>Puesto que los dos últimos elementos están estrechamente relacionados con el elemento anterior (se leen como subinstrucciones u opciones que encajan bajo ese elemento), puede tener sentido anidarlos dentro de su propia lista no ordenada e introducir esa lista bajo el cuarto elemento. Tendría el siguiente aspecto:</p> + +<pre class="brush: html notranslate"><ol> + <li>Pela el ajo y picarlo en trozos gruesos.</li> + <li>Retira las semillas y el tallo del pimiento, y cortarlo en trozos gruesos.</li> + <li>Mete todos los alimentos en un procesador de alimentos.</li> + <li>Procesa todos los ingredientes hasta conseguir una pasta. + <ul> + <li>Si deseas un hummus "grueso", procésalo corto tiempo.</li> + <li>Pica durante más tiempo si se desea obtener un hummus "suave".</li> + </ul> + </li> +</ol></pre> + +<p>Vuelve al ejemplo anterior y reescribe la lista de este modo.</p> + +<h2 id="Énfasis_e_importancia">Énfasis e importancia</h2> + +<p>En el lenguaje humano, a menudo enfatizamos ciertas palabras para alterar el significado de una frase, y a menudo queremos destacar ciertas palabras como importantes o diferentes en algún sentido. HTML nos dota de diversos elementos semánticos que nos permiten destacar contenido textual con tales efectos, y en esta sección veremos los más comunes.</p> + +<h3 id="Énfasis">Énfasis</h3> + +<p>Cuando queremos dar énfasis al lenguaje hablado, <em>acentuamos</em> ciertas palabras y así alteramos sutilmente el significado de lo que decimos. De manera similar, en el lenguaje escrito ponemos palabras en cursiva para destacarlas. Por ejemplo, las dos siguientes frases tienen diferente significado:</p> + +<p>Me alegro de que no llegues tarde.</p> + +<p>Me <em>alegro</em> de que no llegues <em>tarde</em>.</p> + +<p>La primera frase suena aliviada porque la persona no llega tarde. Por el contrario, la segunda suena sarcástica y un tanto pasivo-agresiva, expresa molestia porque la persona ha llegado algo tarde.</p> + +<p>En HTML usamos el elemento {{HTMLElement("em")}} («<em>emphasis</em>») para marcar estos casos. El documento logra entonces transmitir una lectura más interesante y además así lo reconocen los lectores de pantalla, que lo expresan con un diferente tono de voz. El navegador, de manera predeterminada, aplica el estilo de letra itálica, pero no debes utilizar esta etiqueta solamente para establecer el estilo de letra itálica. Para usar ese estilo, debes utilizar únicamente la etiqueta del elemento {{HTMLElement("span")}} y algo de CSS u otra etiqueta con el elemento {{HTMLElement("i")}} (ve abajo).</p> + +<pre class="brush: html notranslate"><p>Me <em>alegro</em> de que no llegues <em>tarde</em>.</p></pre> + +<h3 id="Importancia_fuerte">Importancia fuerte</h3> + +<p>Para enfatizar palabras importantes al hablar solemos acentuarlas, y al escribir lo hacemos en estilo <strong>negrita</strong>. Por ejemplo:</p> + +<p>Este líquido es <strong>altamente tóxico</strong>.</p> + +<p>Cuento contigo. <strong>¡No llegues tarde!</strong></p> + +<p>En HTML usamos el elemento {{HTMLElement("strong")}} (importancia fuerte) para marcar tales expresiones. El documento resulta entonces más útil, y de nuevo los lectores de pantalla reconocen estos elementos y el tono de voz cambia a uno más fuerte. El estilo negrita es el que aplican los navegadores por omisión, pero no debes usar esta etiqueta solamente para aplicar este estilo. Para hacer eso usa el elemento {{HTMLElement("span")}} y CSS, o un elemento {{HTMLElement("b")}} (ve más abajo).</p> + +<pre class="brush: html notranslate"><p>Este líquido es <strong>altamente tóxico</strong>.</p> + +<p>Cuento contigo. <strong>¡No llegues tarde!</strong></p></pre> + +<p>Puedes anidar elementos de énfasis dentro de elementos de importancia y viceversa si lo deseas:</p> + +<pre class="brush: html notranslate"><p>Este líquido es <strong>altamente tóxico</strong> — +si lo bebes, <strong>podrías <em>morir</em></strong>.</p></pre> + +<h3 id="Aprendizaje_activo_¡Seamos_importantes!">Aprendizaje activo: ¡Seamos importantes!</h3> + +<p>En esta sección de aprendizaje activo te proporcionamos un ejemplo editable. Practica un poco añadiendo algo de <em><strong>énfasis</strong></em> e <strong><em>importancia</em></strong> a las palabras que creas que lo necesitan.</p> + +<div class="hidden"> +<h6 id="Código_reproducible_5">Código reproducible</h6> + +<pre class="brush: html notranslate"><h2>Salida en vivo</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Código editable</h2> +<p class="a11y-label">Pulsa Esc para quitar el foco del área de código (Tab inserta un carácter de tabulación).</p> + +<textarea id="code" class="input" style="min-height: 200px; width: 95%"><h1>Aviso importante</h1> +<p>El domingo 9 de enero de 2019, fue vista una pandilla de góticos + robando varios gnomos de jardín de un + centro comercial en el centro de Milwaukee. Todos ellos + vistiendo monos verdes y tontos sombreros, y + al parecer estaban pasando un buen rato. Si alguien + tiene alguna información sobre este incidente, por favor + póngase en contacto con la policía ahora.</p></textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Restablecer"> + <input id="solution" type="button" value="Mostrar solución"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Mostrar solución'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Mostrar solución') { + textarea.value = solutionEntry; + solution.value = 'Ocultar solución'; + } else { + textarea.value = userEntry; + solution.value = 'Mostrar solución'; + } + updateCode(); +}); + +var htmlSolution='<h1>Aviso importante</h1>\n<p>El <strong>domingo 9 de enero de 2019</strong>, fue vista una pandilla de <em>góticos</em> robando <strong>varios <em>gnomos</em> de jardín</strong> de un centro comercial en el centro de <strong>Milwaukee</strong>. Todos ellos vistiendo <em>monos verdes</em> y <em>tontos sombreros</em>, y al parecer estaban pasando un buen rato. Si alguien tiene <strong>alguna</strong> información sobre este incidente, póngase en contacto con la policía <strong>ahora</strong>.</p>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// captura la tecla de tabulación en el área de texto y en su lugar +// hace que se escriba una tabulación en la posición del cursor + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Actualiza el userCode guardado cada vez que el usuario actualiza el código del área de texto + +textarea.onkeyup = function(){ + // Solo queremos guardar el estado cuando se muestra el código de usuario, + // no es la solución, por lo que la solución no se guarda sobre el código del usuario + if(solution.value === 'Mostrar solución') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Código_reproducible_5', 700, 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Cursiva_negrita_subrayado...">Cursiva, negrita, subrayado...</h3> + +<p>Los elementos que hemos comentado hasta ahora tienen asociada una semántica clara. La situación con {{HTMLElement("b")}} (negrita o «<b>bold</b>»), {{HTMLElement("i")}} (cursiva o «<i>italic</i>») y{{HTMLElement("u")}} (subrayado o «<u>underline</u>») es algo más complicada. Surgieron para que las personas pudieran escribir textos en negrita, cursiva o subrayado en un tiempo en el que pocos navegadores o ninguno admitían el CSS. Elementos como estos, que solo afectan a la presentación y no a la semántica, se conocen como <strong>elementos de presentación</strong> y no se deberían usar porque, como hemos visto, la semántica es muy importante para la accesibilidad y el SEO, entre otros aspectos.</p> + +<p>HTML5 redefinió los elementos <code><b></code>, <code><i></code> y <code><u></code> con roles semánticos nuevos un tanto confusos.</p> + +<p>Esta es la regla de oro: el uso de <code><b></code>, <code><i></code> o <code><u></code> resulta adecuado cuando transmiten el significado que suele transmitir el uso tradicional de las negritas, itálicas o el subrayado, si no hay ningún otro elemento que resulte más adecuado. Sin embargo, siempre resulta crítico mantener una actitud orientada a la accesibilidad. El concepto de itálica no es demasiado útil para las personas que usan lectores de pantalla o para las personas que utilizan un sistema de escritura distinto del alfabeto latino.</p> + +<ul> + <li>{{HTMLElement('i')}} se usa para transmitir el significado que tradicionalmente transmite la itálica: extranjerismos, clasificaciones taxonómicas, conceptos técnicos, un pensamiento...</li> + <li>{{HTMLElement('b')}} se usa para transmitir el significado que tradicionalmente transmite la negrita: palabras clave, nombres de productos, frases principales...</li> + <li>{{HTMLElement('u')}} se usa para transmitir el significado que tradicionalmente conlleva el subrayado: nombres propios, errores ortográficos...</li> +</ul> + +<div class="note"> +<p>Una observación prudente acerca del subrayado: <strong>La gente suele asociar estrechamente el subrayado con los hipervínculos.</strong> Por ello en la web es mejor reservar el subrayado para los enlaces. Utiliza el elemento {{HTMLElement('u')}} cuando resulte apropiado semánticamente, pero considera usar CSS para cambiar el subrayado predeterminado por algo más adecuado en la web. El siguiente ejemplo ilustra cómo lo puedes hacer.</p> +</div> + +<pre class="brush: html notranslate"><!-- nombres científicos --> +<p> + El colibrí garganta de rubí (<i>Archilochus colubris</i>) + es el colibrí más común en el este de América del Norte. +</p> + +<!-- extranjerismos --> +<p> + El menú era un mar de palabras exóticas como <i lang="uk-latn">vatrushka</i>, + <i lang="id">nasi goreng</i> y <i lang="fr">soupe à l'oignon</i>. +</p> + +<!-- un error ortográfico reconocido --> +<p> + Algún día aprenderé a <u>deletrear</u> mejor. +</p> + +<!-- Palabras clave destacadas en una serie de instrucciones --> +<ol> + <li> + <b>Corta</b> dos piezas de la hogaza de pan. + </li> + <li> + <b>Inserta</b> una rodaja de tomate y una hoja de + lechuga entre las rebanadas de pan. + </li> +</ol></pre> + +<h2 id="¡Pon_a_prueba_tus_habilidades!">¡Pon a prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo, pero ¿puedes recordar la información más importante? Encontrarás más ejercicios con los que comprobar que has retenido esta información antes de seguir adelante en {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Test_your_skills:_HTML_text_basics", "Pon a prueba tus habilidades: Prueba de conocimientos básicos de HTML")}}.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>¡Eso es todo por ahora! Este artículo debería haberte dado una buena idea de cómo comenzar a marcar texto en HTML y te ha presentado algunos de los elementos más importantes en este ámbito. Hay muchos más elementos semánticos para desarrollar en esta área, y veremos muchos más en nuestro artículo {{web.link("/en-US/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Formateo de texto avanzado")}}, más adelante en el curso. En el siguiente artículo, veremos en detalle cómo {{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "crear hipervínculos")}}, posiblemente el más importante elemento en la web.</p> + +<p>{{PreviousMenuNext("Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Learn/HTML/Introduction_to_HTML")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Getting_started", "Empezar con HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML", "¿Qué hay en el «head»? Metadatos en HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/HTML_text_fundamentals", "Fundamentos de texto HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Creating_hyperlinks", "Crear hipervínculos")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Advanced_text_formatting", "Formateo de texto avanzado")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Document_and_website_structure", "Estructura web y documentación")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Debugging_HTML", "Depurar HTML")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Marking_up_a_letter", "Marcado para una carta")}}</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML/Structuring_a_page_of_content", "Estructuración del contenido de una página")}}</li> +</ul> diff --git a/files/es/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html b/files/es/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html new file mode 100644 index 0000000000..5169cfc976 --- /dev/null +++ b/files/es/learn/html/multimedia_and_embedding/adding_vector_graphics_to_the_web/index.html @@ -0,0 +1,366 @@ +--- +title: Agregar Gráficos Vectoriales a la Web +slug: Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web +tags: + - Aprender + - Guía + - HTML + - Imagenes + - Principiante + - Raster + - SVG + - Vector + - graficos + - iframe + - img +translation_of: Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<div class="summary"> +<p>Los gráficos vectoriales son muy útiles en muchas circunstancias — tienen tamaño de archivo pequeños y son altamente escalables, por lo que no se pixelan cuando se amplían a un tamaño más grande. En este artículo le mostraremos cómo incluir uno en su página web.</p> +</div> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Debe conocer los <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">conceptos básicos de HTML</a> y cómo <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">insertar imágenes en su documento</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a incrustar una imagen SVG (vector) en una página web.</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Nota</strong>: Este artículo no tiene la intención de enseñarte SVG; solo mostrarte qué es, y cómo agregarlo a las páginas web.</p> +</div> + +<h2 id="¿Qué_son_los_gráficos_vectoriales">¿Qué son los gráficos vectoriales?</h2> + +<p>En la web, trabajarás con dos tipos de imágenes — <strong>imágenes rasterizadas</strong>, e <strong>imágenes vectoriales</strong>:</p> + +<ul> + <li><strong>Las imágenes ráster</strong> se definen mediante una cuadrícula de píxeles — un archivo de imagen rasterizado contiene información que muestra exactamente dónde se colocará cada píxel y exactamente de qué color debe ser. Los formatos de ráster web populares incluyen mapa de bits (<code>.bmp</code>), PNG (<code>.png</code>), JPEG (<code>.jpg</code>), and GIF (<code>.gif</code>.)</li> + <li><strong>Las imágenes vectoriales</strong> se definen mediante algoritmos — un archivo de imagen vectorial contiene definiciones de forma y ruta que la computadora puede usar para determinar cómo debería verse la imagen cuando se representa en la pantalla. El formato {{glossary("SVG")}} nos permite crear poderosos gráficos vectoriales para usar en la Web.</li> +</ul> + +<p>Para darte una idea de la diferencia entre los dos, veamos un ejemplo. Puede encontrar este ejemplo en vivo en nuestro repositorio de Github como <a href="https://mdn.github.io/learning-area/html/multimedia-and-embedding/adding-vector-graphics-to-the-web/vector-versus-raster.html">vector-versus-raster.html</a> — muestra dos imágenes aparentemente idénticas una al lado de la otra, de una estrella roja con una sombra negra. La diferencia es que el de la izquierda es un PNG y el de la derecha es una imagen SVG.</p> + +<p>La diferencia se hace evidente cuando amplía la página — la imagen PNG se pixela a medida que se acerca porque contiene información sobre dónde debería estar cada píxel (y de qué color). Cuando se amplía, cada píxel simplemente aumenta de tamaño para llenar varios píxeles en la pantalla, por lo que la imagen comienza a verse borrosa. Sin embargo, la imagen vectorial sigue luciendo agradable y nítida, porque no importa el tamaño que tenga, los algoritmos se utilizan para resolver las formas en la imagen, y los valores simplemente se escalan a medida que aumenta.</p> + +<p><img alt="Two star images" src="https://mdn.mozillademos.org/files/12866/raster-vector-default-size.png" style="display: block; height: 112px; margin: 0px auto; width: 223px;"></p> + +<p><img alt="Two star images zoomed in, one crisp and the other blurry" src="https://mdn.mozillademos.org/files/12868/raster-vector-zoomed.png" style="display: block; height: 328px; margin: 0px auto; width: 677px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Las imágenes de arriba son en realidad todos PNG, con la estrella de la izquierda en cada caso representando una imagen rasterizada y la estrella de la derecha representando una imagen vectorial. Nuevamente, vaya a la demostración de vector-versus-raster.html para ver un ejemplo real.</p> +</div> + +<p>Además, los archivos de imágenes vectoriales son mucho más ligeros que sus equivalentes ráster, porque solo necesitan contener un puñado de algoritmos, en lugar de información sobre cada píxel de la imagen individualmente.</p> + +<h2 id="¿Qué_es_SVG">¿Qué es SVG?</h2> + +<p><a href="/en-US/docs/Web/SVG">SVG</a> es un lenguaje basado en {{glossary("XML")}}-para describir imágenes vectoriales. Básicamente es un marcado, como HTML, excepto que tiene muchos elementos diferentes para definir las formas que desea que aparezcan en su imagen y los efectos que desea aplicar a esas formas. SVG es para marcar gráficos, no contenido. En el extremo más simple del espectro, tienes elementos para crear formas simples, como {{svgelement("circle")}} and {{svgelement("rect")}}. Las funciones SVG más avanzadas incluyen {{svgelement("feColorMatrix")}} (transformar colores usando una matriz de transformación), {{svgelement("animate")}} (animar partes de su gráfico vectorial), and {{svgelement("mask")}} (aplica una máscara sobre la parte superior de tu imagen).</p> + +<p>Como ejemplo simple, el siguiente código crea un círculo y un rectángulo:</p> + +<pre class="brush: html notranslate"><svg version="1.1" + baseProfile="full" + width="300" height="200" + xmlns="http://www.w3.org/2000/svg"> + <rect width="100%" height="100%" fill="black" /> + <circle cx="150" cy="100" r="90" fill="blue" /> +</svg></pre> + +<p>Esto crea la siguiente salida:</p> + +<p>{{ EmbedLiveSample('What_is_SVG', 300, 200, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>En el ejemplo anterior, puede tener la impresión de que SVG es fácil de codificar manualmente. Sí, puede codificar manualmente SVG simple en un editor de texto, pero para una imagen compleja, esto rápidamente comienza a ser muy difícil. Para crear imágenes SVG, la mayoría de la gente usa un editor de gráficos vectoriales como Inkscape o Illustrator. Estos paquetes le permiten crear una variedad de ilustraciones utilizando varias herramientas gráficas y crear aproximaciones de fotos (por ejemplo, la función Trazar mapa de bits de Inkscape).</p> + +<p>SVG tiene algunas ventajas adicionales además de las descritas hasta ahora:</p> + +<ul> + <li>El texto en imágenes vectoriales sigue siendo accesible (lo que también beneficia a su {{glossary("SEO")}}).</li> + <li>Los SVG se prestan bien al estilo / scripting, porque cada componente de la imagen es un elemento que se puede diseñar a través de CSS o scripting a través de JavaScript.</li> +</ul> + +<p>Entonces, ¿por qué alguien querría usar gráficos rasterizados sobre SVG? Bueno, SVG tiene algunas desventajas:</p> + +<ul> + <li>SVG puede complicarse rápidamente, lo que significa que el tamaño de los archivos puede crecer. Además, los SVG complejos también pueden requerir un tiempo de procesamiento significativo en el navegador.</li> + <li>SVG puede ser más difícil de crear que las imágenes rasterizadas, dependiendo del tipo de imagen que intente crear.</li> + <li>SVG no es compatible con navegadores más antiguos, por lo que puede no ser adecuado si necesita admitir versiones anteriores de Internet Explorer con su sitio web (SVG comenzó a ser compatible a partir de IE9).</li> +</ul> + +<p>Los gráficos rasterizados son posiblemente mejores para imágenes de precisión complejas, como fotos, por las razones descritas anteriormente.</p> + +<div class="note"> +<p><strong>Nota</strong>: En Inkscape, guarde sus archivos como SVG simple para ahorrar espacio. Además, consulte este artículo que describe<a href="http://tavmjong.free.fr/INKSCAPE/MANUAL/html/Web-Inkscape.html"> </a><a href="http://tavmjong.free.fr/INKSCAPE/MANUAL/html/Web-Inkscape.html">cómo preparar SVGs para la web</a>.</p> +</div> + +<h2 id="Agregar_SVG_a_sus_páginas">Agregar SVG a sus páginas</h2> + +<p>En esta sección, veremos las diferentes formas en las que puede agregar gráficos vectoriales SVG a sus páginas web.</p> + +<h3 id="La_forma_rápida_htmlelementimg">La forma rápida: {{htmlelement("img")}}</h3> + +<p>Para incrustar un SVG a través de un elemento {{htmlelement ("img")}}, solo necesita hacer referencia a él en el atributo src como es de esperar. Necesitará un atributo de altura o ancho (o ambos si su SVG no tiene una relación de aspecto inherente). Si aún no lo ha hecho, lea <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imágenes en HTML</a>.</p> + +<pre class="brush: html notranslate"><img + src="equilateral.svg" + alt="triangle with all three sides equal" + height="87" + width="100" /></pre> + +<h4 id="Pros">Pros</h4> + +<ul> + <li> + <p>Sintaxis de imagen rápida y familiar con equivalente de texto integrado disponible en el atributo <code>alt</code>.</p> + </li> + <li>Puede convertir la imagen en un hipervínculo fácilmente anidando el <code><img></code> dentro de un elemento {{htmlelement ("a")}}.</li> + <li>El navegador puede almacenar en caché el archivo SVG, lo que da como resultado tiempos de carga más rápidos para cualquier página que utilice la imagen cargada en el futuro.</li> +</ul> + +<h4 id="Cons">Cons</h4> + +<ul> + <li>No puede manipular la imagen con JavaScript.</li> + <li>Si desea controlar el contenido SVG con CSS, debe incluir estilos CSS en línea en su código SVG. (Las hojas de estilo externas invocadas desde el archivo SVG no tienen efecto).</li> + <li>No puede cambiar el estilo de la imagen con pseudoclases CSS (como <code>:focus</code>).</li> +</ul> + +<h3 id="Solución_de_problemas_y_compatibilidad_con_varios_navegadores">Solución de problemas y compatibilidad con varios navegadores</h3> + +<p>Para los navegadores que no admiten SVG (IE 8 y versiones anteriores, Android 2.3 y versiones anteriores), puede hacer referencia a un PNG o JPG de su atributo src y usar un atributo {{htmlattrxref ("srcset", "img")}} ( que solo los navegadores recientes reconocen) para hacer referencia al SVG. Siendo este el caso, solo los navegadores compatibles cargarán el SVG; los navegadores más antiguos cargarán el PNG en su lugar:</p> + +<pre class="brush: html notranslate"><img src="equilateral.png" alt="triangle with equal sides" srcset="equilateral.svg"></pre> + +<p>También puede usar SVG como imágenes de fondo CSS, como se muestra a continuación. En el siguiente código, los navegadores más antiguos se quedarán con el PNG que entienden, mientras que los navegadores más nuevos cargarán el SVG:</p> + +<pre class="brush: css notranslate"><code>background: url("fallback.png") no-repeat center;</code> +<code>background-image: url("image.svg"); +background-size: contain;</code></pre> + +<p>Al igual que el método <code><img></code> descrito anteriormente, la inserción de SVG con imágenes de fondo CSS significa que el SVG no se puede manipular con JavaScript y también está sujeto a las mismas limitaciones de CSS.</p> + +<p>Si sus SVG no se muestran en absoluto, podría deberse a que su servidor no está configurado correctamente. Si ese es el problema, este <a href="/en-US/docs/Web/SVG/Tutorial/Getting_Started#A_Word_on_Webservers">artículo le indicará la dirección correcta</a>.</p> + +<h3 id="Cómo_incluir_código_SVG_dentro_de_su_HTML">Cómo incluir código SVG dentro de su HTML</h3> + +<p>También puede abrir el archivo SVG en un editor de texto, copiar el código SVG y pegarlo en su documento HTML; esto a veces se denomina poner su SVG en línea o SVG en línea. Asegúrese de que su fragmento de código SVG comience y termine con las etiquetas <svg> </svg> (no incluya nada fuera de ellas). Aquí tiene un ejemplo muy simple de lo que puede pegar en su documento:</p> + +<pre class="brush: html notranslate"><svg width="300" height="200"> + <rect width="100%" height="100%" fill="green" /> +</svg> +</pre> + +<h4 id="Pros_2">Pros</h4> + +<ul> + <li>Poner su SVG en línea ahorra una solicitud HTTP y, por lo tanto, puede reducir un poco su tiempo de carga.</li> + <li>Puede asignar clases e identificadores a elementos SVG y aplicarles estilo con CSS, ya sea dentro del SVG o donde quiera que ponga las reglas de estilo CSS para su documento HTML. De hecho, puede utilizar cualquier atributo de presentación SVG como propiedad CSS.</li> + <li>SVG en línea es el único enfoque que le permite usar interacciones CSS (como <code>:focus</code>) y animaciones CSS en su imagen SVG (incluso en su hoja de estilo normal).</li> + <li>Puede convertir el marcado SVG en un hipervínculo envolviéndolo en un elemento {{htmlelement ("a")}}.</li> +</ul> + +<h4 id="Cons_2">Cons</h4> + +<ul> + <li>Este método solo es adecuado si está utilizando SVG en un solo lugar. La duplicación hace que el mantenimiento requiera muchos recursos.</li> + <li>El código SVG adicional aumenta el tamaño de su archivo HTML.</li> + <li>El navegador no puede almacenar en caché SVG en línea, ya que almacenaría en caché activos de imagen normales, por lo que las páginas que incluyen la imagen no se cargarán más rápido después de que se cargue la primera página que contiene la imagen.</li> + <li>Puede incluir respaldo en un elemento {{svgelement ("foreignObject")}}, pero los navegadores que admiten SVG aún descargan las imágenes de respaldo. Debe sopesar si la sobrecarga adicional realmente vale la pena, solo para admitir navegadores obsoletos.</li> +</ul> + +<ul> +</ul> + +<h3 id="Cómo_incrustar_un_SVG_con_un_htmlelementiframe">Cómo incrustar un SVG con un {{htmlelement("iframe")}}</h3> + +<p>Puede abrir imágenes SVG en su navegador al igual que las páginas web. Entonces, incrustar un documento SVG con un <code><iframe></code> se realiza tal como lo estudiamos en <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">De <object> a <iframe> </a><a href="https://wiki.developer.mozilla.org/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">—</a><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies"> otras tecnologías de incrustación</a>.</p> + +<p>Aquí hay una revisión rápida:</p> + +<pre class="brush: html notranslate"><iframe src="triangle.svg" width="500" height="500" sandbox> + <img src="triangle.png" alt="Triangle with three unequal sides" /> +</iframe></pre> + +<p>Este definitivamente no es el mejor método para elegir:</p> + +<h4 id="Cons_3">Cons</h4> + +<ul> + <li>Los <code>iframes</code> tienen un mecanismo de respaldo, como puede ver, pero los navegadores solo muestran el respaldo si carecen por completo de soporte para los iframes.</li> + <li>Además, a menos que el SVG y su página web actual tengan el mismo {{glossary('origin')}}, no puede usar JavaScript en su página web principal para manipular el SVG.</li> +</ul> + +<h2 id="Aprendizaje_activo_jugar_con_SVG">Aprendizaje activo: jugar con SVG</h2> + +<p>En esta sección de aprendizaje activo, nos gustaría que simplemente probaras a jugar con algunos SVG por diversión. En la entrada a continuación, verá que ya le hemos proporcionado algunas muestras para que pueda comenzar. También puedes ir a la <a href="/en-US/docs/Web/SVG/Element">Referencia de Elementos SVG</a>, descubrir más detalles sobre otros juguetes que puedes usar en SVG y probarlos también. Esta sección trata sobre cómo practicar sus habilidades de investigación y divertirse.</p> + +<p>Si se queda atascado y no puede hacer que su código funcione, siempre puede restablecerlo con el <em>botón Restablecer</em>.</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="input" style="width: 95%;min-height: 200px;"> + <svg width="100%" height="100%"> + <rect width="100%" height="100%" fill="red" /> + <circle cx="100%" cy="100%" r="150" fill="blue" stroke="black" /> + <polygon points="120,0 240,225 0,225" fill="green"/> + <text x="50" y="100" font-family="Verdana" font-size="55" + fill="white" stroke="black" stroke-width="2"> + Hello! + </text> + </svg> +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution" disabled> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">const textarea = document.getElementById('code'); +const reset = document.getElementById('reset'); +const solution = document.getElementById('solution'); +const output = document.querySelector('.output'); +let code = textarea.value; +let userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +const htmlSolution = ''; +let solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + const scrollPos = textarea.scrollTop; + const caretPos = textarea.selectionStart; + const front = (textarea.value).substring(0, caretPos); + const back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 500, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Este artículo le ha proporcionado un recorrido rápido por qué son los gráficos vectoriales y SVG, por qué es útil conocerlos y cómo incluir SVG en sus páginas web. Nunca tuvo la intención de ser una guía completa para aprender SVG, solo un indicador para que sepa qué es SVG si lo encuentra en sus viajes por la Web. Así que no se preocupe si todavía no siente que es un experto en SVG. Hemos incluido algunos enlaces a continuación que pueden ayudarlo si desea ir y obtener más información sobre cómo funciona.</p> + +<p>En el próximo artículo de este módulo, exploraremos las imágenes adaptables en detalle, observando las herramientas que tiene HTML para permitirle hacer que sus imágenes funcionen mejor en diferentes dispositivos.</p> + +<h2 id="Vea_también">Vea también</h2> + +<ul> + <li><a href="/en-US/docs/Web/SVG/Tutorial/Getting_Started">Tutorial de SVG</a> en MDN</li> + <li><a href="http://thenewcode.com/744/Making-SVG-Responsive">Consejos rápidos para SVGs adaptables</a></li> + <li><a href="https://tympanus.net/codrops/2014/08/19/making-svgs-responsive-with-css/">Tutorial de Sara Soueidan sobre imágenes SVG adaptables</a></li> + <li><a href="https://www.w3.org/TR/SVG-access/">Beneficios de accesibilidad de SVG</a></li> + <li><a href="https://css-tricks.com/scale-svg/">Cómo escalar SVGs</a> (¡no es tan simple como los gráficos rasterizados!)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imágenes en HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Contenido de Audio y Video</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">De <object> a <iframe> - otras tecnologías de incrustación</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Agregar gráficos vectoriales a la web</a></li> + <li><a href="/es/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Imágenes adaptables</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Página de presentación de Mozilla</a></li> +</ul> diff --git a/files/es/learn/html/multimedia_and_embedding/images_in_html/index.html b/files/es/learn/html/multimedia_and_embedding/images_in_html/index.html new file mode 100644 index 0000000000..22734a9b24 --- /dev/null +++ b/files/es/learn/html/multimedia_and_embedding/images_in_html/index.html @@ -0,0 +1,510 @@ +--- +title: Imágenes en HTML +slug: Learn/HTML/Multimedia_and_embedding/Images_in_HTML +tags: + - Aprendiz + - Article + - HTML + - Imagenes + - captions + - figcaption + - img + - pie de imagen + - subtítulos + - texto alt +translation_of: Learn/HTML/Multimedia_and_embedding/Images_in_HTML +--- +<div> +<p>{{LearnSidebar}}</p> + +<p>{{NextMenu("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding")}}</p> +</div> + +<p class="summary">Al principio, la web solo era texto y resultaba más bien aburrido. Afortunadamente, no pasó mucho tiempo antes de que se añadiera la capacidad de insertar imágenes (y otros tipos de contenido más interesantes) en las páginas web. Hay otros tipos de elementos multimedia que tener en cuenta, pero es lógico comenzar con el humilde elemento {{htmlelement("img")}} utilizado para insertar una imagen simple en una página web. En este artículo, veremos en detalle cómo usar este elemento, incluidos sus conceptos básicos y cómo añadir pies de imagen usando {{htmlelement("figure")}} y explicaremos cómo se relaciona con las imágenes de fondo en <a class="glossaryLink" href="/en-US/docs/Glossary/CSS" title="CSS: CSS (Cascading Style Sheets) is a declarative language that controls how webpages look in the browser.">CSS</a>.</p> + +<figure> +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, tener el <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de cómo <a href="https://developer.mozilla.org/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">trabajar con archivos</a>, estar familiarizado con los principios básicos de HTML (como se describe en <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/iniciar">Empezar con el HTML</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender cómo insertar imágenes simples en HTML y añadirles pies de imagen, y cómo se relacionan las imágenes HTML con las imágenes de fondo de CSS.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Cómo_ponemos_una_imagen_en_una_página_web">¿Cómo ponemos una imagen en una página web?</h2> + +<p>Para poner una imagen simple en una página web, utilizamos el elemento {{htmlelement("img")}}. Se trata de un elemento vacío (lo que significa que no contiene texto o etiqueta de cierre) que requiere de por lo menos de un atributo para ser utilizado: <code>src</code> (a veces denominado por su nombre completo, <em>source</em>). El atributo <code>src</code> contiene una ruta que apunta a la imagen que quieres poner en la página, que puede ser una URL relativa o absoluta, de la misma forma que el elemento {{htmlelement("a")}} contiene los valores del atributo <code>href</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Deberías leer <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/Creating_hyperlinks#Un_primer_acercamiento_a_URL_y_referencias">Inicio rápido a las URL y rutas</a> para refrescar tu memoria sobre URL relativas y absolutas antes de continuar.</p> +</div> + +<p>Por ejemplo, si tu imagen se llama <code>dinosaur.jpg</code>, y está en el mismo directorio que tu página HTML, deberás incrustar la imagen de la siguiente manera:</p> + +<pre class="brush: html notranslate"><img src="dinosaur.jpg"></pre> + +<p>Si la imagen estaba en el subdirectorio <code>images</code>, que estaba en el mismo directorio que la página HTML (lo que Google recomienda con fines de indización y posicionamiento en buscadores {{glossary("SEO")}}), entonces deberías incrustar la imagen así:</p> + +<pre class="brush: html notranslate"><img src="images/dinosaur.jpg"></pre> + +<p>y así sucesivamente.</p> + +<div class="note"> +<p><strong>Nota</strong>: Los motores de búsqueda también leen los nombres de archivo de imagen y esto cuenta para el SEO. Por lo tanto, dale a tu imagen un nombre descriptivo; <code>dinosaur.jpg</code> es mejor que <code>img835.png</code>.</p> +</div> + +<p>Puedes incrustar la imagen usando la URL absoluta, por ejemplo:</p> + +<pre class="brush: html notranslate"><img src="https://www.example.com/images/dinosaur.jpg"></pre> + +<p>Pero esto no tiene sentido, solo hace que el navegador trabaje más buscando la dirección IP desde el servidor DNS cada vez, etc. Casi siempre mantendrás las imágenes para tu sitio web en el mismo servidor de tu HTML.</p> + +<div class="warning"> +<p><strong>Advertencia:</strong> La mayoría de imágenes tienen derechos de autor. <strong>No</strong> muestres una imagen en tu página web a menos que:<br> + <br> + 1) seas dueño de la imagen,<br> + 2) tengas permiso escrito explícito del dueño de la imagen o <br> + 3) tengas suficientes pruebas de que la imagen es de dominio público.<br> + <br> + El incumplimiento de las normas de los derechos de autor es un acto ilegal y poco ético. Por lo tanto, no apuntes <strong>nunca</strong> tu atributo <code>src</code> a una imagen que esté alojada en un sitio web si no tienes el permiso para hacerlo. Esto se llama <em>hotlinking</em>. Asimismo es ilegal robar el ancho de banda de alguien. Además, ralentiza tu página y te deja sin control sobre la imagen si la eliminan o reemplazan por otra que incluso podría resultar embarazosa.</p> +</div> + +<p>Nuestro código anterior debería darnos el resultado siguiente:</p> + +<p><img alt="A basic image of a dinosaur, embedded in a browser, with Images in HTML written above it" src="https://mdn.mozillademos.org/files/12700/basic-image.png" style="display: block; height: 700px; margin: 0px auto; width: 700px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Los elementos como {{htmlelement("img")}} y {{htmlelement("video")}} a veces se denominan <strong>elementos reemplazados</strong>. Esto se debe a que el tamaño y el contenido del elemento se especifican en un recurso externo (como un archivo de imagen o video), no en el contenido del elemento en sí.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar el ejemplo terminado de esta sección <a href="https://mdn.github.io/learning-area/html/multimedia-and-embedding/images-in-html/index.html">en Github</a> (consulta también el <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/images-in-html/index.html">código fuente</a>).</p> +</div> + +<h3 id="Texto_alternativo">Texto alternativo</h3> + +<p>El próximo atributo que veremos es <code>alt</code>. Su valor debe ser una descripción textual de la imagen para usarla en situaciones en que la imagen no puede ser vista/mostrada o tarde demasiado en mostrarse por una conexión lenta a internet. Por ejemplo, nuestro código anterior podría modificarse así:</p> + +<pre class="brush: html notranslate"><img src="images/dinosaur.jpg" + alt="La cabeza y el torso de un esqueleto de dinosaurio; + tiene una cabeza grande con dientes largos y afilados"></pre> + +<p>La forma más fácil de probar el texto <code>alt</code> es escribir mal el nombre de archivo. Si, por ejemplo, escribimos el nombre archivo de nuestra imagen como <code>dinosooooor.jpg</code>, el navegador no podrá mostrar la imagen, en su lugar mostrará el texto alternativo:</p> + +<p><img alt="The Images in HTML title, but this time the dinosaur image is not displayed, and alt text is in its place." src="https://mdn.mozillademos.org/files/12702/alt-text.png" style="display: block; height: 700px; margin: 0px auto; width: 700px;"></p> + +<p>¿Por qué vas a ver o necesitar el texto alternativo? Puede ser por varias razones:</p> + +<ul> + <li>El usuario tiene alguna discapacidad visual y utiliza un <a href="https://es.wikipedia.org/wiki/Lector_de_pantalla">lector de pantalla</a> para leer el contenido de la web. De hecho, disponer de texto alternativo para describir las imágenes es útil para la mayoría de los usuarios.</li> + <li><span id="result_box" lang="es"><span>Como ya hemos dicho anteriormente, es posible que se haya escrito mal el nombre del archivo o su ruta</span></span>.</li> + <li>El navegador no admite el tipo de imagen. Algunas personas aún usan navegadores de solo texto, como <a href="https://es.wikipedia.org/wiki/Lynx_(navegador)">Lynx</a>, que muestran el texto del atributo <em>alt</em>.</li> + <li>Quieres que los motores de búsqueda puedan utilizar este texto. Por ejemplo, los motores de búsqueda pueden hacer coincidir el texto alternativo con la consulta de búsqueda.</li> + <li>Los usuarios han desactivado las imágenes para reducir el volumen de transferencia de datos y de distracciones. Esto sucede especialmente en teléfonos móviles y en países en que el ancho de banda es limitado y caro.</li> +</ul> + +<p>¿Qué hay que escribir exactamente en el atributo <code>alt</code>? Esto depende en primer lugar de <em>por qué</em> la imagen está en ese lugar. En otras palabras, qué se pierde si la imagen no aparece:</p> + +<ul> + <li><strong>Decoración. </strong>Para las imágenes decorativas deberían utilizarse {{anch("imágenes de fondo CSS")}}. Pero si es inevitable usar HTML, la mejor forma de hacerlo es con <code>alt=""</code>. Si la imagen no es parte del contenido, el lector de pantalla no debería malgastar el tiempo en leerla.</li> + <li><strong>Contenido. </strong>Si tu imagen proporciona información significativa, proporciona la misma información en un<em> </em>texto alternativo (<code>alt</code>) breve. O mejor aún, en el texto principal que todos pueden ver. No escribas texto alternativo redundante. ¿Acaso no resultaría molesto para un usuario con visión ordinaria si todos los párrafos se escribieran dos veces en el contenido principal? Si la imagen se describe en el cuerpo principal del texto de modo adecuado, puedes simplemente usar <code>alt=""</code>.</li> + <li><strong>Enlace.</strong> Al poner una imagen dentro de una etiqueta <code><a></code> para convertirla en un enlace, aun debes proporcionar <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/Creating_hyperlinks#Claridad_en_las_palabras">texto de enlace accesible</a>. En tal caso podrías escribirlo dentro del mismo elemento <code><a></code>, o dentro del atributo <code>alt</code> de la imagen. Lo que mejor funcione en tu caso.</li> + <li><strong>Texto.</strong> No deberías poner tu texto en imágenes. Si tu título de encabezado principal necesita, por ejemplo, un sombreado paralelo, <a href="/es/docs/Web/CSS/text-shadow">usa CSS</a> para ello en vez de poner el texto en una imagen. Pero, <em>si realmente no puedes evitarlo</em>, deberías proporcionar el texto en el atributo <code>alt</code>.</li> +</ul> + +<p>En el fondo, la clave es ofrecer una experiencia usable, incluso cuando las imágenes no puedan verse. Esto asegura que ningún usuario pierda ninguna parte del contenido. Desactiva las imágenes en tu navegador y observa cómo se ven las cosas. Te darás cuenta de lo útil que resulta el texto alternativo cuando no es posible ver la imagen.</p> + +<div class="note"> +<p><strong>Nota</strong>: Consulta nuestra guía de <a href="/es/docs/Learn/Accessibility/HTML#Alternativas_de_texto">texto alternativo</a> para obtener más información.</p> +</div> + +<h3 id="Anchura_y_altura">Anchura y altura</h3> + +<p>Puedes usar los atributos ancho (<code>width</code>) y alto (<code>height</code>) para especificar la anchura y altura de tu imagen. Puedes encontrar el ancho y el alto de tu imagen de diversas maneras. Por ejemplo, en Mac puedes usar <kbd>Cmd</kbd> + <kbd>I</kbd> para mostrar información del archivo de imagen. Volviendo a nuestro ejemplo, podríamos hacer esto:</p> + +<pre class="brush: html notranslate"><img src="images/dinosaur.jpg" + alt="La cabeza y el torso de un esqueleto de dinosaurio; + tiene una cabeza grande con dientes largos y afilados" + width="400" + height="341"></pre> + +<p>Esto no proporciona una gran diferencia en la pantalla en circunstancias normales. Pero si la imagen no se muestra, por ejemplo, porque el usuario acaba de acceder a la página y esta aún no se ha cargado, observarás que el navegador reserva un espacio para la imagen:</p> + +<p><img alt="The Images in HTML title, with dinosaur alt text, displayed inside a large box that results from width and height settings" src="https://mdn.mozillademos.org/files/12706/alt-text-with-width-height.png" style="display: block; height: 700px; margin: 0px auto; width: 700px;"></p> + +<p>Hacerlo así es bueno porque la página se carga con mayor rapidez y fluidez.</p> + +<p>Sin embargo, no deberías alterar el tamaño de tus imágenes utilizando atributos HTML. Las imágenes podrían verse granulosas y borrosas si estableces un tamaño demasiado grande; o bien demasiado pequeñas, y se desperdiciaría ancho de banda descargando una imagen que no se ajusta a las necesidades del usuario. La imagen también podría quedar distorsionada, si no mantienes la <a href="https://es.wikipedia.org/wiki/Relaci%C3%B3n_de_aspecto">proporción de aspecto</a> correcta. Deberías utilizar un editor de imágenes, para dar a tu imagen el tamaño adecuado, antes de colocarla en tu página web.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si tienes que alterar el tamaño de una imagen es mejor usar <a href="/es/docs/Learn/CSS">CSS</a>.</p> +</div> + +<h3 id="Título_de_imágenes">Título de imágenes</h3> + +<p>Al igual que con los enlaces, también puedes añadir atributos <code>title</code> a las imágenes para proporcionar más información de ayuda si es necesario. En nuestro ejemplo, podríamos hacer esto:</p> + +<pre class="brush: html notranslate"><img src="images/dinosaur.jpg" + alt="La cabeza y el torso de un esqueleto de dinosaurio; + tiene una cabeza grande con dientes largos y afilados" + width="400" + height="341" + title="Exposición de un T-Rex en el museo de la Universidad de Manchester."></pre> + +<p>Esto nos da una etiqueta de ayuda (<code>tooltip</code>) como las de los enlaces:</p> + +<p><img alt="The dinosaur image, with a tooltip title on top of it that reads A T-Rex on display at the Manchester University Museum " src="https://mdn.mozillademos.org/files/12708/image-with-title.png" style="display: block; height: 341px; margin: 0px auto; width: 400px;"></p> + +<p>Sin embargo, no se recomienda incluir esta propiedad en las imágenes. <code>title</code> presenta algunos problemas de accesibilidad, principalmente porque los lectores de pantalla (<em>screen readers</em>) tienen un comportamiento imprevisible y la mayoría de navegadores no la mostrarán a menos que pases el ratón por encima de la imagen (y por tanto es inútil para quien usa teclado). Si estás interesado en esta cuestión, puedes leer el artículo <a class="external" href="https://www.24a11y.com/2017/the-trials-and-tribulations-of-the-title-attribute/" rel="noopener">The Trials and Tribulations of the Title Attribute</a> de Scott O’Hara.</p> + +<p>Lo mejor es incluir dicha información en el texto principal del artículo, en lugar de adjuntarla en la imagen.</p> + +<h3 id="Aprendizaje_activo_incrustar_imágenes">Aprendizaje activo: incrustar imágenes</h3> + +<p>¡Ahora te toca jugar a ti! Esta sección de aprendizaje activo te mantendrá activo con un ejercicio sencillo de incrustado. Te proporcionamos una etiqueta básica {{htmlelement ("img")}} y nos gustaría que incrustes la imagen ubicada en la URL siguiente:</p> + +<p>https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg</p> + +<p>Ya hemos dicho que nunca se apuntará a imágenes de otros servidores (hotlink), pero esto es solo con fines de aprendizaje, por lo que te lo vamos a dejar hacer por esta vez.</p> + +<p>También nos gustaría que hagas lo siguiente:</p> + +<ul> + <li>Añadir un texto alternativo y comprobar que funciona si escribes mal la URL de la imagen.</li> + <li>Establecer las propiedades <code>width</code> y <code>height</code> correctas de la imagen (pista: tiene 200px de ancho y 171px de alto), luego experimentar con otros valores para ver cuál es el efecto.</li> + <li>Establecer un elemento <code>title</code> en la imagen.</li> +</ul> + +<p>Si te equivocas, puedes volver a empezar pulsando el botón <em>Reiniciar</em>. Si te encallas, pulsa el botón <em>Mostrar la solución</em> para ver la solución:</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="input" style="min-height: 100px; width: 95%"> +<img> +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var htmlSolution = '<img src="https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg"\n alt="The head and torso of a dinosaur skeleton; it has a large head with long sharp teeth"\n width="200"\n height="171"\n title="A T-Rex on display in the Manchester University Museum">'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 350, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Comentar_imágenes_con_figure_y_figcaption">Comentar imágenes con <code>figure</code> y <code>figcaption</code></h2> + +<p>Hay varias formas en que puedes añadir un pie a tu imagen. Por ejemplo, nada te impediría hacer esto:</p> + +<pre class="brush: html notranslate"><div class="figure"> + <img src="images/dinosaur.jpg" + alt="La cabeza y el torso de un esqueleto de dinosaurio; + tiene una cabeza grande con dientes largos y afilados" + width="400" + height="341"> + + <p>Exposición de un T-Rex en el museo de la Universidad de Manchester.</p> +</div></pre> + +<p>Esto está bien. Incluye el contenido que se necesita y es muy personalizable con CSS. Pero hay un problema: no hay nada que vincule semánticamente la imagen con su título, lo que puede causar problemas a los lectores de pantalla. Por ejemplo, cuando hay 50 imágenes y leyendas, ¿qué leyenda se corresponde con cada imagen?</p> + +<p>Una solución mejor es utilizar los elementos HTML5 {{htmlelement("figure")}} y {{htmlelement("figcaption")}}. Estos se crearon exactamente para este propósito: proporcionar un contenedor semántico para las figuras y vincular claramente la figura con el pie. Nuestro ejemplo anterior, podría reescribirse así:</p> + +<pre class="notranslate"><figure> + <img src="images/dinosaur.jpg" + alt="La cabeza y el torso de un esqueleto de dinosaurio; + tiene una cabeza grande con dientes largos y afilados" width="400" + height="341"> + + <figcaption>Exposición de un T-Rex en el museo de la Universidad de Manchester.</figcaption> +</figure></pre> + +<p>El elemento {{htmlelement("figcaption")}} dice al navegador, o a alguna tecnología de apoyo, que el texto que contiene describe la imagen que está contenida en el elemento {{htmlelement("figure")}}.</p> + +<div class="note"> +<p><strong>Nota</strong>: Desde el punto de vista de la accesibilidad, los pies de imagen y el texto alternativo {{htmlattrxref('alt','img')}} cumplen funciones diferentes. Los pies de imagen benefician incluso a quien puede ver la imagen, mientras que el texto {{htmlattrxref('alt','img')}} proporciona la misma función en una imagen ausente. Por tanto, los subtítulos y el texto <code>alt</code> no deberían decir lo mismo, porque ambos aparecen si la imagen no se muestra. Desactiva las imágenes en tu navegador y observa el resultado.</p> +</div> + +<p>El elemento <em>figure</em> no ha de contener una imagen necesariamente. Es una unidad de contenido independiente que:</p> + +<ul> + <li>Expresa un significado en una forma compacta y fácil de entender.</li> + <li>Se puede poner en varios sitios en el flujo lineal de la página.</li> + <li>Proporciona información esencial que da apoyo al texto principal.</li> +</ul> + +<p>Un elemento <em>figure</em> podría contener varias imágenes, un trozo de código, audio, video, ecuaciones, una tabla, o cualquier otra cosa.</p> + +<h3 id="Aprendizaje_activo_crear_un_elemento_figure">Aprendizaje activo: crear un elemento figure</h3> + +<p>En esta sección de aprendizaje activo, te pedimos que tomes el código finalizado de la sección de aprendizaje activo anterior y lo conviertas en un elemento <em>figure</em>:</p> + +<ul> + <li>Delimítalo todo en un elemento {{htmlelement("figure")}}.</li> + <li>Copia el texto del atributo <code>title</code>, elimina el atributo <code>title</code>, y pon el texto dentro de un elemento {{htmlelement("figcaption")}} bajo la imagen.</li> +</ul> + +<p>Si te equivocas, siempre puedes volver a empezar pulsando el botón <em>Reiniciar</em>. Si te quedas atascado, presiona el botón <em>Ver solución</em> para ver la respuesta:</p> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> + +<div class="output" style="min-height: 50px;"> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="input" style="min-height: 100px; width: 95%"> +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var htmlSolution = '<figure>\n <img src="https://raw.githubusercontent.com/mdn/learning-area/master/html/multimedia-and-embedding/images-in-html/dinosaur_small.jpg"\n alt="The head and torso of a dinosaur skeleton; it has a large head with long sharp teeth"\n width="200"\n height="171">\n <figcaption>A T-Rex on display in the Manchester University Museum</figcaption>\n</figure>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', 700, 350, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Imágenes_de_fondo_CSS">Imágenes de fondo CSS</h2> + +<p>También puedes usar CSS para insertar imágenes en páginas web (y JavaScript, pero eso ya es otra historia). La propiedad CSS {{cssxref("background-image")}} y las demás propiedades <code>background-*</code> se usan para controlar la colocación de la imagen de fondo. Por ejemplo, para poner una imagen de fondo en cada párrafo de una página, podríamos hacer esto:</p> + +<pre class="brush: css notranslate">p { + background-image: url("images/dinosaur.jpg"); +}</pre> + +<p>La imagen resultante, podría decirse que es más fácil de posicionar y controlar que una imagen HTML. Entonces ¿para qué molestarse usando imágenes HTML? Como se sugiere arriba, las imágenes de fondo CSS son solo para decoración. Si tan solo quieres añadir algo bonito para mejorar visualmente tu página, están bien. Sin embargo, no tienen ningún significado semántico. No pueden tener su equivalente en texto, son invisibles a los lectores de pantalla, etc. ¡Es entonces cuando las imágenes HTML triunfan!</p> + +<p>En resumen: si una imagen tiene significado en términos del contenido de tu página, entonces deberías usar una imagen HTML. Si la imagen es puramente decorativa, deberías usar imágenes de fondo CSS.</p> + +<div class="note"> +<p><strong>Nota</strong>: Aprenderás mucho más sobre las <a href="/es/docs/Learn/CSS/Building_blocks/Fondos_y_bordes">imágenes de fondo CSS</a> en nuestro apartado <a href="/en-US/docs/Learn/CSS">CSS</a>.</p> +</div> + +<p>Esto es todo por ahora. Hemos expuesto en detalle los conceptos relativos a imágenes y subtítulos de imagen. En el próximo artículo, subiremos un nivel para insertar vídeo y audio en páginas web con HTML.</p> + +<p>{{NextMenu("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imágenes en HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Contenido de video y audio</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">De <object> a <iframe>: otras tecnologías de incrustación</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Añadir gráficos vectoriales a la web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Imágenes <em>responsive</em> (adaptativas)</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Página de bienvenida de Mozilla</a></li> +</ul> +</figure> diff --git a/files/es/learn/html/multimedia_and_embedding/index.html b/files/es/learn/html/multimedia_and_embedding/index.html new file mode 100644 index 0000000000..5e0ffe97a8 --- /dev/null +++ b/files/es/learn/html/multimedia_and_embedding/index.html @@ -0,0 +1,73 @@ +--- +title: Multimedia e inserción +slug: Learn/HTML/Multimedia_and_embedding +tags: + - Aprender + - Audio + - Codificación de Secuencia de comandos + - Evaluación + - Flash + - Gráficos vectoriales + - Guía + - HTML + - Imagenes + - Inserción + - Landing + - Mapa de Imágenes + - Multimedia + - Principiante + - SVG + - Video + - Web + - iframes + - img + - receptivo +translation_of: Learn/HTML/Multimedia_and_embedding +--- +<p class="summary">Hemos visto mucho texto hasta ahora en este curso, pero la web sería realmente aburrida solo usando textos. ¡Comencemos observando como hacer que la web cobre vida, con mucho más contenido interesante! Este módulo te acompañará a explorar maneras de usar HTML para incluir multimedia a tus páginas web, y las diferentes formas en la que podrás hacerlo, incluyendo como enlazar videos, audios e incluso otras páginas webs.</p> + +<h2 id="Requisitos_previos">Requisitos previos</h2> + +<p>Antes de empezar con este módulo, deberías tener un buen conocimiento de las bases de HTML, enseñadas en <a href=" /es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>. Si no has estado trabajando en este módulo (o alguno similar), ¡hazlo y luego vuelve!</p> + +<div class="note"> +<p><strong>Nota</strong>: Si estas trabajando en un ordenador/tablet/u otro dispositivo donde no puedas crear tus propios archivos, puedes probar (la mayoría de ellos) los ejemplos de código en programas online de codificado como <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Glitch</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<p>Este módulo contiene los siguientes artículos que te enseñarán todo lo fundamental sobre introducir multimedia en páginas web.</p> + +<dl> + <dt><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imágenes en HTML</a></dt> + <dd>Hay otros tipos de multimedia a considerar, pero es logico empezar con el humilde elemento {{htmlelement("img")}}, usado para incorporar una imagen simple en una página web. En este artículo veremos cúmo usarlo en profundidad, incluyendo los conceptos básicos, y contenido independiente con título usando {{htmlelement("figure")}}, y cómo relacionarlos con las imágenes de fondo de CSS.</dd> + <dt><a href=" /en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Contenido de Audio y Video</a></dt> + <dd>A continuación, veremos como usar los elementos de HTML5 {{htmlelement("video")}} y {{htmlelement("audio")}}, para insertar video y audio en nuestras páginas, incluyendo conceptos básicos, proporcionando acceso a diferentes formatos de archivo para diferentes navegadores, agregando ilustraciones y subtítulos y cómo resolver inconvenientes en navegadores más antiguos.</dd> + <dt><a href=" /en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">De <object> a <iframe> - otras tecnologías de inserción</a></dt> + <dd>En este punto, nos gustaría dar un paso hacia un lado, mirando algunos de los elementos que te permiten insertar una amplia variedad de tipos de contenido en tus páginas web: los elementos {{htmlelement("iframe")}}, {{htmlelement("embed")}} y {{htmlelement("object")}}.<br> + El elemento <iframe> nos permite incluir otras páginas web, y las otras dos permiten insertar archivos de formato PDF, SVG e incluso Flash -una tecnología que está a punto de desaparecer, pero que todavía puede verse de manera semi-regular-.</dd> + <dt><a href=" /en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Añadiendo graficos vectoriales a la Web </a></dt> + <dd>Los gráficos vectoriales pueden ser muy útiles en ciertas situaciones. A diferencia de los formatos normales como PNG / JPG, estos no se distorsionan/pixelizan cuando se los amplían -pueden permanecer suaves cuando se escalan-. Este artículo te introduce al concepto de gráficos vectoriales y cómo incluir el popular formato {{glossary ("SVG")}} en páginas web.</dd> + <dt><a href=" /en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Imagenes receptivas</a></dt> + <dd>En este artìculo, aprenderás acerca del concepto de imágenes receptivas -imágenes que pueden adaptarse en dispositivos con grandes diferencias de tamaños de pantalla, resoluciones y otras características-. Esto te ayudará a mejorar el rendimiento en diferentes dispositivos. Las imágenes receptivas son sólo una parte del diseño receptivo, un tópico que a futuro aprenderás en CSS.</dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<p>Las siguientes evaluaciones pondrán a prueba tu comprensión de los conceptos básicos de HTML vistos en las guías anteriores.</p> + +<dl> + <dt><a href=" /en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Página de bienvenida de Mozilla</a></dt> + <dd>En esta evaluación, probaremos tu conocimiento de algunas de las técnicas observadas en los artículos de este módulo, ¡lo que te permitirá agregar algunas imágenes y videos a una página original de Mozilla!</dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<dl> + <dt><a href=" /en-US/docs/Learn/HTML/Howto/Add_a_hit_map_on_top_of_an_image">Agregar un mapa de visitas en la parte superior de una imagen</a></dt> + <dd>Los mapas de imágenes proporcionan un mecanismo para hacer diferentes partes de un enlace de imagen a diferentes lugares (piense en un mapa, vinculándolo a más información sobre cada país diferente al que haga clic). Esta técnica a veces puede ser útil.</dd> + <dt><a href="https://learning.mozilla.org/en-US/activities/web-lit-basics-two/">Conceptos básicos de escritura web 2</a></dt> + <dd> + <p>Un excelente curso básico de la fundación Mozilla que explora y prueba algunas de las habilidades mencionadas en el módulo Multimedia e inclusión. Sumérgete en los aspectos básicos de la composición de páginas web, diseño de accesibilidad, uso compartido de recursos, uso de medios en línea y trabajo abierto (significa que tu contenido es libre de compartirse con otros).</p> + </dd> +</dl> diff --git a/files/es/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html b/files/es/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html new file mode 100644 index 0000000000..662d565e31 --- /dev/null +++ b/files/es/learn/html/multimedia_and_embedding/mozilla_splash_page/index.html @@ -0,0 +1,138 @@ +--- +title: Página de bienvenida de Mozilla +slug: Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page +tags: + - Codificación de Secuencia de comandos + - CodingScripting + - Evaluación + - HTML + - Imagenes + - Inserción + - JPEG + - Medidas + - Multimedia + - PNG + - Principiante + - Video + - iframe + - img + - receptivo + - src + - srcset +translation_of: Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<p class="summary">En esta evaluación, pondremos a prueba tu conocimiento de algunas de las técnicas mostradas en los artículos de este módulo, ¡para que tú agregues algunas imágenes y videos a una página de bienvenida de Mozzilla!.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Antes de intentar esta evaluación, ya deberías conocer el módulo de <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding">Multimedia e inserción</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Prueba cuánto sabes de la incorporación de imágenes y videos en páginas web, marcos y técnicas de imagen receptiva a HTML.</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Para comenzar esta evaluación, necesitas el HTML y todas las imágenes de <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/mdn-splash-page-start/">mdn-splash-page-start</a> que tienes en la carpeta de GitHub. Guarda el contenido de <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/mdn-splash-page-start/index.html">index.html</a> en un archivo llamado <code>index.html</code> en tu disco local, en una nueva carpeta. Guarda <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/mdn-splash-page-start/pattern.png">pattern.png</a> en la misma carpeta (haciendo click derecho en la imagen y seleccionando la opción guardar).</p> + +<p>Accede a las diferentes imágenes en la carpeta de <a href="https://github.com/mdn/learning-area/tree/master/html/multimedia-and-embedding/mdn-splash-page-start/originals">originals</a> y guárdalas también de la misma manera. De momento puedes guardarlas en una carpeta diferente, ya que podrías necesitar modificarlas usando un editor de gráficos antes de que estén listas para usarlas.</p> + +<p>También puedes usar una herramienta en línea como <a href="https://glitch.com/">Glitch</a> para crear tu ejemplo. Esto puede ser útil si quieres evaluarlo o pedir ayuda — consulta la sección {{anch("Assessment or further help")}} al final de esta página.</p> + +<div class="note"> +<p><strong>Nota</strong>: El archivo HTML de ejemplo contiene bastante CSS para dar estilo a la página. No necesitas tocar el CSS, solo el HTML dentro del elemento {{htmlelement("body")}}, mientras que insertes el marcado correctamente, el estilo se mantendrá.</p> +</div> + +<h2 id="Resumen_del_proyecto">Resumen del proyecto</h2> + +<p>En esta evaluación, te presentamos una página de bienvenida de Mozzilla en su mayoría terminada, que tiene como objetivo decir algo agradable e interesante sobre lo que significa Mozilla, y proporcionar algunos enlaces a recursos adicionales. Desafortunadamente, aún no se han agregado imágenes o videos, ¡este es tu trabajo!. Debes añadir algunos elementos para que la página se vea bien y tenga sentido. Las siguientes subsecciones detallan lo que tienes que hacer:</p> + +<h3 id="Preparar_las_imágenes">Preparar las imágenes</h3> + +<p>Usa tu editor de imágenes favorito, y utiliza medidas de 400px de ancho y 120px de alto para:</p> + +<ul> + <li><code>firefox_logo-only_RGB.png</code></li> + <li><code>firefox-addons.jpg</code></li> + <li><code>mozilla-dinosaur-head.png</code></li> +</ul> + +<p>Nómbralas por ejemplo, <code>firefoxlogo400.png</code> y <code>firefoxlogo120.png</code>.</p> + +<p>Junto con <code>mdn.svg</code>, estas imágenes serán tus iconos para vincular a otros recursos, dentro del área <code>further-info</code>. Debes vincular al logo de Firefox en el encabezado del sitio. Guarda copias de todos estos dentro de la misma carpeta que <code>index.html</code>.</p> + +<p>A continuación, crea una versión horizontal de 1200px de <code>red-panda.jpg</code>, y una versión vertical de 600px que muestre al panda en una toma de primer plano. Una vez más, ponle un nombre para que puedas identificarlos fácilmente. Guarda una copia de ambos en la misma carpeta que <code>index.html</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Debes optimizar las imágenes JPG y PNG para que sean lo más pequeñas posible, viéndose bien. <a href="https://tinypng.com/">tinypng.com</a> es un gran servicio para hacerlo fácilmente.</p> +</div> + +<h3 id="Añadir_logo_al_encabezado">Añadir logo al encabezado</h3> + +<p>El elemento {{htmlelement("header")}}, añade el elemento {{htmlelement("img")}} que insertará la versión pequeña del logotipo de Firefox al encabezado.</p> + +<h3 id="Añadir_un_video_al_contenido_del_artículo_principal">Añadir un video al contenido del artículo principal</h3> + +<p>Justo dentro del elemento {{htmlelement("article")}} (debajo de la etiqueta de apertura), inserta el video de Youtube <a href="https://www.youtube.com/watch?v=ojcNcvb1olg">https://www.youtube.com/watch?v=ojcNcvb1olg</a>, utilizando las herramientas de YouTube para generar el código. El video debe tener 400px de ancho.</p> + +<h3 id="Agregar_imágenes_receptivas_a_los_enlaces_de_información_adicional">Agregar imágenes receptivas a los enlaces de información adicional</h3> + +<p> Dentro de {{htmlelement("div")}} con clase <code>further-info</code> encontrarás cuatro elementos {{htmlelement("a")}} -cada uno de los cuales vincula a una página interesante relacionada con Mozilla-. Para completar esta sección, debes insertar un elemento {{htmlelement("img")}} dentro de cada uno que contenga los atributos {{htmlattrxref("src", "img")}}, {{htmlattrxref("alt", "img")}}, {{htmlattrxref("srcset", "img")}} y {{htmlattrxref("sizes", "img")}}.</p> + +<p>En cada caso, (excepto uno que es inherentemente receptivo) queremos que el navegador sirva la versión 120px cuando el ancho de la ventana de visualización sea de 500px o menos, o la versión de 400px en otro caso.</p> + +<p>¡Asegúrate de hacer coincidir las imágenes correctas con los enlaces correctos!</p> + +<div class="note"> +<p><strong>Nota</strong>: para probar correctamente los ejemplos <code>srcset</code>/<code>sizes</code> necesitarás cargar tu sitio a un servidor (usar <a href="/en-US/docs/Learn/Common_questions/Using_Github_pages">Github pages</a> es una solución fácil y gratis), y desde allí puedes probar si funcionan correctamente usando herramientas de desarrollo del navegador como Firefox <a href="/en-US/docs/Tools/Network_Monitor">Network Monitor</a>.</p> +</div> + +<h3 id="Un_red-panda_con_arte_dirigido">Un "red-panda" con arte dirigido</h3> + +<p>Dentro del elemento {{htmlelement("div")}} con clase <code>red-panda</code>, queremos insertar un elemento {{htmlelement("picture")}} que permita una imagen pequeña del panda si la ventana tiene 600px de ancho o menos, y la gran imagen del paisaje en caso contrario.</p> + +<h2 id="Ejemplo">Ejemplo</h2> + +<p>Las siguientes capturas de pantalla muestran como debería verse la página de bienvenida después de haber sido marcada correctamente, en una pantalla ancha y estrecha.</p> + +<p><img alt="A wide shot of our example splash page" src="https://mdn.mozillademos.org/files/12946/wide-shot.png" style="border-style: solid; border-width: 1px; display: block; height: 620px; margin: 0px auto; width: 700px;"></p> + +<p><img alt="A narrow shot of our example splash page" src="https://mdn.mozillademos.org/files/12944/narrow-shot.png" style="border-style: solid; border-width: 1px; display: block; height: 1069px; margin: 0px auto; width: 320px;"></p> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Si quieres evaluar tu trabajo, estás atorado o quieres pedir ayuda:</p> + +<ol> + <li>Pon tu trabajo en un editor en línea para compartir, como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, or <a href="https://glitch.com/">Glitch</a>. Glitch es probablemente el mejor para este ejemplo, porque permite cargar propiedades como imágenes, mientras que algunas de las otras herramientas no lo hacen.</li> + <li>Escribe una publicación solicitando evaluación y/o ayuda en el foro <a href="https://discourse.mozilla.org/c/mdn">MDN Discourse forum</a>. Agrega la etiqueta "aprendizaje" a tu publicación para que podamos encontrarla más fácilmente. Tu publicación debe incluir: + <ul> + <li>Un título descriptivo como "Evaluación para página de bienvenida de Mozilla".</li> + <li>Detalles de lo que quiera que hagamos, por ejemplo, lo que ya has intentado, si estás atascado y necesitas ayuda.</li> + <li>Un enlace al ejemplo que deseas evaluar o en el que necesitas ayuda, en un editor en línea. Ésta es una buena práctica: es muy difícil ayudar a alguien con un problema de codificación si no puede ver su código.</li> + <li>Un enlace a la página de evaluación actual, para que podamos encontrar la pregunta con la que desea ayuda.</li> + </ul> + </li> +</ol> + +<p>{{PreviousMenu("Learn/HTML/Multimedia_and_embedding/Responsive_images", "Learn/HTML/Multimedia_and_embedding")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imágenes in HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">Contenido de Audio y Video</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">De <object> to <iframe> - otras tecnologías de inserción</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Agregar gráficos vectoriales a la Web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Imágenes receptivas</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Página de bienvenida de Mozilla</a></li> +</ul> diff --git a/files/es/learn/html/multimedia_and_embedding/other_embedding_technologies/index.html b/files/es/learn/html/multimedia_and_embedding/other_embedding_technologies/index.html new file mode 100644 index 0000000000..67b01247a4 --- /dev/null +++ b/files/es/learn/html/multimedia_and_embedding/other_embedding_technologies/index.html @@ -0,0 +1,371 @@ +--- +title: Desde object hasta iframe - otras tecnologías de incrustación +slug: Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies +translation_of: Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<p class="summary">Ahora ya deberías estar acostumbrado a integrar cosas en tus páginas web, incluyendo imágenes, video y audio. En este punto nos gustaría que des algo así como un paso al costado, prestando atención a elementos que te permiten integrar una amplia variedad de tipos de contenido en tus páginas web: los elementos {{htmlelement("iframe")}}, {{htmlelement("embed")}} y {{htmlelement("object")}}. Los <code><iframe></code>s son para incrustar otras páginas web, y los otros dos te permiten incrustar PDFs, SVG e incluso Flash — una tecnología que está en su camino de despedida, pero la cual seguirás viendo semi-regularmente.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, <a href="/es/docs/Learn/Getting_started_with_the_web/Instalacion_de_software_basico">software básico instalado</a>, conocimientos básicos de <a href="/es/docs/Learn/Getting_started_with_the_web/Manejando_los_archivos">manejo de archivos</a>, familiaridad con los fundamentos de HTML (visto en <a href="/es/docs/Learn/HTML/Introduccion_a_HTML/iniciar">Iniciando en HTML</a>) y los artículos previos en este modulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>To learn how to embed items into web pages using {{htmlelement("object")}}, {{htmlelement("embed")}}, and {{htmlelement("iframe")}}, like Flash movies and other webpages.</td> + </tr> + </tbody> +</table> + +<h2 id="Enlace_a_la_sección_Una_breve_historia_de_incrustación">Enlace a la sección: Una breve historia de incrustación</h2> + +<p>Hace mucho tiempo en la Web, era popular usar <strong>marcos (frames)</strong> para crear sitios web, pequeñas partes de un sitio web almacenadas en páginas HTML individuales. Estos estaban incrustados en un documento maestro llamado <strong>conjunto de marcos (frameset)</strong>, que le permitía especificar el área en la pantalla que ocupaba cada cuadro, como el tamaño de las columnas y las filas de una tabla. Estos fueron considerados el colmo del frescor a mediados y finales de los 90, y había evidencia de que tener una página web dividida en trozos más pequeños como este era mejor para velocidades de descarga, especialmente notable con conexiones de red tan lentas en ese momento. Sin embargo, tuvieron muchos problemas, que superaron con creces cualquier aspecto positivo ya que las velocidades de red se hicieron más rápidas, por lo que ya no se ve que se usen.</p> + +<p>Poco tiempo después (finales de los 90, principios de 2000), las tecnologías de complementos se volvieron muy populares, como los Applets de Java y Flash . Esto permitió a los desarrolladores web incorporar contenido enriquecido en páginas web como videos y animaciones, que simplemente no estaban disponibles solo a través de HTML. La incrustación de estas tecnologías se logró a través de elementos como <code><object></code> y el menos utilizado <code><embed></code> , que fueron muy útiles en ese momento. Desde entonces, pasaron de moda debido a muchos problemas, incluidos el acceso, la seguridad, el tamaño del archivo y entre otros; en la actualidad, la mayoría de los dispositivos móviles ya no son compatibles con estos complementos, y el soporte de escritorio está en camino de desaparecer.</p> + +<p>Finalmente, apareció el elemento <code><iframe></code> (junto con otras formas de incrustación de contenido, como <code><canvas></code> , <code><video></code> , etc.). Esto proporciona una forma de insertar un documento web entero dentro de otro, como si fuera un <code><img></code> u otro elemento similar, y asi es como se usa en la actualidad.</p> + +<p>Con la lección de historia fuera del camino, sigamos y veamos cómo usar algunos de estos.</p> + +<h2 id="Aprendizaje_activo_usos_de_incrustación_clásicos">Aprendizaje activo: usos de incrustación clásicos</h2> + +<p>En este artículo vamos a ir directamente a una sección de aprendizaje activo, para darle una idea real de la utilidad de las tecnologías de inclusión. El mundo en línea está muy familiarizado con Youtube, pero muchas personas no conocen algunas de las comodidades para compartir que tiene disponibles. Veamos cómo Youtube nos permite insertar un video en cualquier página que nos guste usando un <code><iframe></code> .</p> + +<ol> + <li>Primero, ve a Youtube y encuentra el video que te gusta.</li> + <li>Debajo del video, encontrará un botón <em>Compartir</em> : seleccionelo para mostrar las opciones para compartir.</li> + <li>Seleccione el botón <em>Insertar</em> y recibirá un código <code><iframe></code> - copielo.</li> + <li>Insértelo en el cuadro de <em>entrada a</em> continuación, y vea cuál es el resultado en la <em>salida</em> .</li> +</ol> + +<p>Para obtener puntos de bonificación, también puede intentar insertar un mapa de Google en el ejemplo:</p> + +<ol> + <li>Ve a Google Maps y encuentra un mapa que te guste.</li> + <li>Haga clic en el "Menú Hamburger" (tres líneas horizontales) en la esquina superior izquierda de la IU.</li> + <li>Seleccione la opción <em>Compartir o Insertar mapa</em> .</li> + <li>Seleccione la opción Insertar mapa, que le dará un código <code><iframe></code> - copielo.</li> + <li>Insértelo en el cuadro de <em>entrada a</em> continuación, y vea cuál es el resultado en la <em>salida</em> .</li> +</ol> + +<p>Si comete un error, siempre puede restablecerlo usando el botón <em>Restablecer</em> . Si realmente te quedas atascado, presiona el botón <em>Mostrar solución</em> para ver una respuesta.</p> + +<div class="hidden"> +<h6 id="Código_interactivo">Código interactivo</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> + +<div class="output" style="min-height: 250px;"> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="input" style="width: 95%;min-height: 100px;"> +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div></pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var output = document.querySelector('.output'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + output.innerHTML = textarea.value; +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = htmlSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var htmlSolution = '<iframe width="420" height="315" src="https://www.youtube.com/embed/QH2-TGUlwu4" frameborder="0" allowfullscreen>\n</iframe>\n\n<iframe src="https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d37995.65748333395!2d-2.273568166412784!3d53.473310471916975!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x487bae6c05743d3d%3A0xf82fddd1e49fc0a1!2sThe+Lowry!5e0!3m2!1sen!2suk!4v1518171785211" width="600" height="450" frameborder="0" style="border:0" allowfullscreen>\n</iframe>'; +var solutionEntry = htmlSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', 700, 600, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Iframes_en_detalle">Iframes en detalle</h2> + +<p>Entonces, fue fácil y divertido ¿verdad? Los elementos {{htmlelement("iframe")}} están diseñados para permitirte incrustar documentos web en el documento actual. Esto es excelente para incorporar contenido de terceros en tu sitio web sobre el que no tengas control directo y no quieras tener que implementar tu propia versión — como vídeo de porveedeores de vídeo en línea, sistemas de comentarios como <a href="https://disqus.com/">Disqus</a>, mapas de proveedores de mapas en línea, banners publicitarios, etc. Los ejemplos editables que has estado usando a través de este curso se implementan usando <code><iframe></code>s.</p> + +<p>Hay algunos serios {{anch("Security concerns")}} a considerar con <code><iframe></code>s, también se discute a continuación, pero esto no significa que debas dejar de usarlos en tus sitios web — solo requiere un poco de conocimiento y pensar cuidadosamente. Vamos a explorar el código con un poco más de detalle. Supongamos que quieres incluir el glosario de MDN en una de tus páginas web — podrías intentar algo como esto:</p> + +<pre class="notranslate"><iframe src="https://developer.mozilla.org/en-US/docs/Glossary" + width="100%" height="500" frameborder="0" + allowfullscreen sandbox> + <p> <a href="https://developer.mozilla.org/en-US/docs/Glossary"> + Fallback link for browsers that don't support iframes + </a> </p> +</iframe></pre> + +<p>Este ejemplo incluye los elementos básicos necesarios para usar un <code><iframe></code>:</p> + +<dl> + <dt>{{htmlattrxref('allowfullscreen','iframe')}}</dt> + <dd>Si está configurado, el <code><iframe></code> se puede colocar en modo pantalla completa usando el <a href="/en-US/docs/Web/API/Fullscreen_API">Full Screen API</a> (El uso del API está fuera del alcance de este artículo.)</dd> + <dt>{{htmlattrxref('frameborder','iframe')}}</dt> + <dd>Si se establece en 1, esto le indica al navegador que dibuje un borde entre este marco y otros marcos, que es el comportamiento predeterminado. 0 elimina el borde. Usar esto ya no es realmente recomendable, ya que el mismo efecto se puede lograr mejor usando{{cssxref('border')}}<code>: none;</code> en tu {{Glossary('CSS')}}.</dd> + <dt>{{htmlattrxref('src','iframe')}}</dt> + <dd>Este atributo, como con {{htmlelement("video")}}/{{htmlelement("img")}},contiene una ruta que apunta a la URL del documento que se va a incrustar.</dd> + <dt>{{htmlattrxref('width','iframe')}} and {{htmlattrxref('height','iframe')}}</dt> + <dd>Estos atributos especifican el ancho y la altura (width y height) que quieres que tenga el iframe.</dd> + <dt><strong>Contenido de reserva</strong></dt> + <dd>De la misma manera que otros elementos similares {{htmlelement("video")}}, puedes incluir contenido alternativo entre las etiquetas de apertura y cierre <code><iframe></iframe></code> que aparecerán si el navegador no admite el <code><iframe></code>. En este caso hemos incluido un enlace a la página. Es poco probable que encuentres algún navegador que no admita <code><iframe></code>s en estos días.</dd> + <dt>{{htmlattrxref('sandbox','iframe')}}</dt> + <dd>Este atributo, que funciona en navegadores un poco más modernos que el resto de la funciones de <code><iframe></code> (por ejemplo IE 10 y superior) solicita una mayor configuración de seguridad; bueno, hablaremos más sobre esto en la siguiente sección.</dd> +</dl> + +<div class="note"> +<p><strong>Nota</strong>: Para mejorar la velocidad, es una buena idea establecer el atributo <code>src</code> de iframes con JavaScript después de que se cargue el contenido principal. Esto hace que tu página pueda utilizarse antes y disminuye el tiempo de carga de tu página principal (an important {{Glossary("SEO")}}.)</p> +</div> + +<h3 id="Con_respecto_a_la_seguridad">Con respecto a la seguridad</h3> + +<p>Arriba mencionamos nuestra preocupación por la seguridad — vamos a entrar en esto con un poco más de detalle ahora. No esperamos que comprendas todo este contenido perfectametne a la primera. Solo queremos informarte sobre esta preocupación y proporcionarte una referencia a la que volver a medida que tengas más experiencia y comiences a considerar el uso de <code><iframe></code>s en tu trabajo y en tus experimentos.además, no es necesario tener miedo y no usar <code><iframe></code>s — iframes, solo debes tener cuidado. Sigue leyendo...</p> + +<p>Los creadores de navegadores y los desarrolladores web han aprendido por las malas que los iframes son un objetivo común (término oficial: <strong>vector de ataque</strong>) para los "malos" de la Web (a menudo denominados <strong>hackers</strong>,o más exactamente, <strong>crackers</strong>) para atacar si están tratando de modificar maliciosamente tu página web, o engañar a las personas para que hagan algo que no quieren hacer, como revelar información confidencial como nombre de usuario o contraseña. Debido a esto, los ingenieros de especificaciones y los desarrolladores de navegadores han desarrollado varios mecanismos para hacer que los <code><iframe></code>s sean más seguros, y también hay mejores prácticas a considerar — cubriremos algunas de estas a continuación.</p> + +<div class="note"> +<p>{{interwiki('wikipedia','Clickjacking')}} es un tipo de ataque de iframe común en el que los piratas informáticos incrustan un iframe invisible en tu documento (o incrustan tu documento en su propio sitio web malicioso) y lo utilizan para capturar las interacciones de los ususarios. Esta es una forma común de engañar a los usuarios o robar datos sensibles.</p> +</div> + +<p>Primero un ejemplo rápido — intenta cargar el ejemplo anterior que mostramos arriba en tu navegador — puedes encontrarlo en <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/other-embedding-technologies/iframe-detail.html"> Github</a> (ver el <a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/other-embedding-technologies/iframe-detail.html">código fuente</a> ) Tu no verás nada en tu navegador, pero si miras en la <em>Consola</em> en las <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">herramientas de desarrollador de tu navegador</a>, tú verás un mensaje diciendote porque.En Firefox, te dirá <em>Load denied by X-Frame-Options: https://developer.mozilla.org/en-US/docs/Glossary does not permit framing</em>. Esto es porque los desarrolladores que construyeron MDN han incluido una configuración en el servidor que almacena la página web que impide que sean incrustados dentro de <code><iframe></code>s (ver {{anch("Configure CSP directives")}}, abajo.) Esto tiene sentido— una página completa de MDN no tiene sentido estar incrustada en otras páginas, a menos que tu quieras hacer algo como incrustarlas en tu sitio web y reclamarlas como propias — o intentar robar datos via clickjacking, los cuales ambos son cosas realmente malas. Además de que si todo el mundo comienza a hacerlo, todo el ancho de banda adicional podría costarle mucho dinero a Mozzilla.</p> + +<h4 id="Solo_incrusta_cuando_sea_necesario">Solo incrusta cuando sea necesario</h4> + +<p>Algunas veces tiene sentido embeber contenido de terceros— como vídeos de youtube y mapas — pero puedes ahorrarte muchos dolores de cabeza si tu solo embebes contenido de terceros solo cuando es necesario. Una buena regla de oro para la seguridad web es "Nunca puedes ser demasiado cauteloso. Si lo hizo, verifíquelo de todos modos. Si alguien más lo hizo, asuma que es peligroso hasta que se demuestre lo contrario".</p> + +<p>Además de la seguridad, debes ser consciente de los temas de propiedad intelectual. La mayoría del contenido tiene derechos de autor, en línea y fuera de línea, incluso contenido que no te esperas(por ejemplo, la mayoría de las imágenes en <a href="https://commons.wikimedia.org/wiki/Main_Page">Wikimedia Commons</a>). Nunca muestres en tu pagina contenido a menos que te pertenezca o que el dueño te haya dado por escrito su permiso inequívoco. Las penalidades por derechos de autor son severas. De nuevo, tu nunca puedes ser demasiado cauteloso. </p> + +<p>Si el contenido es licenciado, debes obedecer los terminos de la licencia. Por ejemplo, el contenido en MDN es licenciado bajo<a href="/en-US/docs/MDN/About#Copyrights_and_licenses"> CC-BY-SA</a>. Esto significa, que tu debes darnos <a href="https://wiki.creativecommons.org/wiki/Best_practices_for_attribution">credito apropiadamente</a> cuando tu citas nuestro contenido, aun si tu haces cambios substanciales.</p> + +<h4 id="Usa_HTTPS">Usa HTTPS</h4> + +<p>{{Glossary("HTTPS")}} es la versión encriptada de {{Glossary("HTTP")}}. Deberias cumplir con tu página web usando HTTPS siempre que sea posible:</p> + +<ol> + <li>HTTPS reduce la oportunidad de que contenido remoto haya sido manipulado en el tránsito.</li> + <li>HTTPS previene que el contenido embebido acceda al documento padre y viceversa. </li> +</ol> + +<p>Usar HTTPS requiere un certificado de seguridad, el cual puede ser costoso (Aunque <a href="https://letsencrypt.org/">Let's Encrypt</a> hace las cosas más faciles) — si tu no puedes tener uno, tu debes servir tu documento padre con HTTP. Sin embargo, debido al segundo beneficio de HTTPS expuesto arriba, no importa cual sea el costo tu nunca debes embeber contenido de terceros con HTTP. (En el mejor de los casos, el navegador de tus usuarios les dará una advertencia). Todas las empresas con buena reputación que hacen contenido para embeber via <code><iframe></code> lo harán disponible via HTTPS — mira la URLs dentro del <code><iframe></code> atributo <code>src</code> cuando tu estes embebiendo contenido desde Google Maps o Youtube, por ejemplo.</p> + +<div class="note"> +<p><strong>Note</strong>: <a href="/en-US/docs/Learn/Common_questions/Using_Github_pages">Github pages</a> permite que el contenido sea servido via HTTPS por defecto, asi que es util para hospedar tu contenido. Si estás usando un hosting diferente y no estás seguro, pregunta a tu proveedor de hosting acerca del tema .</p> +</div> + +<h4 id="Siempre_usa_el_atributo_sandbox">Siempre usa el atributo <code>sandbox</code></h4> + +<p>You want to give attackers as little power as you can to do bad things on your website, therefore you should give embedded content <em>only the permissions needed for doing its job. </em>Of course, this applies to your own content, too. un contenedor para codigo que puedes usar apropiadamente — o para probar — but can't cause any harm to the rest of the codebase (either accidental or malicious) is called a <a href="https://en.wikipedia.org/wiki/Sandbox_(computer_security)">sandbox</a>.</p> + +<p>Unsandboxed content can do way too much (executing JavaScript, submitting forms, popup windows, etc.) By default you should impose all available restrictions by using the <code>sandbox</code> attribute with no parameters, as shown in our previous example.</p> + +<p>If absolutely required, you can add permissions back one by one (inside the <code>sandbox=""</code> attribute value) — see the {{htmlattrxref('sandbox','iframe')}} reference entry for all the available options. One important note is that you should <em>never</em> add both <code>allow-scripts</code> and <code>allow-same-origin</code> to your <code>sandbox</code> attribute — in that case the embedded content could bypass the same origin security policy that stops sites from executing scripts, and use JavaScript to turn off sandboxing altogether.</p> + +<div class="note"> +<p><strong>Note</strong>: Sandboxing provides no protection if attackers can fool people into visiting malicious content directly (outside an <code>iframe</code>). If there's any chance that certain content may be malicious (e.g., user-generated content), please serve it from a different {{glossary("domain")}} to your main site.</p> +</div> + +<h4 id="Configure_CSP_directives">Configure CSP directives</h4> + +<p>{{Glossary("CSP")}} stands for <strong><a href="/en-US/docs/Web/Security/CSP">content security policy</a></strong>, and provides <a href="/en-US/docs/Web/Security/CSP/CSP_policy_directives">a set of HTTP Headers</a> (metadata sent along with your web pages when they are served from a web server) designed to improve the security of your HTML document. When it comes to securing <code><iframe></code>s, you can <em><a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/X-Frame-Options">configure your server to send an appropriate <code>X-Frame-Options</code> header.</a></em> This can prevent other websites from embedding your content in their webpages (which would enable {{interwiki('wikipedia','clickjacking')}} and a host of other attacks), which is exactly what the MDN developers have done, as we saw earlier on.</p> + +<div class="note"> +<p><strong>Note</strong>: You can read Frederik Braun's post <a href="https://blog.mozilla.org/security/2013/12/12/on-the-x-frame-options-security-header/">On the X-Frame-Options Security Header</a> for more background information on this topic. Obviously, it's rather out of scope for a full explanation in this article.</p> +</div> + +<h2 id="The_<embed>_and_<object>_elements">The <embed> and <object> elements</h2> + +<p>The {{htmlelement("embed")}} and {{htmlelement("object")}} elements serve a different function to {{htmlelement("iframe")}} — these elements are general purpose embedding tools for embedding multiple types of external content, which include plugin technologies like Java Applets and Flash, PDF (which can be shown in a browser with a PDF plugin), and even content like videos, SVG and images!</p> + +<div class="note"> +<p><strong>Note</strong>: A <strong>plugin</strong> is software that provides access to content the browser cannot read natively.</p> +</div> + +<p>However, you are unlikely to use these elements very much — Applets haven't been used for years, Flash is no longer very popular, due to a number of reasons (see {{anch("The case against plugins")}}, below), PDFs tend to be be better linked to than embedded, and other content such as images and video have much better, easier elements to handle those. Plugins and these embedding methods are really a legacy technology, and we are mainly mentioning them in case you come across them in certain circumstances like intranets, or enterprise projects.</p> + +<p>If you find yourself needing to embed plugin content, this is the kind of information you'll need, at a minimum:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col"></th> + <th scope="col">{{htmlelement("embed")}}</th> + <th scope="col">{{htmlelement("object")}}</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{glossary("URL")}} of the embedded content</td> + <td>{{htmlattrxref('src','embed')}}</td> + <td>{{htmlattrxref('data','object')}}</td> + </tr> + <tr> + <td><em>accurate </em>{{glossary("MIME type", 'media type')}} of the embedded content</td> + <td>{{htmlattrxref('type','embed')}}</td> + <td>{{htmlattrxref('type','object')}}</td> + </tr> + <tr> + <td>height and width (in CSS pixels) of the box controlled by the plugin</td> + <td>{{htmlattrxref('height','embed')}}<br> + {{htmlattrxref('width','embed')}}</td> + <td>{{htmlattrxref('height','object')}}<br> + {{htmlattrxref('width','object')}}</td> + </tr> + <tr> + <td>names and values, to feed the plugin as parameters</td> + <td>ad hoc attributes with those names and values</td> + <td>single-tag {{htmlelement("param")}} elements, contained within <code><object></code></td> + </tr> + <tr> + <td>independent HTML content as fallback for an unavailable resource</td> + <td>not supported (<code><noembed></code> is obsolete)</td> + <td>contained within <code><object></code>, after <code><param></code> elements</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Note</strong>: <code><object></code> requires a <code>data</code> attribute, a <code>type</code> attribute, or both. If you use both, you may also use the {{htmlattrxref('typemustmatch','object')}} attribute (only implemented in Firefox, as of this writing). <code>typemustmatch</code> keeps the embedded file from running unless the <code>type</code> attribute provides the correct media type. <code>typemustmatch</code> can therefore confer significant security benefits when you're embedding content from a different {{glossary("origin")}} (it can keep attackers from running arbitrary scripts through the plugin).</p> +</div> + +<p>Here's an example that uses the {{htmlelement("embed")}} element to embed a Flash movie (see this <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/other-embedding-technologies/embed-flash.html">live on Github</a>, and <a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/other-embedding-technologies/embed-flash.html">check the source code</a> too):</p> + +<pre class="brush: html notranslate"><embed src="whoosh.swf" quality="medium" + bgcolor="#ffffff" width="550" height="400" + name="whoosh" align="middle" allowScriptAccess="sameDomain" + allowFullScreen="false" type="application/x-shockwave-flash" + pluginspage="http://www.macromedia.com/go/getflashplayer"></pre> + +<p>Pretty horrible, isn't it. The HTML generated by the Adobe Flash tool tended to be even worse, using an <code><object></code> element with an <code><embed></code> element embedded in it, to cover all bases (check out an example.) Flash was even used successfully as fallback content for HTML5 video, for a time, but this is increasingly being seen as not necessary.</p> + +<p>Now let's look at an <code><object></code> example that embeds a PDF into a page (see the <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/other-embedding-technologies/object-pdf.html">live example</a> and the <a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/other-embedding-technologies/object-pdf.html">source code</a>):</p> + +<pre class="brush: html notranslate"><object data="mypdf.pdf" type="application/pdf" + width="800" height="1200" typemustmatch> + <p>You don't have a PDF plugin, but you can <a href="myfile.pdf">download the PDF file.</a></p> +</object></pre> + +<p>PDFs were a necessary stepping stone between paper and digital, but they pose many <a href="http://webaim.org/techniques/acrobat/acrobat">accessibility challenges</a> and can be hard to read on small screens. They do still tend to be popular in some circles, but it is much better to link to them so they can be downloaded or read on a separate page, rather than embedding them in a webpage.</p> + +<h3 id="The_case_against_plugins">The case against plugins</h3> + +<p>Once upon a time, plugins were indispensable on the Web. Remember the days when you had to install Adobe Flash Player just to watch a movie online? And then you constantly got annoying alerts about updating Flash Player and your Java Runtime Environment. Web technologies have since grown much more robust, and those days are over. For most applications, it's time to stop delivering content that depends on plugins, and start taking advantage of Web technologies instead.</p> + +<ul> + <li><strong>Broaden your reach to everyone. </strong>Everyone has a browser, but plugins are increasingly rare, especially among mobile users. Since the Web is largely usable without plugins, people would rather just go to your competitors' websites than install a plugin.</li> + <li><strong>Give yourself a break from the <a href="http://webaim.org/techniques/flash/">extra accessibility headaches </a>that come with Flash and other plugins.</strong></li> + <li><strong>Stay clear of additional security hazards. </strong>Adobe Flash is <a href="http://www.cvedetails.com/product/6761/Adobe-Flash-Player.html?vendor_id=53">notoriously insecure,</a> even after countless patches. In 2015, Alex Stamos, chief security officer of Facebook, even <a href="http://www.theverge.com/2015/7/13/8948459/adobe-flash-insecure-says-facebook-cso">requested that Adobe discontinue Flash.</a></li> +</ul> + +<p>So what should you do? If you need interactivity, HTML and {{glossary("JavaScript")}} can readily get the job done for you with no need for Java applets or outdated ActiveX/BHO technology. Instead of relying on Adobe Flash, you can use <a href="/en-US/docs/Learn/HTML/Howto/Add_audio_or_video_content_to_a_webpage">HTML5 video</a> for your media needs, <a href="/en-US/docs/Learn/HTML/Howto/Add_vector_image_to_a_webpage">SVG</a> for vector graphics, and <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial">Canvas</a> for complex images and animations. <a href="https://plus.google.com/+PeterElst/posts/P5t4pFhptvp">Peter Elst was already writing some years ago</a> that Adobe Flash is rarely the right tool for the job, except for specialized gaming and business applications. As for ActiveX, even Microsoft's {{glossary("Microsoft Edge","Edge")}} browser no longer supports it.</p> + +<h2 id="Summary">Summary</h2> + +<p>The topic of embedding other content in web documents can quickly become very complex, so in this article we've tried to introduce it in a simple, familiar way that will immediately seem relevant, while still hinting at some of the more advanced features of the involved technologies. To start with, you are unlikely to use embedding for much beyond including third party content like maps and videos on your pages. As you become more experienced however, you are likely to start finding more uses for them.</p> + +<p>There are many other technologies that involve embedding external content besides the ones we discussed here. We saw some in earlier articles, such as {{htmlelement("video")}}, {{htmlelement("audio")}}, and {{htmlelement("img")}}, but there are others to discover, such as {{htmlelement("canvas")}} for JavaScript-generated 2D and 3D graphics, and {{htmlelement("svg")}} for embedding vector graphics. We'll look at <a href="/en-US/docs/Web/SVG">SVG</a> in the next article of the module.</p> + +<p>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Video_and_audio_content", "Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Images in HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Video and audio content</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">From <object> to <iframe> — other embedding technologies</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Adding vector graphics to the Web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Responsive images</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla splash page</a></li> +</ul> diff --git a/files/es/learn/html/multimedia_and_embedding/responsive_images/index.html b/files/es/learn/html/multimedia_and_embedding/responsive_images/index.html new file mode 100644 index 0000000000..daa97085e9 --- /dev/null +++ b/files/es/learn/html/multimedia_and_embedding/responsive_images/index.html @@ -0,0 +1,265 @@ +--- +title: Imágenes adaptables +slug: Learn/HTML/Multimedia_and_embedding/Responsive_images +translation_of: Learn/HTML/Multimedia_and_embedding/Responsive_images +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<div> +<p class="summary">En este artículo, aprenderemos sobre el concepto de imágenes adaptables — imágenes que funcionan bien en dispositivos con una amplia diferencia de tamaño de pantallas, resoluciones y otras tantas características — y observar qué herramientas proporciona HTML para ayudar a implementarlas. Esto ayuda a mejorar el rendimiento en diferentes dispositivos.</p> + +<p class="summary">Las imágenes adaptables son solo una parte del diseño web responsivo, un tema que aprenderás próximamente en nuestro tutorial de <a href="/en-US/docs/Learn/CSS">CSS</a>.</p> +</div> + +<table class="learn-box nostripe standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Deberías tener un conocimiento <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">básico de HTML</a> y cómo <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">agregar imágenes estáticas a un sitio web</a>.</td> + </tr> + <tr> + <th scope="row"><span style="display: none;"> </span>Objetivo:<span style="display: none;"> </span></th> + <td>Aprende a usar características como {{htmlattrxref("srcset", "img")}} y el elemento {{htmlelement("picture")}} para implementar soluciones de imágenes adaptables a sitios web.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Por_qué_imágenes_adaptables">¿Por qué imágenes adaptables?</h2> + +<p>Examinemos un escenario típico. Un sitio web típico puede contener una imagen de encabezado y algunas imágenes de contenido debajo del encabezado. Es probable que la imagen del encabezado abarque todo el ancho del encabezado y la imagen del contenido quepa en algún lugar dentro de la columna de contenido. He aquí un ejemplo sencillo:</p> + +<p><img alt="Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center." src="https://mdn.mozillademos.org/files/12940/picture-element-wide.png" style="display: block; height: 554px; margin: 0px auto; width: 700px;"></p> + +<p>Esto funciona bien en un dispositivo de pantalla ancha, como una computadora portatil o de escritorio (puedes <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/not-responsive.html">ver el ejemplo en vivo </a>y encontrar el <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/responsive-images/not-responsive.html">código fuente</a> en Github.) No hablaremos mucho del CSS en esta lección, excepto para decir que:</p> + +<ul> + <li>El contenido del <code><em>body</em></code> se ha ajustado a un ancho máximo de 1200 píxeles - en pantallas por encima de ese ancho, el cuerpo permanece a 1200px y se centra en el espacio disponible. En pantallas por debajo de ese ancho, el cuerpo permanecerá al 100% del ancho de la ventana.</li> + <li>La imagen del encabezado se ha configurado para que su centro siempre permanezca en el centro del encabezado, sin importar el ancho que tenga el encabezado. Por lo tanto, si el sitio se visualiza en una pantalla más estrecha, aún se puede ver el detalle importante en el centro de la imagen (las personas) y el exceso se pierde en ambos lados. Tiene 200px de alto.</li> + <li>Las imágenes de contenido se han configurado de modo que si el elemento <code>body</code> se vuelve más pequeño que la imagen, las imágenes comienzan a encogerse para permanecer siempre dentro del <code>body</code>, en lugar de desbordarlo.</li> +</ul> + +<p>Sin embargo, surgen problemas cuando comienza a ver el sitio en un dispositivo de pantalla estrecha — el encabezado de abajo está bien, pero empieza a ocupar gran parte de la altura de la pantalla de un dispositivo móvil. ¡A este tamaño es difícil ver a las personas que aparecen en la foto!</p> + +<p><img alt="Our example site as viewed on a narrow screen; the first image has shrunk to the point where it is hard to make out the detail on it." src="https://mdn.mozillademos.org/files/12936/non-responsive-narrow.png" style="display: block; height: 793px; margin: 0px auto; width: 320px;" title=""></p> + +<p>Una mejora sería mostrar una versión recortada de la imagen que muestra los detalles importantes de la imagen cuando el sitio se ve en una pantalla estrecha. Se podría mostrar una segunda imagen recortada para un dispositivo de pantalla de ancho medio, como una tableta. A esto se le conoce comúnmente como <strong>el problema de cambio de resolución.</strong></p> + +<p>Además, no es necesario incrustar imágenes más grandes en la página si se está viendo en una pantalla móvil. Y, a la inversa, una <a href="https://wiki.developer.mozilla.org/en-US/docs/Glossary/Raster_image">imagen rasterizada</a> pequeña comienza a verse más pixelada cuando se muestra mayor que su tamaño original (una imagen rasterizada es un conjunto determinado de píxeles de ancho y de alto, como vimos cuando vimos los gráficos vectoriales). Esto se denomina problema de cambio de resolución.</p> + +<p>Por el contrario, no es necesario mostrar una imagen grande en una pantalla significativamente más pequeña que el tamaño para el que fue diseñada. Hacerlo puede desperdiciar ancho de banda; en particular, los usuarios de dispositivos móviles no quieren desperdiciar ancho de banda descargando una imagen grande destinada al escritorio, cuando una imagen pequeña sería suficiente para su dispositivo. Idealmente, tendría varias resoluciones disponibles y serviría el tamaño apropiado según el dispositivo que acceda a los datos en el sitio web.</p> + +<p>Para hacer las cosas más complicadas, algunos dispositivos tienen pantallas de alta resolución que necesitan imágenes más grandes de las que se espera que luzcan bien. Esto es, básicamente, el mismo problema, pero en un contexto ligeramente diferente.</p> + +<p>Podrías pensar que las imágenes vectoriales resolverían estos problemas, y lo hacen hasta cierto punto: son pequeñas en tamaño de archivo y escalan bien, y deberías usarlos siempre que sea posible. Sin embargo, no son adecuados para todos tipos de imágenes. Si bien son geniales para gráficos simples, patrones, elementos de interfaz, etc., es muy complejo crear una imagen basada en vectores con la cantidad de detalles que encontrarías, por ejemplo, en una foto. Formatos de imágenes rasterizadas como JPEG son más adecuados para el tipo de imágenes que vemos en el ejemplo anterior.</p> + +<p>Este tipo de problemas no existían cuando la web se creó por primera vez, a principios y mediados de los noventa — en ese entonces, los únicos dispositivos disponibles para navegar por la web eran los ordenadores de escritorio y laptops, por lo que los desarrolladores e ingenieros que programaban los navegadores ni siquiera pensaban en implementar estas soluciones. Las tecnologías de imagen adaptable<em> </em>se implementaron recientemente para resolver los problemas descritos anteriormente al permitirle ofrecer al navegador varias versiones de imágenes (en diferentes archivos), ya sea que muestren lo mismo pero contengan diferentes números de píxeles (cambio de resolución), o diferentes imágenes adecuadas para diferentes asignaciones de espacio (dirección de arte).</p> + +<div class="note"> +<p><strong>Nota</strong>: Las nuevas características discutidas en este artículo — {{htmlattrxref("srcset", "img")}}/{{htmlattrxref("sizes", "img")}}/{{htmlelement("picture")}} —son compatibles con las versiones de lanzamiento de los navegadores de escritorio y móviles modernos (incluido el navegador Edge de Microsoft, aunque no Internet Explorer).</p> +</div> + +<h2 id="¿Cómo_se_crean_las_imágenes_adaptables">¿Cómo se crean las imágenes adaptables?</h2> + +<p>En esta sección, veremos los dos problemas ilustrados anteriormente y mostraremos cómo solucionarlos usando las características de imágenes adaptables con HTML. Debe tener en cuenta que nos centraremos en el elemento HTML {{htmlelement("img")}} para esta sección, tal como se muestra en el área de contenido del ejemplo anterior — la imagen en el encabezado del sitio es solo de decoración y, por lo tanto, implementado usando imágenes de fondo con CSS. Se puede decir que<a href="http://blog.cloudfour.com/responsive-images-101-part-8-css-images/"> CSS posee mejores herramientas para el diseño adaptable que HTML</a>, y hablaremos sobre ellas en nuestro módulo <a href="/en-US/docs/Web/CSS">CSS</a>. </p> + +<h3 id="Cambio_de_resolución_Diferentes_tamaños">Cambio de resolución: Diferentes tamaños</h3> + +<p>Entonces, ¿qué queremos solucionar con el cambio de resolución? Queremos mostrar la misma imagen, más grande o más pequeña dependiendo del dispositivo — Esta es la situación que tenemos en la segunda imagen de nuestro ejemplo. El elemento estándar {{htmlelement("img")}} tradicionalmente solo permite apuntar el navegador a un solo archivo fuente:</p> + +<pre class="brush: html notranslate"><img src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy"></pre> + +<p>Sin embargo, podemos utilizar dos nuevos atributos — {{htmlattrxref("srcset", "img")}} y {{htmlattrxref("sizes", "img")}} — para proporcionar varias imágenes de origen adicionales junto con sugerencias para ayudar al navegador a elegir el correcto. Puede ver el ejemplo <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/responsive.html">responsive.html</a> en Github (vea también <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/responsive-images/responsive.html">el código fuente</a>):</p> + +<pre class="brush: html notranslate"><img srcset="elva-fairy-320w.jpg 320w, + elva-fairy-480w.jpg 480w, + elva-fairy-800w.jpg 800w" + sizes="(max-width: 320px) 280px, + (max-width: 480px) 440px, + 800px" + src="elva-fairy-800w.jpg" alt="Elva dressed as a fairy"></pre> + +<p>Los atributos <code>srcset</code> y <code>sizes</code> parecen complicados, pero resultan más fáciles de entender si los formatea como se muestra arriba, con valores diferentes para el atributo en cada línea. Cada valor contiene una lista separada por coma, y cada parte de la lista está compuesta por tres sub-partes. Repasemos ahora el contenido de cada uno:</p> + +<p><strong><code>srcset</code></strong> define el conjunto de imágenes que el navegador podrá elegir, y el tamaño de cada imagen.<strong> </strong>Cada conjunto de información de imagen está separado del anterior por una coma. Para cada uno, escribimos:</p> + +<ol> + <li>Un nombre de archivo de imagen (elva-fairy-480w.jpg)</li> + <li>Un espacio.</li> + <li>El <strong>ancho intrínseco de la imagen en píxeles</strong> (480w): tenga en cuenta que esto usa la unidad w, no px como cabría esperar. Este es el tamaño real de la imagen, que se puede encontrar inspeccionando el archivo de imagen en su computadora (por ejemplo, en una Mac puede seleccionar la imagen en Finder y presionar <kbd>Cmd</kbd> + <kbd>I</kbd> para que aparezca la pantalla de información).</li> +</ol> + +<p><strong><code>sizes</code></strong> define un conjunto de condiciones de medios (por ejemplo, anchos de pantalla) e indica qué tamaño de imagen sería mejor elegir cuando se cumplen ciertas condiciones de medios — estas son las sugerencias de las que hablamos anterriormente. En este caso, antes de cada coma escribimos:</p> + +<ol> + <li>Una <strong>condición de medios</strong> ((max-width: 600px)): aprenderá más sobre esto en el <a href="/en-US/docs/Web/CSS">tema CSS</a>, pero por ahora digamos que una condición de medios describe un posible estado en el que puede estar la pantalla. En este caso, estamos diciendo "cuando el ancho de la ventana gráfica es de 600 píxeles o menos".</li> + <li>Un espacio.</li> + <li>El <strong>ancho de la ranura</strong> que la imagen llenará cuando la condición de medios sea verdadera (<code>440px</code>.)</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Para el <strong>ancho de la ranura</strong>, debe indicar una longitud absoluta (<code>px</code>, <code>em</code>) o relativa (como un porcentaje.) Usted debe haber advertido que el ancho de la última ranura no tiene condición de medios (esta es la opción por defecto que se elige cuando ninguna de las condiciones de medios se cumplen). El navegador ignora todo lo posterior a la primera condición coincidente, por eso sea cuidadoso con el orden de las condiciones de medios.</p> +</div> + +<p>Entonces, con estos atributos establecidos, el navegador:</p> + +<ol> + <li>Verificará el ancho del dispositivo.</li> + <li>Resolverá qué condición de medios en la lista <code>sizes</code> es la primera que se cumple.</li> + <li>Verificará la medida de la ranura dada a esa consulta de medios.</li> + <li>Cargará la imagen referenciada en la lista <code>srcset</code> con coincidencia más cercana a la medida de la ranura.</li> +</ol> + +<p>¡Y eso es todo! Hasta este punto, si un navegador compatible con un ancho de ventana de 480px carga la página, la condición de medios <code>(max-width: 480px)</code> se cumplirá, por lo que la ranura de <code>440px</code> será elegida y se cargará el archivo de imagen <code>elva-fairy-480w.jpg</code>, ya que el ancho inherente (<code>480w</code>) es el más cercano a <code>440px</code>. La imagen de 800px tiene 128KB en disco mientras que la versión de 480px tiene solo 63KB — un ahorro de 65KB. Ahora imagine si esta fuera una página que tuviera muchas imágenes. Usar esta técnica puede ahorrarle a los usuarios de dispositivos móviles mucho ancho de banda.</p> + +<div class="blockIndicator note"> +<p><strong>Nota:</strong> Al probar esto con un navegador de escritorio, si el navegador no carga las imágenes más estrechas cuando tiene su ventana configurada en el ancho más estrecho, eche un vistazo a cuál es la ventana gráfica (puede aproximarla yendo a la <u>Consola JavaScript</u> del navegador y escribiendo <code>document.querySelector('html').clientWidth</code>). Los diferentes navegadores tienen tamaños mínimos a los que te permitirán reducir el ancho de la ventana y pueden ser más anchos de lo que piensas. Al probarlo con un navegador móvil, puede usar herramientas como la página de depuración de Firefox <code>about:debugging</code> para inspeccionar la página cargada en el dispositivo móvil usando las herramientas de desarrollo de escritorio. Para ver qué imágenes se cargaron, puede usar la pestaña <a href="/en-US/docs/Tools/Network_Monitor">Monitor de red</a> en las herramientas del desarrollador de Firefox.</p> +</div> + +<p>Los navegadores más antiguos que no soportan estas características solo las ignorarán y seguirán adelante con la carga de la imagen referenciada en el atributo {{htmlattrxref("src", "img")}} como lo hacen habitualmente.</p> + +<div class="note"> +<p><strong>Nota</strong>: En el {{htmlelement("head")}} del documento usted hallará la línea <code><meta name="viewport" content="width=device-width"></code>: esto fuerza a los dispositivos móviles a adoptar su ancho real de ventana para cargar las páginas web (algunos navegadores móviles mienten sobre el ancho de su ventana gráfica y, en su lugar, cargan páginas con un ancho de ventana más grande y luego reducen la página cargada, lo que no es muy útil para imágenes o diseño receptivos).</p> +</div> + +<h3 id="Useful_developer_tools">Useful developer tools</h3> + +<p>There are some useful <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">developer tools</a> in browsers to help with working out the necessary slot widths, etc, that you need to use. When I was working them out, I first loaded up the non-responsive version of my example (<code>not-responsive.html</code>), then went into <a href="/en-US/docs/Tools/Responsive_Design_Mode">Responsive Design View</a> (<em>Tools > Web Developer > Responsive Design View</em>), which allows you to look at your web page layouts as if they were being viewed through a variety of different device screen sizes.</p> + +<p>I set the viewport width to 320px then 480px; for each one I went into the <a href="/en-US/docs/Tools/Page_Inspector">DOM Inspector</a>, clicked on the {{htmlelement("img")}} element we are interested in, then looked at its size in the Box Model view tab on the right hand side of the display. This should give you the inherent image widths you need.</p> + +<p><img alt="A screenshot of the firefox devtools with an image element highlighted in the dom, showing its dimensions as 440 by 293 pixels." src="https://mdn.mozillademos.org/files/12932/box-model-devtools.png" style="display: block; height: 845px; margin: 0px auto; width: 480px;"></p> + +<p>Next, you can check whether the <code>srcset</code> is working by setting the viewport width to what you want (set it to a narrow width, for example), opening the Network Inspector (<em>Tools > Web Developer > Network</em>), then reloading the page. This should give you a list of the assets that were downloaded to make up the webpage, and here you can check which image file was chosen for download.</p> + +<p><img alt="a screenshot of the network inspector in firefox devtools, showing that the HTML for the page has been downloaded, along with three images, which include the two 800 wide versions of the responsive images" src="https://mdn.mozillademos.org/files/12934/network-devtools.png" style="display: block; height: 630px; margin: 0px auto; width: 600px;"></p> + +<h3 id="Resolution_switching_Same_size_different_resolutions">Resolution switching: Same size, different resolutions</h3> + +<p>If you're supporting multiple display resolutions, but everyone sees your image at the same real-world size on the screen, you can allow the browser to choose an appropriate resolution image by using <code>srcset</code> with x-descriptors and without <code>sizes</code> — a somewhat easier syntax! You can find an example of what this looks like in <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/srcset-resolutions.html">srcset-resolutions.html</a> (see also <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/responsive-images/srcset-resolutions.html">the source code</a>):</p> + +<pre class="brush: html notranslate"><img srcset="elva-fairy-320w.jpg, + elva-fairy-480w.jpg 1.5x, + elva-fairy-640w.jpg 2x" + src="elva-fairy-640w.jpg" alt="Elva dressed as a fairy"> +</pre> + +<p><img alt="A picture of a little girl dressed up as a fairy, with an old camera film effect applied to the image" src="https://mdn.mozillademos.org/files/12942/resolution-example.png" style="display: block; height: 425px; margin: 0px auto; width: 480px;">In this example, the following CSS is applied to the image so that it will have a width of 320 pixels on the screen (also called CSS pixels):</p> + +<pre class="brush: css notranslate">img { + width: 320px; +}</pre> + +<p>In this case, <code>sizes</code> is not needed — the browser simply works out what resolution the display is that it is being shown on, and serves the most appropriate image referenced in the <code>srcset</code>. So if the device accessing the page has a standard/low resolution display, with one device pixel representing each CSS pixel, the <code>elva-fairy-320w.jpg</code> image will be loaded (the 1x is implied, so you don't need to include it.) If the device has a high resolution of two device pixels per CSS pixel or more, the <code>elva-fairy-640w.jpg</code> image will be loaded. The 640px image is 93KB, whereas the 320px image is only 39KB.</p> + +<h3 id="Art_direction">Art direction</h3> + +<p>To recap, the <strong>art direction problem</strong> involves wanting to change the image displayed to suit different image display sizes. For example, if a large landscape shot with a person in the middle is shown on a website when viewed on a desktop browser, then shrunk down when the website is viewed on a mobile browser, it will look bad as the person will be really tiny and hard to see. It would probably be better to show a smaller, portrait image on mobile, which shows the person zoomed in. The {{htmlelement("picture")}} element allows us to implement just this kind of solution.</p> + +<p>Returning to our original <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/not-responsive.html">not-responsive.html</a> example, we have an image that badly needs art direction:</p> + +<pre class="brush: html notranslate"><img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"></pre> + +<p>Let's fix this, with {{htmlelement("picture")}}! Like <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content"><code><video></code> and <code><audio></code></a>, The <code><picture></code> element is a wrapper containing several {{htmlelement("source")}} elements that provide several different sources for the browser to choose between, followed by the all-important {{htmlelement("img")}} element. The code in <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/responsive-images/responsive.html">responsive.html</a> looks like so:</p> + +<pre class="brush: html notranslate"><picture> + <source media="(max-width: 799px)" srcset="elva-480w-close-portrait.jpg"> + <source media="(min-width: 800px)" srcset="elva-800w.jpg"> + <img src="elva-800w.jpg" alt="Chris standing up holding his daughter Elva"> +</picture> +</pre> + +<ul> + <li>The <code><source></code> elements include a <code>media</code> attribute that contains a media condition — as with the first <code>srcset</code> example, these conditions are tests that decide which image is shown — the first one that returns true will be displayed. In this case, If the viewport width is 799px wide or less, the first <code><source></code> element's image will be displayed. If the viewport width is 800px or more, it'll be the second one.</li> + <li>The <code>srcset</code> attributes contain the path to the image to display. Note that just as we saw with <code><img></code> above, <code><source></code> can take a <code>srcset</code> attribute with multiple images referenced, and a <code>sizes</code> attribute too. So you could offer multiple images via a <code><picture></code> element, but then also offer multiple resolutions of each one too. Realistically, you probably won't want to do this kind of thing very often.</li> + <li>In all cases, you must provide an <code><img></code> element, with <code>src</code> and <code>alt</code>, right before <code></picture></code>, otherwise no images will appear. This provides a default case that will apply when none of the media conditions return true (you could actually remove the second <code><source></code> element in this example), and a fallback for browsers that don't support the <code><picture></code> element.</li> +</ul> + +<p>This code allows us to display a suitable image on both wide screen and narrow screen displays, as shown below:</p> + +<p><img alt="Our example site as viewed on a wide screen - here the first image works ok, as it is big enough to see the detail in the center." src="https://mdn.mozillademos.org/files/12940/picture-element-wide.png" style="display: block; height: 554px; margin: 0px auto; width: 700px;"><img alt="Our example site as viewed on a narrow screen with the picture element used to switch the first image to a portrait close up of the detail, making it a lot more useful on a narrow screen" src="https://mdn.mozillademos.org/files/12938/picture-element-narrow.png" style="display: block; height: 710px; margin: 0px auto; width: 320px;"></p> + +<div class="note"> +<p><strong>Note</strong>: You should use the <code>media</code> attribute only in art direction scenarios; when you do use <code>media</code>, don't also offer media conditions within the <code>sizes</code> attribute.</p> +</div> + +<h3 id="¿Por_qué_no_podemos_usar_simplemente_CSS_o_Javascript">¿Por qué no podemos usar, simplemente, CSS o Javascript?</h3> + +<p>Cuando el navegador comienza a cargar una página, empieza a descargar (precargar) cualquier imagen before the main parser has started to load and interpret the page's CSS and JavaScript. This is a useful technique, which on average has shaved 20% off page load times. However, it is not helpful for responsive images, hence the need to implement solutions like <code>srcset</code>. You couldn't for example load the {{htmlelement("img")}} element, then detect the viewport width with JavaScript and dynamically change the source image to a smaller one if desired. By then, the original image would already have been loaded, and you would load the small image as well, which is even worse in responsive image terms.</p> + +<ul> +</ul> + +<h3 id="Use_modern_image_formats_boldly">Use modern image formats boldly</h3> + +<p>There are several exciting new image formats (such as WebP and JPEG-2000) that can maintain a low file size and high quality at the same time. However, browser support is spotty.</p> + +<p><code><picture></code> lets us continue catering to older browsers. You can supply MIME types inside <code>type</code> attributes so the browser can immediately reject unsupported file types:</p> + +<pre class="brush: html notranslate"><picture> + <source type="image/svg+xml" srcset="pyramid.svg"> + <source type="image/webp" srcset="pyramid.webp"> + <img src="pyramid.png" alt="regular pyramid built from four equilateral triangles"> +</picture> +</pre> + +<ul> + <li>No uses el atributo <code>media</code>, unless you also need art direction.</li> + <li>En un elemento <code><source></code> , solo puedes enlazar a imágenes del tipo que has declarado en <code>type</code>.</li> + <li>Al igual que antes, puedes usar sin ningún problema listas separadas con comas tanto en <code>srcset</code> , como en <code>sizes</code>, así como lo necesites.</li> +</ul> + +<h2 id="Aprendizaje_activo_Implementando_sus_propias_imágenes_adaptables">Aprendizaje activo: Implementando sus propias imágenes adaptables</h2> + +<p>For this active learning, we're expecting you to be brave and go it alone ... mostly. We want you to implement your own suitable art directed narrow screen/wide screen shot using <code><picture></code>, and a resolution switching example that uses <code>srcset</code>.</p> + +<ol> + <li>Write some simple HTML to contain your code (use <code>not-responsive.html</code> as a starting point, if you like)</li> + <li>Find a nice wide screen landscape image with some kind of detail contained in it somewhere. Create a web-sized version of it using a graphics editor, then crop it to show a smaller part that zooms in on the detail, and create a second image (about 480px wide is good for this.)</li> + <li>Use the <code><picture></code> element to implement an art direction picture switcher!</li> + <li>Create multiple image files of different sizes, each showing the same picture.</li> + <li>Use <code>srcset</code>/<code>size</code> to create a resolution switcher example, either to serve the same size image at different resolutions, or different image sizes at different viewport widths.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: Use the browser devtools to help work out what sizes you need, as mentioned above.</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p>That's a wrap for responsive images — we hope you enjoyed playing with these new techniques. As a recap, there are two distinct problems we've been discussing here:</p> + +<ul> + <li><strong>Art direction</strong>: The problem whereby you want to serve cropped images for different layouts — for example a landscape image showing a full scene for a desktop layout, and a portrait image showing the main subject zoomed in close for a mobile layout. This can be solved using the {{htmlelement("picture")}} element.</li> + <li><strong>Resolution switching</strong>: The problem whereby you want to serve smaller image files to narrow screen devices, as they don't need huge images like desktop displays do — and also optionally that you want to serve different resolution images to high density/low density screens. This can be solved using <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">vector graphics</a> (SVG images), and the {{htmlattrxref("srcset", "img")}} and {{htmlattrxref("sizes", "img")}} attributes.</li> +</ul> + +<p>This also draws to a close the entire <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding">Multimedia and embedding</a> module! The only thing to do now before moving on is to try our multimedia assessment, and see how you get on. Have fun.</p> + +<h2 id="Vea_también">Vea también</h2> + +<ul> + <li><a href="http://blog.cloudfour.com/responsive-images-101-definitions">Excelente introducción de Jason Grigsby excellent a las imágenes adaptables</a></li> + <li><a href="https://css-tricks.com/responsive-images-youre-just-changing-resolutions-use-srcset/">Imagenes adaptables: Si solo está cambiando resoluciones , use srcset</a> — incluye más explicaciones sobre como el navegador resuelve qué imagen utilizar</li> + <li>{{htmlelement("img")}}</li> + <li>{{htmlelement("picture")}}</li> + <li>{{htmlelement("source")}}</li> +</ul> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web", "Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<div> +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imágenes in HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Contenido de audio y video</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">De <object> a <iframe> — otras tecnologías de i</a>ncrustación</li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Agregando gráficos de vector a la Web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Imagenes adaptables</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Página de bienvenida de Mozilla</a></li> +</ul> +</div> + +<p><iframe></iframe><hv-copy-modal></hv-copy-modal></p> diff --git a/files/es/learn/html/multimedia_and_embedding/video_and_audio_content/index.html b/files/es/learn/html/multimedia_and_embedding/video_and_audio_content/index.html new file mode 100644 index 0000000000..e9b5571e23 --- /dev/null +++ b/files/es/learn/html/multimedia_and_embedding/video_and_audio_content/index.html @@ -0,0 +1,319 @@ +--- +title: Video and audio content +slug: Learn/HTML/Multimedia_and_embedding/Video_and_audio_content +translation_of: Learn/HTML/Multimedia_and_embedding/Video_and_audio_content +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Images_in_HTML", "Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding")}}</div> + +<p class="summary">Ahora que estamos cómodos añadiendo imágenes simples a una página web, el siguiente paso será empezar a agregar reproductores de audio y video a tu documento HTML. En este artículo veremos cómo hacerlo con los elementos {{htmlelement("video")}} y {{htmlelement("audio")}}; luego terminaremos viendo como agregar subtítulos a nuestros videos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Conocimientos básicos de computación, <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Installing_basic_software">programas básicos instalados</a>, conocimiento básico de <a href="https://developer.mozilla.org/en-US/Learn/Getting_started_with_the_web/Dealing_with_files">trabajo con archivos</a>, familiaridad con los fundamentos de HTML (como está cubierto en <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/Getting_started">Empezando con HTML</a>) e <a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Imágenes en HTML</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender como incrustar contenido de audio y video en una página web, y agregar subtítulos a los videos.</td> + </tr> + </tbody> +</table> + +<h2 id="Audio_y_video_en_la_web">Audio y video en la web</h2> + +<p>Los desarrolladores web han querido usar audio y video en la web por mucho tiempo, desde comienzos del 2000 cuando empezamos a tener un ancho de banda suficientemente rápido para soportar cualquier tipo de video (los archivos de video son mucho más grandes que texto o imágenes). En los inicios, las tecnologías web nativas como HTML no tenían el soporte para incrustar audio y video en la Web, tecnologías privadas (o basadas en plugins) como <a href="https://en.wikipedia.org/wiki/Adobe_Flash">Flash</a> (y después, <a href="https://en.wikipedia.org/wiki/Microsoft_Silverlight">Silverlight</a>) se convirtieron populares para manipular este tipo de contenido. Este tipo de tecnología funcionó bien, pero tenía ciertos problemas, incluídos el no trabajar bien con las características de HTML/CSS, problemas de seguridad y problemas de accesibilidad.</p> + +<p>Una solución nativa podría resolver mucho de esto si es implementado correctamente. Afortunadamente, unos pocos años después la especificación {{glossary("HTML5")}} tenía tales características agregadas, con los elementos {{htmlelement("video")}} y {{htmlelement("audio")}}, y algo nuevo {{Glossary("JavaScript")}} {{Glossary("API","APIs")}} para controlar estos. No veremos Javascript aquí — solo los fundamentos básicos que se pueden lograr con HTML.</p> + +<p>No te enseñaremos como crear archivos de audio y video — eso requiere un conocimiento completamente diferente. Por el contrario, te proporcionamos <a href="https://github.com/mdn/learning-area/tree/master/html/multimedia-and-embedding/video-and-audio-content">archivos de audio y video de muestra con códigos de ejemplo</a> para que tu mismo experimentes, en caso de que no puedas conseguirlos por ti mismo.</p> + +<div class="note"> +<p><strong>Observación</strong>: Antes de empezar, también deberías saber que hay un puñado de OVPs (proveedores de video online) como <a href="https://www.youtube.com/">YouTube</a>, <a href="http://www.dailymotion.com">Dailymotion</a> y <a href="https://vimeo.com/">Vimeo</a>, y proveedores de audio como <a href="https://soundcloud.com/">Soundcloud</a>. Tales compañías ofrecen una conveniente fácil forma de hospedar y consumir videos, y que no tienes que preocuparte sobre el enorme ancho de banda que se consume. Los OVPs normalmente usan código prefabricado para incrustar video/audio en tus sitios web; si usas ese camino, puedes evitar algunas dificultates que discutimos en este artículo. Discutiremos este tipo de servicios un poco más en el siguiente artículo.</p> +</div> + +<h3 id="El_elemento_<video>">El elemento <video></h3> + +<p>El elemento {{htmlelement("video")}} nos permite incrustar video fácilmente. Un ejemplo muy simple luce como lo siguiente:</p> + +<pre class="brush: html notranslate"><video src="rabbit320.webm" controls> + <p>Tu navegador no soporta HTML5 video. Aquí está el <a href="rabbit320.webm">enlace del video</a>.</p> +</video></pre> + +<p>Las características a notar son:</p> + +<dl> + <dt>{{htmlattrxref("src","video")}}</dt> + <dd>De la misma manera que para el elemento {{htmlelement("img")}}, el atributo <code>src</code> (source) contiene una ruta al video que deseas incrustar. Funciona de la misma manera.</dd> + <dt>{{htmlattrxref("controls","video")}}</dt> + <dd>Los usuarios deben ser capaces de controlar la reproducción de video y audio (esto es especialmente crítico en personas que padecen <a href="https://en.wikipedia.org/wiki/Epilepsy#Epidemiology">epilepsia</a>). Se debe utilizar el atributo <code>controls</code> para incluir la interfaz de control del browser, o construir la nuestra utilizando la <a href="/en-US/docs/Web/API/HTMLMediaElement">JavaScript API</a> apropiada. Como mínimo la interfaz debe incluir una manera de empezar y terminar la reproducción, y ajustar el volumen.</dd> + <dt>El párrafo dentro de la etiqueta <code><video></code></dt> + <dd>Se lo llama <strong>fallback content</strong> (contenido de reserva) — y será mostrado si el browser desde el que se está accediendo a la página no soporta el elemento <code><video></code>, permitiéndonos proveer un fallback para browsers más antiguos. Puede ser de la manera que se quiera; en este caso proporcionamos un link directo al archivo de video, por lo que el usuario puede al menos acceder de alguna manera, independientemente del browser que esté usando.</dd> +</dl> + +<p>El video incrustado se verá así:</p> + +<p><img alt="A simple video player showing a video of a small white rabbit" src="https://mdn.mozillademos.org/files/12794/simple-video.png" style="display: block; height: 592px; margin: 0px auto; width: 589px;"></p> + +<p>Puedes <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/simple-video.html">probar el ejemplo</a> aquí (también el <a href="https://github.com/mdn/learning-area/blob/master/html/multimedia-and-embedding/video-and-audio-content/simple-video.html">código fuente</a>).</p> + +<h3 id="Uso_de_formatos_múltiples_para_mejorar_la_compatibilidad">Uso de formatos múltiples para mejorar la compatibilidad</h3> + +<p>Hay un problema con el ejemplo de arriba, que quizás hayas notado si trataste de acceder al <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/simple-video.html">ejemplo en línea</a> con un navegador como Safari o Internet Explorer. ¡El video no funciona! Esto es porque diferentes navegadores soportan diferentes formatos de video (y audio).</p> + +<h4 id="Contenidos_de_un_archivo_de_medios">Contenidos de un archivo de medios</h4> + +<p>Repasemos la terminología rápidamente. Formatos como MP3, MP4 y WebM son llamados <strong>formatos contenedores</strong>. Estos contienen diferentes partes que componen toda la canción o video — como una pista de audio y una pista de video (en el caso del video), y metadatos para describir los contenidos que se presentan, qué codecs se usan para codificar sus canales, etcétera.</p> + +<p>Un archivo WebM contiene una película que tiene una pista principal de video y otra pista con un ángulo alternativo, junto con audio en inglés y español, además de una pista con comentarios en inglés, lo que puede ser conceptualizado en el siguiente diagrama. También se incluyeron pistas de texto que contienen los subtítulos de la película en inglés, español y para el comentario.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16898/ContainersAndTracks.svg" style="height: 607px; width: 823px;"></p> + +<p>Las pistas de audio y video dentro del contenedor mantienen los datos en un formato adecuado para el codec usado para codificar ese medio. Se usan diferentes formatos para pistas de audio versus de video. Cada pista de audio es codificada usando un codec de audio mientras que las pistas de video son codificadas (como probablemente ya has adivinado) usando un codec de video. Así como hemos hablado previamente, diferentes navegadores soportan diferentras formatos de audio y video, y diferentes formatos contenedores (como MP3, MP4 y WebM, que pueden contener diferentes tipos de video y audio).</p> + +<p>Por ejemplo:</p> + +<ul> + <li>Un WebM usualmente contiene paquetes de Ogg Vorbis audio con VP8/VP9 video. Soportado principalmente por Firefox y Chrome.</li> + <li>Un MP4 contiene a menudo paquetes AAC o audio MP3 con videos H.264. Principalmente soportados en Internet Explorer y Safari.</li> + <li>El antiguo contenedor Ogg suele usar audio Ogg Vorbis y video Ogg Theora. Es principalmente soportado por Firefox y Chrome, pero básicamente ha sido reemplazado por el formato WebM de mejor calidad.</li> +</ul> + +<p>Un reproductor de audio tenderá a reproducir directamente un track de audio. Por ejemplo un archivo MP3 u Ogg. No necesitan contenedores.</p> + +<div class="note"> +<p><strong>Nota</strong>: No es tan simple como se ve en nuestra <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats#Browser_compatibility"> tabla de compatibilidad de codecs audio-video</a>. Además, muchos browsers de plataformas móviles pueden reproducir un formato no soportado entregándoselo al reproductor multimedia del sistema subyacente para que lo reproduzca. Pero esto servirá por ahora.</p> +</div> + +<p>Los formatos anteriores existen para comprimir los archivos de audio y video volviéndolos manejables (el tamaño sin comprimir es muy grande). Los browsers contienen diferentes <strong>{{Glossary("Codec","Codecs")}}</strong>, como Vorbis o H.264, los cuales son usados para convertir el sonido y video comprimidos en binario y viceversa. Pero desafortunadamente, como indicamos antes, no todos los browsers soportan los mismos codecs, por lo tanto, habrá que proveer varios archivos para cada producción multimedia. Si te falta el codec correcto para decodificar el medio, simplemente no se reproducirá.</p> + +<div class="note"> +<p><strong>Nota:</strong> Debes estar preguntándote por qué sucede esto. El <strong>MP3 </strong> (para audio) y el <strong>MP4/H.264</strong> (para video) son ampliamente compatibles y de buena calidad, sin embargo, también están patentados — sus patentes cubren MP3 al menos hasta 2017 y a H.264 hasta 2027, lo que significa que los browsers que no tienen la patente tienen que pagar grandes sumas de dinero para soportar estos formatos. Además, mucha gente no permite el software con restricciones, por estar a favor de formatos abiertos. Por todo esto es que tenemos que proveer múltiples formatos para los diferentes browsers.</p> +</div> + +<p>Está bien, ¿pero cómo lo hacemos? Miremos el siguiente <a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats.html">ejemplo actualizado (</a><a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-video-formats.html">pruébalo en vivo aquí</a>), o acá:</p> + +<pre class="brush: html notranslate"><video controls> + <source src="rabbit320.mp4" type="video/mp4"> + <source src="rabbit320.webm" type="video/webm"> + <p>Su navegador no soporta video HTML5. Aquí hay un <a href="rabbit320.mp4">enlace al video</a>.</p> +</video></pre> + +<p>Tomamos el atributo <code>src</code> del tag <code><video></code> y en su lugar incluimos elementos separados {{htmlelement("source")}} que apuntan a sus propias fuentes. En este caso el browser irá a los elementos <code><source> y </code>reproducirá el primero de los elementos que el codec soporte. Incluir fuentes WebM y MP4 debería bastar para reproducir el video en la mayoría de los browsers en estos días.</p> + +<p>Cada elemento <code><source></code> tambien tiene un atributo <code>type</code> . Esto es opcional, pero se recomienda que se incluyan, ya que contienen {{glossary("MIME type","MIME types")}} de los archivos de vídeo y los navegadores pueden leerlos y omitir inmediatamente los vídeos que no tienen. Si no estan incluidos, los navegadores cargarán e intentarán reproducir cada archivo hasta que encuentren uno que funcione, lo que llevará aún más tiempo y recursos.</p> + +<div class="note"> +<p><strong>Note</strong>: Nuestro <a href="/en-US/docs/Web/HTML/Supported_media_formats">articulo sobre soporte de formatos multimedia</a> contiene algunos de los habituales {{glossary("MIME type","MIME types")}}.</p> +</div> + +<h3 id="Otras_características_de_la_etiqueta_<video>">Otras características de la etiqueta <video></h3> + +<p>Hay varias otras características que puede incluir en un vídeo HTML5. Eche un vistazo a nuestro tercer ejemplo, a continuación.</p> + +<pre class="brush: html notranslate"><video controls width="400" height="400" + autoplay loop muted + poster="poster.png"> + <source src="rabbit320.mp4" type="video/mp4"> + <source src="rabbit320.webm" type="video/webm"> + <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p> +</video> +</pre> + +<p>Esto nos dará un resultado que se parece a esto:</p> + +<p><img alt="A video player showing a poster image before it plays. The poster image says HTML5 video example, OMG hell yeah!" src="https://mdn.mozillademos.org/files/12796/extra-video-features.png" style="display: block; height: 731px; margin: 0px auto; width: 653px;">Las nuevas características son:</p> + +<dl> + <dt>{{htmlattrxref("width","video")}} y {{htmlattrxref("height","video")}}</dt> + <dd>Puede controlar el tamanño con estos atributos o con {{Glossary("CSS")}}. En ambos casos, los vídeos mantienen su relación <strong>anchura - altura nativa</strong>. Si la relación de aspecto no se mantiene con los tamañis establecidos, el vídeo crecerá para rellenar el espacio horizontalmente y el el espacio sin rellenar sólo recibirá un color de fondo sólido de forma predeterminada.</dd> + <dt>{{htmlattrxref("autoplay","video")}}</dt> + <dd>Hace que el audio o el vídeo empiece a reproducirse de inmediato, mientras se carga el resto de la página. Le aconsejamos que no utilice vídeo (o audio) de reproducción automática en sus sitios, ya que los usuarios pueden encontralo molesto.</dd> + <dt>{{htmlattrxref("loop","video")}}</dt> + <dd>Hace que el vídeo (o audio) comience a reproducirse cada vez que finaliza.Esto puede en ocasiones resultar molesto, así que utilizalo solo si es realmente necesario.</dd> + <dt>{{htmlattrxref("muted","video")}}</dt> + <dd>Hace que los medios se reproduzcan con el sonido apagado de forma predeterminada.</dd> + <dt>{{htmlattrxref("poster","video")}}</dt> + <dd>La URL de una imagen que se mostrará antes de reproducir el vídeo. Está destinado a ser utilizado para una pantalla de presentación o pantalla publicitaria (miniatura del vídeo).</dd> + <dt>{{htmlattrxref("preload","video")}}</dt> + <dd> + <p>Se utiliza para almacenar en búfer archivos grandes; Puede tomar uno de estos tres valores:</p> + + <ul> + <li><code>"none"</code> no almacena el archivo en el búfer</li> + <li><code>"auto"</code> almacena el archivo multimedia</li> + <li><code>"metadata"</code> almacena solo los metadatos del archivo</li> + </ul> + </dd> +</dl> + +<p>Puedes encontrar el ejemplo anterior disponible en <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/extra-video-features.html">play live on Github</a> (también <a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/video-and-audio-content/extra-video-features.html">see the source code</a>.) Tenga en cuenta que hemos incluido el atributo <code>autoplay</code> en la versión en vivo — Si el vídeo comienza a reproducirse tan pronto como se cargue la página no podrá ver la miniatura!</p> + +<h3 id="El_elemento_<audio>">El elemento <audio></h3> + +<p>El elemento {{htmlelement("audio")}} funciona exactamente de la misma forma que el elemento {{htmlelement("video")}}, con algunas pequeñas diferencias como se describe a continuación. Un ejemplo típico podría ser así:</p> + +<pre class="brush: html notranslate"><audio controls> + <source src="viper.mp3" type="audio/mp3"> + <source src="viper.ogg" type="audio/ogg"> + <p>Your browser doesn't support HTML5 audio. Here is a <a href="viper.mp3">link to the audio</a> instead.</p> +</audio></pre> + +<p>Esto produce algo como lo siguiente en un navegador:</p> + +<p><img alt="A simple audio player with a play button, timer, volume control, and progress bar" src="https://mdn.mozillademos.org/files/12798/audio-player.png" style="display: block; height: 413px; margin: 0px auto; width: 626px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes <a href="http://mdn.github.io/learning-area/html/multimedia-and-embedding/video-and-audio-content/multiple-audio-formats.html">reproducir este ejemplo de audio</a> en Github (también, puedes ver el <a href="https://github.com/mdn/learning-area/blob/gh-pages/html/multimedia-and-embedding/video-and-audio-content/multiple-audio-formats.html">código fuente del reproductor de audio</a>.)</p> +</div> + +<p>Esto ocupa menos espacio que un reproductor de video, ya que no hay un componente visual; solo necesita mostrar los controles para reproducir el audio. Otras diferencias con respecto al video HTML5 son las siguentes:</p> + +<ul> + <li>El elemento {{htmlelement("audio")}} no soporta los atributos <code>width</code>/<code>height</code> — de nuevo, no hay un componente visual,por no que no hay nada a lo que asignar un width o height (ancho o alto).</li> + <li>Tampoco es compatible con el atributo <code>poster</code> — de nuevo , no hay componente visual.</li> +</ul> + +<p>Además de esto, <code><audio></code> admite las mismas características que <code><video></code> — revisa las secciones anteriores para obtener más información sobre ellas.</p> + +<h3 id="Reinicio_de_la_reproducción_multimedia">Reinicio de la reproducción multimedia</h3> + +<p>En cualquier momento, puede restablecer los medios al principio—incluyendo el proceso de selección de la mejor fuente de medios, si se especifica más de una usando {{HTMLElement("source")}} elementos—llamando al elemento {{domxref("HTMLMediaElement.load", "load()")}} method:</p> + +<pre class="brush: js notranslate">var mediaElem = document.getElementById("my-media-element"); +mediaElem.load();</pre> + +<h3 id="Detecting_track_addition_and_removal">Detecting track addition and removal</h3> + +<p>You can monitor the track lists within a media element to detect when tracks are added to or removed from the element's media. For example, you can watch for the {{event("addtrack")}} event being fired on the associated {{domxref("AudioTrackList")}} object (retrieved via {{domxref("HTMLMediaElement.audioTracks")}}) to be informed when audio tracks are added to the media:</p> + +<pre class="brush: js notranslate">var mediaElem = document.querySelector("video"); +mediaElem.audioTracks.onaddtrack = function(event) { + audioTrackAdded(event.track); +} +</pre> + +<p>Encontraras mas documentacion acerca de esto en nuestra {{domxref("TrackEvent")}} documentacion.</p> + +<h2 id="Displaying_video_text_tracks">Displaying video text tracks</h2> + +<p>Now we'll discuss a slightly more advanced concept that is really useful to know about. Many people can't or don't want to hear the audio/video content they find on the Web, at least at certain times. For example:</p> + +<ul> + <li>Many people have auditory impairments (more commonly known as hard of hearing, or deaf) so can't hear the audio.</li> + <li>Others may not be able to hear the audio because they are in noisy environments (like a crowded bar when a sports game is being shown) or might not want to disturb others if they are in a quiet place (like a library.)</li> + <li>People who don't speak the language of the video might want a text transcript or even translation to help them understand the media content.</li> +</ul> + +<p>Wouldn't it be nice to be able to provide these people with a transcript of the words being spoken in the audio/video? Well, thanks to HTML5 video you can, with the <a href="/en-US/docs/Web/API/Web_Video_Text_Tracks_Format">WebVTT</a> format and the {{htmlelement("track")}} element.</p> + +<div class="note"> +<p><strong>Note</strong>: "Transcribe" means "to write down spoken words as text." The resulting text is a "transcript."</p> +</div> + +<p>WebVTT is a format for writing text files containing multiple strings of text along with metadata such as what time in the video you want each text string to be displayed, and even limited styling/positioning information. These text strings are called <strong>cues</strong>, and you can display different types for different purposes, the most common being:</p> + +<dl> + <dt>subtitles</dt> + <dd>Translations of foreign material, for people who don't understand the words spoken in the audio.</dd> + <dt>captions</dt> + <dd>Synchronized transcriptions of dialog or descriptions of significant sounds, to let people who can't hear the audio understand what is going on.</dd> + <dt>timed descriptions</dt> + <dd>Text for conversion into audio, to serve people with visual impairments.</dd> +</dl> + +<p>A typical WebVTT file will look something like this:</p> + +<pre class="eval line-numbers language-html notranslate"><code class="language-html">WEBVTT + +1 +00:00:22.230 --> 00:00:24.606 +This is the first subtitle. + +2 +00:00:30.739 --> 00:00:34.074 +This is the second. + + ...</code> +</pre> + +<p>To get this displayed along with the HTML media playback, you need to:</p> + +<ol> + <li>Save it as a <code>.vtt</code> file in a sensible place.</li> + <li>Link to the <code>.vtt</code> file with the {{htmlelement("track")}} element. <code><track></code> should be placed within <code><audio></code> or <code><video></code>, but after all <code><source></code> elements. Use the {{htmlattrxref("kind","track")}} attribute to specify whether the cues are <code>subtitles</code>, <code>captions</code>, or <code>descriptions</code>. Further, use {{htmlattrxref("srclang","track")}} to tell the browser what language you have written the subtitles in.</li> +</ol> + +<p>Here's an example:</p> + +<pre class="brush: html notranslate"><video controls> + <source src="example.mp4" type="video/mp4"> + <source src="example.webm" type="video/webm"> + <track kind="subtitles" src="subtitles_en.vtt" srclang="en"> +</video></pre> + +<p>This will result in a video that has subtitles displayed, kind of like this:</p> + +<p><img alt='Video player with stand controls such as play, stop, volume, and captions on and off. The video playing shows a scene of a man holding a spear-like weapon, and a caption reads "Esta hoja tiene pasado oscuro."' src="https://mdn.mozillademos.org/files/7887/video-player-with-captions.png" style="display: block; height: 365px; margin: 0px auto; width: 593px;"></p> + +<p>For more details, please read <a href="/en-US/Apps/Build/Audio_and_video_delivery/Adding_captions_and_subtitles_to_HTML5_video">Adding captions and subtitles to HTML5 video</a>. You can <a href="http://iandevlin.github.io/mdn/video-player-with-captions/">find the example</a> that goes along with this article on Github, written by Ian Devlin (see the <a href="https://github.com/iandevlin/iandevlin.github.io/tree/master/mdn/video-player-with-captions">source code</a> too.) This example uses some JavaScript to allow users to choose between different subtitles. Note that to turn the subtitles on, you need to press the "CC" button and select an option — English, Deutsch, or Español. </p> + +<div class="note"> +<p><strong>Note</strong>: Text tracks also help you with {{glossary("SEO")}}, since search engines especially thrive on text. Text tracks even allow search engines to link directly to a spot partway through the video.</p> +</div> + +<h3 id="Active_learning_Embedding_your_own_audio_and_video">Active learning: Embedding your own audio and video</h3> + +<p>For this active learning, we'd (ideally) like you to go out into the world and record some of your own video and audio — most phones these days allow you to record audio and video very easily, and provided you can transfer it on to your computer, you can use it. You may have to do some conversion to end up with a WebM and MP4 in the case of video, and an MP3 and Ogg in the case of audio, but there are enough programs out there to allow you to do this without too much trouble, such as <a href="http://www.mirovideoconverter.com/">Miro Video Converter</a> and <a href="https://sourceforge.net/projects/audacity/">Audacity</a>. We'd like you to have a go!</p> + +<p>If you are unable to source any video or audio, then you can feel free to use our <a href="https://github.com/mdn/learning-area/tree/master/html/multimedia-and-embedding/video-and-audio-content">sample audio and video files</a> to carry out this exercise. You can also use our sample code for reference.</p> + +<p>We would like you to:</p> + +<ol> + <li>Save your audio and video files in a new directory on your computer.</li> + <li>Create a new HTML file in the same directory, called <code>index.html</code>.</li> + <li>Add <code><audio></code> and <code><video></code> elements to the page; make them display the default browser controls.</li> + <li>Give both of them <code><source></code> elements so that browsers will find the audio format they support best and load it. These should include <code>type</code> attributes.</li> + <li>Give the <code><video></code> element a poster that will be displayed before the video starts to be played. Have fun creating your own poster graphic.</li> +</ol> + +<p>For an added bonus, you could try researching text tracks, and work out how to add some captions to your video.</p> + +<h2 id="Summary">Summary</h2> + +<p>And that's a wrap; we hope you had fun playing with video and audio in web pages! In the next article, we'll look at other ways of embedding content on the Web, using technologies like {{htmlelement("iframe")}} and {{htmlelement("object")}}.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{htmlelement("audio")}}</li> + <li>{{htmlelement("video")}}</li> + <li>{{htmlelement("source")}}</li> + <li>{{htmlelement("track")}}</li> + <li><a href="/en-US/Apps/Build/Audio_and_video_delivery/Adding_captions_and_subtitles_to_HTML5_video">Adding captions and subtitles to HTML5 video</a></li> + <li><a href="/en-US/docs/Web/Apps/Fundamentals/Audio_and_video_delivery">Audio and Video delivery</a>: A LOT of detail about putting audio and video onto web pages using HTML and JavaScript.</li> + <li><a href="/en-US/docs/Web/Apps/Fundamentals/Audio_and_video_manipulation">Audio and Video manipulation</a>: A LOT of detail about manipulating audio and video using JavaScript (for example adding filters.)</li> + <li>Automated options to <a href="http://www.inwhatlanguage.com/blog/translate-video-audio/">translate multimedia</a>.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/HTML/Multimedia_and_embedding/Images_in_HTML", "Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies", "Learn/HTML/Multimedia_and_embedding")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Images_in_HTML">Images in HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Video_and_audio_content">Video and audio content</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Other_embedding_technologies">From <object> to <iframe> — other embedding technologies</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Adding_vector_graphics_to_the_Web">Adding vector graphics to the Web</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Responsive_images">Responsive images</a></li> + <li><a href="/en-US/docs/Learn/HTML/Multimedia_and_embedding/Mozilla_splash_page">Mozilla splash page</a></li> +</ul> + +<dl> +</dl> + +<ul> +</ul> diff --git a/files/es/learn/html/tablas/conceptos_básicos_de_las_tablas_html/index.html b/files/es/learn/html/tablas/conceptos_básicos_de_las_tablas_html/index.html new file mode 100644 index 0000000000..7259adf427 --- /dev/null +++ b/files/es/learn/html/tablas/conceptos_básicos_de_las_tablas_html/index.html @@ -0,0 +1,563 @@ +--- +title: Conceptos básicos de las tablas HTML +slug: Learn/HTML/Tablas/Conceptos_básicos_de_las_tablas_HTML +translation_of: Learn/HTML/Tables/Basics +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}</div> + +<p class="summary">Este artículo te ayudará a comenzar con las tablas HTML. Vamos a exponer conceptos básicos como filas y celdas, encabezados, celdas que abarcan múltiples columnas y filas, y la forma de agrupar todas las celdas de una columna para aplicarles estilo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conceptos básicos de HTML (ver <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Adquirir conocimientos básicos de las tablas HTML.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_una_tabla">¿Qué es una tabla?</h2> + +<p>Una tabla es un conjunto estructurado de datos distribuidos en filas y columnas (<strong>datos tabulados</strong>). Una tabla permite buscar con rapidez y facilidad valores entre diferentes tipos de datos que indiquen algún tipo de conexión. Por ejemplo, una persona y su edad, o un día de la semana o el horario de una piscina municipal.</p> + +<p><img alt="Una tabla de datos de ejemplo que muestra los nombres y las edades de algunas personas: Chris 38, Dennis 45, Sarah 29, Karen 47." src="https://mdn.mozillademos.org/files/14583/numbers-table.png" style="display: block; height: 156px; margin: 0px auto; width: 350px;"></p> + +<p><img alt="Una tabla de datos que muestra unos horarios de clases natación" src="https://mdn.mozillademos.org/files/14587/swimming-timetable.png" style="display: block; height: 301px; margin: 0px auto; width: 794px;"></p> + +<p>Las tablas se utilizan con mucha frecuencia en la sociedad desde hace años, como lo demuestra este documento censal de los EUA de 1800:</p> + +<p><img alt="Un pergamino muy antiguo; cuesta un poco leer los datos, pero muestra con claridad que las tablas de datos ya se utilizaban en 1800." src="https://mdn.mozillademos.org/files/14585/1800-census.jpg" style="display: block; height: 505px; margin: 0px auto; width: 800px;"></p> + +<p>Por lo tanto, no es de extrañar que los creadores de HTML proporcionen un medio con el que estructurar y presentar datos en tablas en la web.</p> + +<h3 id="¿Cómo_funciona_una_tabla">¿Cómo funciona una tabla?</h3> + +<p>El aspecto básico de una tabla es que es un elemento rígido. Es fácil interpretar la información haciendo asociaciones visuales entre los encabezados de las filas y las columnas. Por ejemplo, observa la tabla siguiente y busca un gigante de gas joviano con 62 lunas. Puedes encontrar la respuesta asociando los encabezados de la fila y la columna correspondientes.</p> + +<table> + <caption>Datos sobre los planetas de nuestro sistema solar (datos planetarios tomados de la hoja técnica sobre datos planetarios de la NASA (<a href="http://nssdc.gsfc.nasa.gov/planetary/factsheet/">Nasa's Planetary Fact Sheet - Metric</a>).</caption> + <thead> + <tr> + <td colspan="2"></td> + <th scope="col">Nombre</th> + <th scope="col">Masa (10<sup>24</sup> kg)</th> + <th scope="col">Diámetro (km)</th> + <th scope="col">Densidad (kg/m<sup>3</sup>)</th> + <th scope="col">Gravedad (m/s<sup>2</sup>)</th> + <th scope="col">Duración del día (horas)</th> + <th scope="col">Distancia del Sol (10<sup>6</sup>km)</th> + <th scope="col">Temperatura media (°C)</th> + <th scope="col">Número de lunas</th> + <th scope="col">Observaciones</th> + </tr> + </thead> + <tbody> + <tr> + <th colspan="2" rowspan="4" scope="rowgroup">Planetas terrestres</th> + <th scope="row">Mercurio</th> + <td>0,330</td> + <td>4.879</td> + <td>5.427</td> + <td>3,7</td> + <td>4.222,6</td> + <td>57,9</td> + <td>167</td> + <td>0</td> + <td>El más cercano al Sol</td> + </tr> + <tr> + <th scope="row">Venus</th> + <td>4,87</td> + <td>12.104</td> + <td>5.243</td> + <td>8,9</td> + <td>2.802,0</td> + <td>108,2</td> + <td>464</td> + <td>0</td> + <td></td> + </tr> + <tr> + <th scope="row">La Tierra</th> + <td>5,97</td> + <td>12.756</td> + <td>5.514</td> + <td>9,8</td> + <td>24,0</td> + <td>149,6</td> + <td>15</td> + <td>1</td> + <td>Nuestro planeta</td> + </tr> + <tr> + <th scope="row">Marte</th> + <td>0,642</td> + <td>6.792</td> + <td>3.933</td> + <td>3,7</td> + <td>24,7</td> + <td>227,9</td> + <td>-65</td> + <td>2</td> + <td>El planeta rojo</td> + </tr> + <tr> + <th rowspan="4" scope="rowgroup">Planetas jovianos</th> + <th rowspan="2" scope="rowgroup">Los gigantes de gas</th> + <th scope="row">Júpiter</th> + <td>1.898</td> + <td>142.984</td> + <td>1.326</td> + <td>23,1</td> + <td>9,9</td> + <td>778,6</td> + <td>-110</td> + <td>67</td> + <td>El planeta más grande</td> + </tr> + <tr> + <th scope="row">Saturno</th> + <td>568</td> + <td>120.536</td> + <td>687</td> + <td>9,0</td> + <td>10,7</td> + <td>1.433,5</td> + <td>-140</td> + <td>62</td> + <td></td> + </tr> + <tr> + <th rowspan="2" scope="rowgroup">Los gigantes de hielo</th> + <th scope="row">Urano</th> + <td>86,8</td> + <td>51.118</td> + <td>1.271</td> + <td>8,7</td> + <td>17,2</td> + <td>2.872,5</td> + <td>-195</td> + <td>27</td> + <td></td> + </tr> + <tr> + <th scope="row">Neptuno</th> + <td>102</td> + <td>49.528</td> + <td>1.638</td> + <td>11,0</td> + <td>16,1</td> + <td>4.495,1</td> + <td>-200</td> + <td>14</td> + <td></td> + </tr> + <tr> + <th colspan="2" scope="rowgroup">Planetas enanos</th> + <th scope="row">Plutón</th> + <td>0,0146</td> + <td>2.370</td> + <td>2.095</td> + <td>0,7</td> + <td>153,3</td> + <td>5.906,4</td> + <td>-225</td> + <td>5</td> + <td>Desclasificado como planeta en 2006, pero aún es una <a href="http://www.usatoday.com/story/tech/2014/10/02/pluto-planet-solar-system/16578959/">cuestión polémica</a>.</td> + </tr> + </tbody> +</table> + +<p>Cuando se hace correctamente, incluso las personas ciegas pueden interpretar los datos de una tabla HTML. Una tabla HTML bien hecha debe mejorar la experiencia de los usuarios videntes e invidentes por igual.</p> + +<h3 id="Dar_estilo_a_las_tablas">Dar estilo a las tablas</h3> + +<p>También puedes <a href="https://mdn.github.io/learning-area/html/tables/assessment-finished/planets-data.html">echar un vistazo al ejemplo vivo</a> en GitHub. Observarás que la tabla que encontrarás allí tiene un aspecto más legible; esto se debe a que la tabla que ves en esta página tiene un estilo mínimo, mientras que en la de la versión de GitHub se ha aplicado un CSS más significativo.</p> + +<p>No te hagas ilusiones; para que las tablas sean efectivas en la web, debes proporcionar cierta información de estilo con <a href="/es/docs/Learn/CSS">CSS</a>, así como una buena estructura sólida con HTML. En este módulo nos centramos en la parte HTML; para averiguar sobre la parte del CSS debes visitar nuestro artículo <a href="/es/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a>.</p> + +<p>En este módulo no nos vamos a centrar en el CSS, sino que te vamos a proporcionar una hoja de estilo de CSS que dará a tus tablas algo más de legibilidad de la que se obtiene por defecto si no se proporciona ningún estilo. Puedes encontrar la hoja de estilo <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/minimal-table.css">aquí</a>, así como también una <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/blank-template.html">plantilla HTML</a> para aplicar la hoja de estilo (te darán un buen punto de partida para experimentar con las tablas HTML).</p> + +<h3 id="¿Cuándo_no_debes_usar_tablas_HTML">¿Cuándo no debes usar tablas HTML?</h3> + +<p>Las tablas HTML están pensadas para utilizarse con datos tabulados. Por desgracia, mucha gente utiliza las tablas HTML para hacer compaginaciones de páginas web. Por ejemplo, una fila para contener la cabecera, una fila para contener las columnas de contenido, una fila para contener el pie de página, etc. Puede encontrar más detalles y un ejemplo en <a href="/es/docs/Learn/Accessibility/HTML#Page_layouts">Diseños de página</a> en nuestro <a href="/es/docs/Learn/Accessibility">Módulo de aprendizaje de accesibilidad</a>. Se solía hacer este uso de las tablas porque la compatibilidad CSS entre navegadores solía ser terrible. Los diseños de tablas son mucho menos comunes hoy en día, pero aún se pueden ver en algunos rincones de la web.</p> + +<p>En resumen, es una mala idea usar tablas para el diseño en lugar de las <a href="/es/docs/Learn/CSS/CSS_layout">técnicas de diseño CSS</a>. Las razones principales son las siguientes:</p> + +<ol> + <li><strong>Las tablas de diseño reducen la accesibilidad para los usuarios con discapacidad visual</strong>: Los <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Accessibility#Screenreaders">lectores de pantalla</a> que utilizan las personas con visibilidad reducida interpretan las etiquetas de una página HTML y leen su contenido para el usuario. Puesto que las tablas no son la herramienta adecuada para el diseño y el marcado es más complejo que con las técnicas de diseño CSS, la salida de los lectores de pantalla será confusa para estos usuarios.</li> + <li><strong>Las tablas generan estructuras incorrectas</strong>: Como ya se mencionó, los diseños de tabla suelen involucrar estructuras de marcado más complejas que las técnicas de diseño. Esto puede dificultar la escritura, el mantenimiento y la depuración del código.</li> + <li><strong>Las tablas no tienen respuesta adaptativa automática</strong>: Cuando usas contenedores de diseño adecuados (tales como {{HTMLElement ("header")}}, {{HTMLElement ("section")}}, {{HTMLElement ("article")}} o {{HTMLElement ("div")}}), su ancho predeterminado es el 100% de su elemento padre. En cambio, las tablas se dimensionan de forma predeterminada según su contenido, por lo que se necesitan medidas adicionales para que el diseño de la tabla funcione de manera efectiva en todos los dispositivos.</li> +</ol> + +<h2 id="Aprendizaje_activo_Crea_tu_primera_tabla">Aprendizaje activo: Crea tu primera tabla</h2> + +<p>Ya hemos hablado bastante sobre la teoría de las tablas, así que veamos un ejemplo práctico y construyamos una tabla simple.</p> + +<ol> + <li>En primer lugar, haz una copia local de <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/blank-template.html">blank-template.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/minimal-table.css">minimal-table.css</a> en un directorio nuevo de tu ordenador.</li> + <li>El contenido de cada tabla está delimitado entre estas dos etiquetas: <strong><code><a href="/en-US/docs/Web/HTML/Element/table"><table></table></a></code></strong>. Añádelas al cuerpo de tu código HTML.</li> + <li>El contenedor más pequeño dentro de una tabla es una celda, que se crea con un elemento <strong><code><a href="/en-US/docs/Web/HTML/Element/td"><td></a></code></strong> ('td' significa 'table data', <em>datos de tabla</em>). Añade lo siguiente dentro de tus etiquetas de tabla: + <pre class="brush: html notranslate"><td>Hola, soy tu primera celda.</td></pre> + </li> + <li>Si quieres una fila de cuatro celdas, tienes que copiar estas etiquetas tres veces. Actualiza el contenido de la tabla para que se vea así: + <pre class="brush: html notranslate"><td>Hola, soy tu primera celda.</td> +<td>Soy tu segunda celda.</td> +<td>Soy tu tercera celda.</td> +<td>Soy tu cuarta celda.</td></pre> + </li> +</ol> + +<p>Como verás, las celdas no se colocan una debajo de la otra, sino que se alinean automáticamente entre sí en la misma fila. Cada elemento <td> crea una sola celda, y juntas forman la primera fila. Cada celda que agregamos hace crecer la fila.</p> + +<p>Para detener el crecimiento de esta fila y comenzar a colocar las celdas posteriores en una segunda fila, necesitamos usar el elemento <strong><code><a href="/en-US/docs/Web/HTML/Element/tr"><tr></a></code></strong> ('tr' significa 'table raw', <em>fila de tabla</em>). Vamos a verlo en detalle.</p> + +<ol> + <li>Coloca las cuatro celdas que has creado dentro de las etiquetas <code><tr></code>, de esta forma: + + <pre class="brush: html notranslate"><tr> + <td>Hola, soy tu primera celda.</td> + <td>Soy tu segunda celda.</td> + <td>Soy tu tercera celda.</td> + <td>Soy tu cuarta celda.</td> +</tr></pre> + </li> + <li>Ahora que has hecho una fila, intenta hacer una o dos más: cada fila debe estar delimitada por un elemento <code><tr></code> adicional, con cada celda contenida en un <code><td></code>.</li> +</ol> + +<p>Esto debería dar como resultado una tabla similar a la siguiente:</p> + +<table> + <tbody> + <tr> + <td>Hola, soy tu primera celda.</td> + <td>Soy tu segunda celda.</td> + <td>Soy tu tercera celda.</td> + <td>Soy tu cuarta celda.</td> + </tr> + <tr> + <td>Segunda fila, primera celda.</td> + <td>Celda 2.</td> + <td>Celda 3.</td> + <td>Celda 4.</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Nota</strong>: También puedes encontrar esto en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/simple-table.html">simple-table.html</a> (consúltalo <a href="http://mdn.github.io/learning-area/html/tables/basic/simple-table.html">en vivo</a>).</p> +</div> + +<h2 id="Añadir_encabezados_con_elementos_<th>">Añadir encabezados con elementos <th></h2> + +<p>Ahora nos vamos a centrar en los encabezados de tabla: celdas especiales que van al comienzo de una fila o columna y definen el tipo de datos que contiene esa fila o columna (por ejemplo, observa las celdas «Propietario» y «Edad» en el primer ejemplo que se muestra en este artículo). Para ilustrar por qué son útiles, echa un vistazo al ejemplo de tabla siguiente. En primer lugar, el código fuente:</p> + +<pre class="brush: html notranslate"><table> + <tr> + <td>&nbsp;</td> + <td>Knocky</td> + <td>Flor</td> + <td>Ella</td> + <td>Juan</td> + </tr> + <tr> + <td>Raza</td> + <td>Jack Russell</td> + <td>Caniche</td> + <td>Perro callejero</td> + <td>Cocker Spaniel</td> + </tr> + <tr> + <td>Edad</td> + <td>16</td> + <td>9</td> + <td>10</td> + <td>5</td> + </tr> + <tr> + <td>Propietario</td> + <td>Suegra</td> + <td>Yo</td> + <td>Yo</td> + <td>Cuñada</td> + </tr> + <tr> + <td>Hábitos alimentarios</td> + <td>Come las sobras de todos</td> + +<td>Mordisquea la comida</td> + <td>Come en abundancia</td> + +<td>Come hasta que revienta</td> + </tr> +</table></pre> + +<p>Ahora observa la tabla representada:</p> + +<table> + <tbody> + <tr> + <td></td> + <td>Knocky</td> + <td>Flor</td> + <td>Ella</td> + <td>Juan</td> + </tr> + <tr> + <td>Raza</td> + <td>Jack Russell</td> + <td>Caniche</td> + <td>Perro callejero</td> + <td>Cocker Spaniel</td> + </tr> + <tr> + <td>Edad</td> + <td>16</td> + <td>9</td> + <td>10</td> + <td>5</td> + </tr> + <tr> + <td>Propietario</td> + <td>Suegra</td> + <td>Yo</td> + <td>Yo</td> + <td>Cuñada</td> + </tr> + <tr> + <td>Hábitos alimentarios</td> + <td>Come las sobras de todos</td> + <td>Mordisquea la comida</td> + <td>Come en abundancia</td> + <td>Come hasta que revienta</td> + </tr> + </tbody> +</table> + +<p>El problema aquí es que, si bien puedes distinguir lo que sucede, no es tan fácil cruzar datos de referencia. Sería mucho mejor si los encabezados de las columnas y las filas se destacasen de alguna manera.</p> + +<h3 id="Aprendizaje_activo_encabezados_de_tabla">Aprendizaje activo: encabezados de tabla</h3> + +<p>Intentemos mejorar esta tabla.</p> + +<ol> + <li>Primero, haz una copia local de nuestros archivos <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/dogs-table.html">dogs-table.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/minimal-table.css">minimal-table.css</a> en un directorio nuevo de tu ordenador. El HTML contiene el mismo ejemplo sobre perros que viste arriba.</li> + <li>Para reconocer los encabezados de la tabla como encabezados, tanto visual como semánticamente, puedes usar el elemento <strong><code><a href="/en-US/docs/Web/HTML/Element/th"><th></a></code></strong> ('th' significa 'table header', <em>encabezado de tabla</em>). Funciona exactamente igual que un <code><td></code>, excepto que denota un encabezado, no una celda normal. Entra en el código HTML, y cambiar todos los elementos <code><td></code> que delimitan los encabezados de tabla por elementos <code><th></code>.</li> + <li>Guarda tu HTML y cárgalo en un navegador. Los encabezados deberían verse como tal.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar nuestro ejemplo terminado en <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/dogs-table-fixed.html">dogs-table-fixed.html</a> en GitHub (<a href="http://mdn.github.io/learning-area/html/tables/basic/dogs-table-fixed.html">o consultarlo en vivo</a>).</p> +</div> + +<h3 id="¿Por_qué_son_útiles_los_encabezados">¿Por qué son útiles los encabezados?</h3> + +<p>Ya hemos respondido parcialmente a esta pregunta: es más fácil encontrar los datos que buscas cuando los encabezados se destacan con claridad, y el diseño suele presentar un aspecto mejor.</p> + +<div class="note"> +<p><strong>Nota</strong>: Los encabezados de las tablas vienen con un estilo predeterminado: están en negrita y centrados (incluso si no añades tu estilo propio a la tabla) para que destaquen.</p> +</div> + +<p>Los encabezados de tabla también presentan otra ventaja: junto con el atributo de <code>scope</code> (que veremos en el próximo artículo), mejoran la accesibilidad de las tablas porque asocian cada encabezado con todos los datos de la misma fila o columna. Así que los lectores de pantalla pueden leer una fila o columna de datos a la vez, lo cual es bastante útil.</p> + +<h2 id="Celdas_que_abarcan_varias_filas_y_columnas">Celdas que abarcan varias filas y columnas</h2> + +<p>A veces queremos que las celdas abarquen varias filas o columnas. Toma el ejemplo siguiente, que muestra los nombres de algunos animales comunes. En algunos casos, queremos mostrar los nombres de los machos y las hembras junto al nombre del animal. A veces no lo queremos, y en tales casos queremos que el nombre del animal abarque toda la tabla.</p> + +<p>El marcado inicial se ve así:</p> + +<pre class="brush: html notranslate"><table> + <tr> + <th>Animales</th> + </tr> + <tr> + <th>Hipopótamo</th> + </tr> + <tr> + <th>Caballo</th> + <td>Yegua</td> + </tr> + <tr> + <td>Semental</td> + </tr> + <tr> + +<th>Cocodrilo</th> + </tr> + <tr> + +<th>Pollo</th> + +<td>Gallina</td> + </tr> + <tr> + <td>Gallo</td> + </tr> +</table></pre> + +<p>Pero la salida no nos da exactamente lo que queremos:</p> + +<table> + <tbody> + <tr> + <th>Animales</th> + </tr> + <tr> + <th>Hipopótamo</th> + </tr> + <tr> + <th>Caballo</th> + <td>Yegua</td> + </tr> + <tr> + <td>Semental</td> + </tr> + <tr> + <th>Cocodrilo</th> + </tr> + <tr> + <th>Pollo</th> + <td>Gallina</td> + </tr> + <tr> + <td>Gallo</td> + </tr> + </tbody> +</table> + +<p>Necesitamos una forma de hacer que «Animales», «Hipopótamo» y «Cocodrilo» se extiendan dos columnas más allá, y «Caballo» y «Pollo» se extiendan dos filas más abajo. Por fortuna, los encabezados de tabla y las celdas tienen los atributos <code>colspan</code> y <code>rowspan</code>, que nos permiten hacer exactamente esas cosas. Ambos aceptan un valor numérico sin unidades, que es igual al número de filas o columnas que desea abarcar. Por ejemplo, <code>colspan="2"</code> extiende una celda dos columnas más allá.</p> + +<p>Usemos <code>colspan</code> y <code>rowspan</code> para mejorar esta tabla.</p> + +<ol> + <li>Primero, haz una copia local de nuestros archivos <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/animals-table.html">animals-table.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/minimal-table.css">minimal-table.css</a> en un directorio nuevo de tu ordenador. El HTML contiene el mismo ejemplo sobre perros que viste arriba.</li> + <li>Luego, usa <code>colspan</code> para extender las celdas «Animales», «Hipopótamo» y «Cocodrilo» dos columnas más allá.</li> + <li>Por último, usa <code>rowspan</code> para extender las celdas de «Caballo» y «Pollo» dos filas más abajo.</li> + <li>Guarda tu código y ábrelo en un navegador para ver la mejora.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar nuestro ejemplo terminado en <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/animals-table-fixed.html">animals-table-fixed.html</a> en GitHub (<a href="http://mdn.github.io/learning-area/html/tables/basic/animals-table-fixed.html">o consultarlo en vivo</a>).</p> +</div> + +<table id="tabular" style="background-color: white;"> +</table> + +<h2 id="Proporcionar_un_estilo_común_a_las_columnas.">Proporcionar un estilo común a las columnas.</h2> + +<p>Hay una última característica de la que queremos hablar en este artículo antes de continuar. El HTML tiene un método para definir información de estilo para una columna completa de datos en un solo lugar: los elementos <strong><code><a href="/es/docs/Web/HTML/Elemento/col"><col></a></code></strong> y <strong><code><a href="/es/docs/Web/HTML/Elemento/colgroup"><colgroup></a></code></strong>. Estos atributos existen porque especificar el estilo de las columnas puede resultar enojoso e ineficiente; en general hay que especificar la información de estilo en <em>cada</em> <code><td></code> o <code><th></code> de la columna, o utilizar un selector complejo como {{cssxref(":nth-child()")}}.</p> + +<p>Tomemos el ejemplo sencillo siguiente:</p> + +<pre class="brush: html notranslate"><table> + <tr> + +<th>Dato 1</th> + <th style="background-color: yellow">Dato 2</th> + </tr> + <tr> + <td>Calcuta</td> + <td style="background-color: yellow">Pizza</td> + </tr> + <tr> + <td>Robots</td> + <td style="background-color: yellow">Jazz</td> + </tr> +</table></pre> + +<p>Esto nos da el resultado siguiente:</p> + +<table> + <tbody> + <tr> + <th>Dato 1</th> + <th style="background-color: yellow;">Dato 2</th> + </tr> + <tr> + <td>Calcuta</td> + <td style="background-color: yellow;">Naranja</td> + </tr> + <tr> + <td>Robots</td> + <td style="background-color: yellow;">Jazz</td> + </tr> + </tbody> +</table> + +<p>Esto no es ideal, porque hay que repetir la información de estilo en las tres celdas de la columna (en un proyecto real probablemente habría definida una clase <code>class</code> en las tres celdas y el estilo se especificaría en una hoja de estilo por separado). En vez de hacer esto, podemos especificar la información una sola vez, con un elemento <code><col></code>. Los elementos <code><col></code> se especifican dentro de un contenedor <code><colgroup></code> justo debajo de la etiqueta de apertura <code><table></code>. Podríamos crear el mismo efecto que vemos arriba especificando nuestra tabla de la manera siguiente:</p> + +<pre class="brush: html notranslate"><table> + <colgroup> + <col> + <col style="background-color: yellow"> + </colgroup> + <tr> + +<th>Dato 1</th> + +<th>Dato 2</th> + </tr> + <tr> + <td>Calcuta</td> + <td>Pizza</td> + </tr> + <tr> + <td>Robots</td> + <td>Jazz</td> + </tr> +</table></pre> + +<p>En efecto, definimos dos tipos de «columnas de estilo», una que especifica la información para la aplicación de estilo en cada columna. No aplicamos estilo a la primera columna, sino que aún tenemos que incluir un elemento <code><col></code> en blanco; de lo contrario, el estilo también se aplicaría a la primera columna.</p> + +<p>Si quisiéramos aplicar la información de estilo a ambas columnas, podríamos incluir un elemento <code><col></code> con un atributo <code>span</code>, como este:</p> + +<pre class="brush: html notranslate"><colgroup> + <col style="background-color: yellow" span="2"> +</colgroup></pre> + +<p>Al igual que <code>colspan</code> y <code>rowspan</code>, <code>span</code> toma un valor numérico sin unidades que especifica el número de columnas a las que se desea aplicar el estilo.</p> + +<h3 id="Aprendizaje_activo_colgroup_y_col">Aprendizaje activo: colgroup y col</h3> + +<p>Ahora es el momento de intentarlo tú mismo.</p> + +<p>A continuación puedes ver el horario de una profesora de idiomas. El viernes tiene que enseñar holandés todo el día, pero también enseña alemán durante unas horas los martes y los jueves, y quiere resaltar las columnas que contienen los días que da clase.</p> + +<p>{{EmbedGHLiveSample("learning-area/html/tables/basic/timetable-fixed.html", '100%', 320)}}</p> + +<p>Recrea la tabla a partir de los pasos siguientes.</p> + +<ol> + <li>Primero, haz una copia local de nuestro archivo <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/timetable.html">timetable.html</a> en un directorio nuevo de tu ordenador. El HTML contiene la misma tabla que viste arriba, menos la información de estilo de las columnas.</li> + <li>Añade un elemento <code><colgroup></code> en la parte superior de la tabla, justo debajo de la etiqueta <code><table></code>, en la que puedes añadir tus elementos <code><col></code> (consulta los pasos restantes a continuación).</li> + <li>Las dos primeras columnas deben dejarse sin estilo.</li> + <li>Añade un color de fondo a la tercera columna. El valor para tu atributo de <code>style</code> es <code>background-color:#97DB9A;</code></li> + <li>Establece un ancho distinto para la cuarta columna. El valor de tu atributo de <code>style</code> es <code>width: 42px;</code></li> + <li>Añade un color de fondo a la quinta columna. El valor para tu atributo de <code>style</code> es <code>background-color:#97DB9A;</code></li> + <li>Añade un color de fondo diferente más un borde a la sexta columna, para indicar que este es un día especial porque da clases de un idioma diferente. Los valores para tu atributo de <code>style</code> son <code>background-color:#DCC48E; border:4px solid #C1437A;</code></li> + <li>Los últimos dos días los tiene libres, así que no establezcas ningún color de fondo, pero sí un valor para el ancho; el valor para el atributo de <code>style</code> es <code>width: 42px;</code></li> +</ol> + +<p>Mira cómo sigue en el ejemplo. Si te encallas o quieres verificar tu trabajo, puedes encontrar nuestra versión en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/timetable-fixed.html">timetable-fixed.html</a> (o también puedes consultarlo <a href="http://mdn.github.io/learning-area/html/tables/basic/timetable-fixed.html">en vivo</a>).</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Con esto casi hemos abarcado todos los conceptos básicos de las tablas HTML. En el próximo artículo, veremos algunas características un poco más avanzadas de las tablas y comenzaremos a pensar acerca de su accesibilidad para las personas con discapacidad visual.</p> + +<div>{{NextMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}</div> + +<div> +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Tables/Basics">Conceptos básicos de las tablas en HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Tables/Advanced">Funciones avanzadas de las tablas HTML y accesibilidad</a></li> + <li><a href="/en-US/docs/Learn/HTML/Tables/Structuring_planet_data">Estructuración de datos planetarios</a></li> +</ul> +</div> diff --git a/files/es/learn/html/tablas/funciones_avanzadas_de_las_tablas_html_y_accesibilidad/index.html b/files/es/learn/html/tablas/funciones_avanzadas_de_las_tablas_html_y_accesibilidad/index.html new file mode 100644 index 0000000000..a74817c5d4 --- /dev/null +++ b/files/es/learn/html/tablas/funciones_avanzadas_de_las_tablas_html_y_accesibilidad/index.html @@ -0,0 +1,471 @@ +--- +title: Funciones avanzadas de las tablas HTML y accesibilidad +slug: Learn/HTML/Tablas/Funciones_avanzadas_de_las_tablas_HTML_y_accesibilidad +translation_of: Learn/HTML/Tables/Advanced +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/HTML/Tables/Basics", "Learn/HTML/Tables/Structuring_planet_data", "Learn/HTML/Tables")}}</div> + +<p class="summary">En el segundo artículo de este módulo, analizamos algunas características más avanzadas de las tablas HTML, como los subtítulos/resúmenes, la agrupación de filas en las secciones del encabezado, el cuerpo y el pie de página; y también analizamos la accesibilidad de las tablas para usuarios con discapacidad visual.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conceptos básicos de HTML (ver <a href="/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción al HTML</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender las características más avanzadas de las tablas HTML y la accesibilidad de las tablas.</td> + </tr> + </tbody> +</table> + +<h2 id="Añadir_un_subtítulo_a_tu_tabla_con_<caption>">Añadir un subtítulo a tu tabla con <caption></h2> + +<p>Puedes dar un título a tu tabla colocándolo dentro de un elemento {{htmlelement ("caption")}} y anidándolo dentro del elemento {{htmlelement ("table")}}. Debes ponerlo justo debajo de la etiqueta de apertura <code><table></code>.</p> + +<pre class="brush: html notranslate"><table> + <caption>Dinosaurios en el período Jurásico</caption> + + ... +</table></pre> + +<p>Como puedes deducir a partir del breve ejemplo anterior, el título debe contener una descripción del contenido de la tabla. Esto es útil para todos los lectores que deseen descubrir de un vistazo si la tabla les resulta útil mientras ojean la página, pero es útil especialmente para usuarios ciegos. En lugar de que un lector de pantalla lea el contenido de muchas celdas solo para averiguar de qué trata la tabla, el lector puede contar con el título para luego decidir si leer la tabla con mayor detalle.</p> + +<p>Los subtítulos se colocan directamente debajo de la etiqueta <code><table></code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: El atributo {{htmlattrxref("summary","table")}} también se puede usar en el elemento <code>table</code> para proporcionar una descripción; los lectores de pantalla también lo leen. Sin embargo, recomendamos usar el elemento <code>caption</code>, porque {{htmlattrxref("summary","table")}} está {{glossary("obsoleto")}} conforme a la especificación HTML5 y porque los usuarios sin discapacidad visual no pueden leerlo (no aparece en la página).</p> +</div> + +<h3 id="Aprendizaje_activo_Añadir_un_subtítulo">Aprendizaje activo: Añadir un subtítulo</h3> + +<p>Vamos a probarlo con un ejemplo del artículo anterior.</p> + +<ol> + <li>Abre el ejemplo del horario de clases de la profesora de idiomas del final de <a href="/es/docs/Learn/HTML/Tablas/Conceptos_b%C3%A1sicos_de_las_tablas_HTML#Aprendizaje_activo_colgroup_y_col"> conocimientos básicos de las tablas HTML</a>, o haz una copia local de nuestro archivo <a href="https://github.com/mdn/learning-area/blob/master/html/tables/basic/timetable-fixed.html">timetable-fixed.html</a>.</li> + <li>Añade un título adecuado a la tabla.</li> + <li>Guarda tu código, ábrelo en un navegador y observa qué aspecto presenta.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar nuestra versión en GitHub: consulta <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/timetable-caption.html">timetable-caption.html</a> (<a href="http://mdn.github.io/learning-area/html/tables/advanced/timetable-caption.html">mirar en vivo</a>).</p> +</div> + +<h2 id="Añadir_estructura_con_<thead>_<tfoot>_y_<tbody>">Añadir estructura con <thead>, <tfoot> y <tbody></h2> + +<p>A medida que la estructura de las tablas se vuelve más compleja, es útil darles una estructura más definida. Una forma clara de hacerlo es con {{htmlelement ("thead")}}, {{htmlelement ("tfoot")}} y {{htmlelement ("tbody")}}, que te permiten marcar un encabezado, un pie de página y una sección del cuerpo de la tabla.</p> + +<p>Estos elementos no mejoran las características de accesibilidad de la tabla para los usuarios de lectores de pantalla ni su aspecto visual en sí. Sin embargo, son muy útiles para la aplicación de estilo y la compaginación, porque actúan como soportes útiles para añadir CSS a tu tabla. Como ejemplos interesantes, en el caso de una tabla extensa, puedes hacer que el encabezado y el pie de página se repitan en cada página impresa, y también que el cuerpo de la tabla se muestre en una sola página y desplazarte por los contenidos arriba y abajo con la barra de desplazamiento.</p> + +<p>Para utilizarlos:</p> + +<ul> + <li>El elemento <code><thead></code> debe delimitar el encabezado de la tabla; esta suele ser la primera fila, que contiene los encabezados de las columnas, pero no siempre es así. Si utilizas los elementos {{htmlelement ("col")}}/{{htmlelement ("colgroup")}}, el encabezado de la tabla debe estar justo debajo.</li> + <li>El elemento <code><tfoot></code> delimita la parte de la tabla correspondiente al pie de página; esta podría ser una fila final con elementos en las filas anteriores. Puedes incluir el pie de página de la tabla justo en la parte inferior de la tabla, donde esperarías que esté, o justo debajo del encabezado (y el navegador lo mostrará aun así en la parte inferior de la tabla).</li> + <li>El elemento <code><tbody></code> delimita las otras partes del contenido de la tabla que no están en el encabezado o en el pie de página de la tabla. Aparecerá debajo del encabezado de la tabla o, a veces, en el pie de página, según cómo hayas decidido estructurarlo.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: <code><tbody></code> se incluye siempre en todas las tablas de forma implícita si no lo especificas en tu código. Para comprobarlo, abre uno de tus ejemplos anteriores que no incluya <code><tbody></code> y mira el código HTML en las <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">herramientas de desarrollo de tu navegador</a>; verás que el navegador ha añadido esta etiqueta. Quizás te preguntes por qué deberías molestarte en incluirlo. Debes hacerlo para tener más control sobre la estructura y el estilo de la tabla.</p> +</div> + +<h3 id="Aprendizaje_activo_Añadir_estructura_a_la_tabla">Aprendizaje activo: Añadir estructura a la tabla</h3> + +<p>Pongamos en acción estos elementos nuevos.</p> + +<ol> + <li>En primer lugar, haz una copia local de <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/spending-record.html">spending-record.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/minimal-table.css">minimal-table.css</a> en una carpeta nueva de tu ordenador.</li> + <li>Intenta abrirlo en un navegador: observarás que se ve bien, pero podría mejorarse. La fila «SUM», que contiene una suma de las cantidades gastadas, parece estar en el lugar equivocado, y faltan algunos detalles del código.</li> + <li>Coloca la fila de encabezados dentro de un elemento <code><thead></code>, la fila «SUM» dentro de un elemento <code><tfoot></code>, y el resto del contenido dentro de un elemento <code><tbody></code>.</li> + <li>Guarda y actualiza, y observa que añadir el elemento <code><tfoot></code> ha provocado que la fila «SUM» pase al final de la tabla.</li> + <li>Luego, añade un atributo {{htmlattrxref ("colspan", "td")}} para que la celda «SUM» abarque las primeras cuatro columnas, de modo que el número aparezca en la parte inferior de la columna «Costes».</li> + <li>Vamos a añadir un estilo adicional sencillo a la tabla para que veas cuán útiles son estos elementos para aplicar CSS. Dentro del encabezado del documento HTML hay un elemento {{htmlelement ("style")}} vacío. Añade a este elemento las líneas de código CSS siguientes: + <pre class="brush: css notranslate">tbody { + font-size: 95%; + font-style: italic; +} + +tfoot { + font-weight: bold; +} +</pre> + </li> + <li>Guarda, actualiza, y échale un vistazo al resultado. Si los elementos <code><tbody></code> y <code><tfoot></code> no estuvieran en su lugar, tendrías que escribir selectores/reglas mucho más complicados para obtener la misma aplicación de estilo.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: No esperamos que comprendas completamente el CSS en este momento. Aprenderás más sobre el tema cuando llegues a nuestros módulos CSS (<a href="/es/docs/Learn/CSS/First_steps">Introducción al CSS</a> es un buen lugar para comenzar; también tenemos un artículo específico sobre <a href="/es/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a>).</p> +</div> + +<p>Tu tabla final debería tener un aspecto similar al siguiente:</p> + +<div class="hidden"> +<h6 id="Hidden_example">Hidden example</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title> Mi historial de gastos </title> + <style> + + html { + font-family: sans-serif; + } + + table { + border-collapse: collapse; + border: 4px solid rgb(200,200,200); + letter-spacing: 1px; + font-size: 0.8rem; + } + + td, th { + border: 2px solid rgb(190,190,190); + padding: 10px 20px; + } + + th { + background-color: rgb(235,235,235); + } + + td { + text-align: center; + } + + tr:nth-child(even) td { + background-color: rgb(250,250,250); + } + + tr:nth-child(odd) td { + background-color: rgb(245,245,245); + } + + caption { + padding: 10px; + } + + tbody { + font-size: 90%; + font-style: italic; + } + + tfoot { + font-weight: bold; + } + </style> + </head> + <body> + <table> + +<caption> Cómo elegí gastar mi dinero </caption> + <thead> + <tr> + <th> Compra </th> + +<th> Ubicación </th> + <th> Fecha </th> + <th> Revisión </th> + +<th> Coste (€) </th> + </tr> + </thead> + <tfoot> + <tr> + <td colspan="4">SUM</td> + <td>118</td> + </tr> + </tfoot> + <tbody> + <tr> + <td> Corte de pelo </td> + +<td> Peluquería </td> + <td>12/09</td> + +<td> Gran idea </td> + <td>30</td> + </tr> + <tr> + +<td> Lasaña </td> + +<td> Restaurante </td> + <td>12/09</td> + <td> Arrepentimiento </td> + <td>18</td> + </tr> + <tr> + +<td> Zapatos </td> + <td> Zapatería </td> + <td>13/09</td> + +<td> Mucho arrepentimiento </td> + <td>65</td> + </tr> + <tr> + <td> Pasta de dientes </td> + <td> Supermercado </td> + <td>13/09</td> + +<td> Bien </td> + <td>5</td> + </tr> + </tbody> + </table> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_example', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>Nota</strong>: También puedes encontrarlo en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/spending-record-finished.html">spending-record-finished.html</a> (o consultarlo también <a href="http://mdn.github.io/learning-area/html/tables/advanced/spending-record-finished.html">en vivo</a>).</p> +</div> + +<h2 id="Anidar_tablas">Anidar tablas</h2> + +<p>Es posible anidar una tabla dentro de otra, siempre que incluyas la estructura completa, incluido el elemento <code><table></code>. Por lo general, esto no se recomienda, porque se obtiene un marcado más confuso y menos accesible para los usuarios que usan lectores de pantalla, y además, en muchos casos sería posible sencillamente insertar celdas/filas/columnas adicionales en la tabla. Sin embargo, a veces es necesario, por ejemplo, si deseas importar contenido de forma sencilla desde otras fuentes.</p> + +<p>El marcado siguiente muestra una tabla anidada simple:</p> + +<pre class="brush: html notranslate"><table id="tabla1"> + <tr> + <th>título1</th> + <th>título2</th> + <th>título3</th> + </tr> + <tr> + <td id="nested"> + <table id="tabla2"> + <tr> + <td>celda1</td> + <td>celda2</td> + <td>celda3</td> + </tr> + </table> + </td> + <td>celda2</td> + <td>celda3</td> + </tr> + <tr> + <td>celda4</td> + <td>celda5</td> + <td>celda6</td> + </tr> +</table></pre> + +<p>La salida se verá así:</p> + +<table id="table1"> + <tbody> + <tr> + <th>título1</th> + <th>título2</th> + <th>título3</th> + </tr> + <tr> + <td id="nested"> + <table id="table2"> + <tbody> + <tr> + <td>celda1</td> + <td>celda2</td> + <td>celda3</td> + </tr> + </tbody> + </table> + </td> + <td>celda2</td> + <td>celda3</td> + </tr> + <tr> + <td>celda4</td> + <td>celda5</td> + <td>celda6</td> + </tr> + </tbody> +</table> + +<h2 id="Tablas_para_usuarios_con_discapacidad_visual">Tablas para usuarios con discapacidad visual</h2> + +<p>Repasemos brevemente cómo usamos las tablas de datos. Una tabla puede ser una herramienta útil porque nos proporciona un acceso rápido a unos datos y nos permite buscar entre valores diferentes. Por ejemplo, echa un vistazo a la tabla siguiente para saber cuántos anillos se vendieron en Gante en agosto pasado. Para comprender la información que contiene la tabla, establecemos asociaciones visuales entre los datos de la tabla y sus encabezados de columna y/o fila.</p> + +<table> + <caption>Artículos vendidos en agosto de 2016</caption> + <tbody> + <tr> + <td></td> + <td></td> + <th colspan="3" scope="colgroup">Ropa</th> + <th colspan="2" scope="colgroup">Accesorios</th> + </tr> + <tr> + <td></td> + <td></td> + <th scope="col">Pantalones</th> + <th scope="col">Faldas</th> + <th scope="col">Vestidos</th> + <th scope="col">Pulseras</th> + <th scope="col">Anillos</th> + </tr> + <tr> + <th rowspan="3" scope="rowgroup">Bélgica</th> + <th scope="row">Amberes</th> + <td>56</td> + <td>22</td> + <td>43</td> + <td>72</td> + <td>23</td> + </tr> + <tr> + <th scope="row">Gante</th> + <td>46</td> + <td>18</td> + <td>50</td> + <td>61</td> + <td>15</td> + </tr> + <tr> + <th scope="row">Bruselas</th> + <td>51</td> + <td>27</td> + <td>38</td> + <td>69</td> + <td>28</td> + </tr> + <tr> + <th rowspan="2" scope="rowgroup">Los países bajos</th> + <th scope="row">Ámsterdam</th> + <td>89</td> + <td>34</td> + <td>69</td> + <td>85</td> + <td>38</td> + </tr> + <tr> + <th scope="row">Utrecht</th> + <td>80</td> + <td>12</td> + <td>43</td> + <td>36</td> + <td>19</td> + </tr> + </tbody> +</table> + +<p>Pero, ¿y si no puedes hacer esas asociaciones visuales? ¿Cómo podrías leer una tabla como la anterior? Las personas con discapacidad visual a menudo usan un lector de pantalla que les lee la información de las páginas web. Esto no resulta un problema cuando lees un texto sin formato, pero interpretar una tabla puede ser un gran desafío para una persona ciega. Sin embargo, con el marcado adecuado podemos reemplazar las asociaciones visuales por otras asociaciones de tipo programático.</p> + +<div class="note"> +<p><strong>Nota</strong>: Hay en torno a 253 millones de personas con discapacidad visual según los<a href="https://www.who.int/es/news-room/fact-sheets/detail/blindness-and-visual-impairment" title="datos de la OMS sobre la discapacidad visual"> datos de la OMS de 2017</a>.</p> +</div> + +<p>Esta sección del artículo proporciona técnicas adicionales para conferir a las tablas la mayor accesibilidad posible.</p> + +<h3 class="attTitle" id="Usar_encabezados_de_columna_y_fila">Usar encabezados de columna y fila</h3> + +<p>Los lectores de pantalla identificarán todos los encabezados y los usarán para hacer asociaciones programáticas entre esos encabezados y las celdas con las que se relacionan. La combinación de encabezados por columna y fila identificará e interpretará los datos de cada celda para que los usuarios que usan lectores de pantalla puedan interpretar la tabla de manera similar a como lo hace un usuario sin discapacidad visual.</p> + +<p>Ya expusimos los encabezados en nuestro artículo anterior; consulta <a href="/es/docs/Learn/HTML/Tablas/Conceptos_b%C3%A1sicos_de_las_tablas_HTML#A%C3%B1adir_encabezados_con_elementos_%3Cth%3E">Añadir encabezados con elementos <th></a>.</p> + +<h3 class="attTitle" id="El_atributo_scope">El atributo scope</h3> + +<p>Un nuevo tema para este artículo es el atributo {{htmlattrxref ("scope", "th")}}, que se puede añadir al elemento <code><th></code> para indicar a los lectores de pantalla exactamente para qué celdas es el encabezado. Volviendo a nuestro ejemplo anterior de registro de gastos, podrías definir los encabezados de columna inequívocamente como encabezados de columna de este modo:</p> + +<pre class="brush: html notranslate"><thead> + <tr> + <th scope="col">Compra</th> + <th scope="col">Ubicación</th> + <th scope="col">Fecha</th> + <th scope="col">Revisión</th> + <th scope="col">Coste (€)</th> + </tr> +</thead></pre> + +<p>Y también cada fila podría tener un encabezado definido de esta manera (si añadimos encabezados de fila y encabezados de columna):</p> + +<pre class="brush: html notranslate"><tr> + <th scope="row">Corte de pelo</th> + +<td>Peluquería</td> + <td>12/09</td> + +<td>Gran idea</td> + <td>30</td> +</tr></pre> + +<p>Los lectores de pantalla reconocerán el marcado estructurado de esta manera y permitirán a tus usuarios, por ejemplo, leer toda la columna o fila a la vez.</p> + +<p>El atributo <code>scope</code> tiene dos valores posibles más: <code>colgroup</code> y <code>rowgroup</code>. Se utilizan para encabezados que se encuentran sobre la parte superior de varias columnas o filas. Si vuelves a echar un vistazo a la tabla «Artículos vendidos en agosto de 2016» al comienzo de esta sección, verás que la celda «Ropa» se encuentra encima de las celdas «Pantalones», «Faldas» y «Vestidos» Todas estas celdas deben estar marcadas como encabezados (<code><th></code>), pero «Ropa» es un encabezado que está por encima y define los otros tres subencabezados. Por lo tanto, «Ropa» debería incluir un atributo <code>scope="colgroup"</code>, mientras que los demás tendrían un atributo <code>scope="col"</code>.</p> + +<h3 class="attTitle" id="Los_atributos_de_id_y_encabezados">Los atributos de id y encabezados</h3> + +<p>Una alternativa al uso del atributo <code>scope</code> es usar los atributos {{htmlattrxref ("id")}} y {{htmlattrxref ("headers", "td")}} para crear asociaciones entre encabezados y celdas. La forma en que se usan es la siguiente:</p> + +<ol> + <li>Añades un <code>id</code> único a cada elemento <code><th></code>.</li> + <li>Añades un atributo <code>headers</code> a cada elemento <code><td></code>. Cada atributo <code>headers</code> debe contener una lista de los <code>id</code> de todos los elementos <code><th></code> que actúan como encabezado de esa celda, separados por espacios.</li> +</ol> + +<p>Esto le da a tu tabla HTML una definición explícita de la posición de cada celda en la tabla definida por los encabezados de cada columna y fila de la que forma parte, como en una hoja de cálculo. Para que funcione bien, la tabla necesita tanto encabezados de columna como encabezados de fila.</p> + +<p>Volviendo a nuestro ejemplo de gastos, los dos fragmentos anteriores podrían reescribirse así:</p> + +<pre class="brush: html notranslate"><thead> + <tr> + <th id="purchase">Compra</th> + <th id="location">Ubicación</th> + <th id="date">Fecha</th> + <th id="evaluation">Revisión</th> + <th id="cost">Coste (€)</th> + </tr> +</thead> +<tbody> +<tr> + <th id="haircut">Corte de pelo</th> + <td headers="location haircut">Peluquería</td> + <td headers="date haircut">12/09</td> + <td headers="evaluation haircut">Gran idea</td> + <td headers="cost haircut">30</td> +</tr> + + ... + +</tbody></pre> + +<div class="note"> +<p><strong>Nota</strong>: Este método crea asociaciones muy precisas entre los encabezados y las celdas de datos, pero utiliza <strong>un montón</strong> más de código de marcado y no permite errores. El enfoque <code>scope</code> suele bastar para la mayoría de las tablas.</p> +</div> + +<h3 id="Aprendizaje_activo_jugar_con_scope_y_headers">Aprendizaje activo: jugar con scope y headers</h3> + +<ol> + <li>Para este ejercicio final, te proponemos que primero hagas copias locales de <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/items-sold.html">items-sold.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/minimal-table.css">minimal-table.css</a> en un directorio nuevo.</li> + <li>Ahora intenta añadir los atributos <code>scope</code> adecuados para hacer que esta tabla sea más accesible.</li> + <li>Por último, haz otra copia de los archivos originales, y esta vez añade accesibilidad a la tabla utilizando los atributos <code>id</code> y <code>headers</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Puedes verificar tu trabajo con nuestros ejemplos terminados: consulta <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/items-sold-scope.html">items-sold-scope.html</a> (<a href="http://mdn.github.io/learning-area/html/tables/advanced/items-sold-scope.html">consúltalo en vivo</a>) y <a href="https://github.com/mdn/learning-area/blob/master/html/tables/advanced/items-sold-headers.html">items-sold-headers.html</a> (<a href="http://mdn.github.io/learning-area/html/tables/advanced/items-sold-headers.html">consúltalo en vivo</a>).</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p>Podrías aprender algo más sobre las tablas en HTML, pero en realidad te hemos proporcionado toda la información que necesitas saber en este momento. En este punto, es posible que desees ir y aprender sobre la aplicación de estilo a tablas HTML: consulta <a href="/es/docs/Learn/CSS/Building_blocks/Styling_tables">Aplicar estilo a las tablas</a>.</p> + +<div>{{PreviousMenuNext("Learn/HTML/Tables/Basics", "Learn/HTML/Tables/Structuring_planet_data", "Learn/HTML/Tables")}}</div> + +<div> +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/HTML/Tables/Basics">Conceptos básicos de las tablas en HTML</a></li> + <li><a href="/en-US/docs/Learn/HTML/Tables/Advanced">Funciones avanzadas de las tablas HTML y accesibilidad</a></li> + <li><a href="/en-US/docs/Learn/HTML/Tables/Structuring_planet_data">Estructuración de datos planetarios </a></li> +</ul> +</div> diff --git a/files/es/learn/html/tablas/index.html b/files/es/learn/html/tablas/index.html new file mode 100644 index 0000000000..7d04eb0cbf --- /dev/null +++ b/files/es/learn/html/tablas/index.html @@ -0,0 +1,34 @@ +--- +title: Tablas HTML +slug: Learn/HTML/Tablas +translation_of: Learn/HTML/Tables +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Una tarea muy común en HTML es la estructuración de datos, y para esto hay múltiples elementos y atributos. Esto unido a un poco de CSS, hace que en HTML sea sencillo mostrar tablas con información sobre tu horario escolar, los horarios de una piscina local o las estadisticas de tu equipo de dinosaurios o fútbol preferido. Este módulo te guiará en todo lo que necesitas saber sobre la estructuración tabular de datos en HTML.</p> + +<h2 id="Requisitos_previos">Requisitos previos</h2> + +<p>Antes de comenzar este módulo, deberías de saber las cosas básicas de HTML — ver <a href="https://developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML">Introducción a HTML</a>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si estas trabjando en un ordenador/tableta/otro dispositivo en el que no puedes crear tus propios archivos, puedes probar la mayoría de ejemplos online en webs como <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<p>Este módulo contiene los siguientes artículos:</p> + +<dl> + <dt><a href="/en-US/docs/Learn/HTML/Tables/Basics">Comenzando con tablas HTML</a></dt> + <dd>Este artículo te introduce en las tablas HTML , cubriendo las cosas más basicas como las líneas y las celdas, encabezados, crear celdas de multiples líneas y columnas, y como agrupar todas las celdas en una columna con fines estilisticos.</dd> + <dt><a href="/en-US/docs/Learn/HTML/Tables/Advanced">Características avanzadas y accesibilidad en tablas HTML</a></dt> + <dd>En el segundo artículo de este módulo, veremos algunas características avanzadas de las tablas HTML — como subtítulos/resumenes y agrupar líneas en la cabeza, cuerpo y pie de la tabla — además de realizar tablas accesibles para aquellos usuarios con problemas de visión.</dd> +</dl> + +<h2 id="Evaluación">Evaluación</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/HTML/Tables/Structuring_planet_data">Estructurar datos planetarios</a></dt> + <dd>En nuestra evaluación, te proporcionamos datos sobre los planetas de nuestro sistemas solar y tu los estructurarás en una tabla HTML.</dd> +</dl> diff --git a/files/es/learn/html/tablas/structuring_planet_data/index.html b/files/es/learn/html/tablas/structuring_planet_data/index.html new file mode 100644 index 0000000000..e9868bb95a --- /dev/null +++ b/files/es/learn/html/tablas/structuring_planet_data/index.html @@ -0,0 +1,72 @@ +--- +title: 'Evaluación: Estructurando datos planetarios' +slug: Learn/HTML/Tablas/Structuring_planet_data +translation_of: Learn/HTML/Tables/Structuring_planet_data +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}</div> + +<p class="summary">En nuestra evaluación te proporcionamos datos sobre los planetas de nuestro sistema solar y tu los estructurarás en una tabla HTML.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Antes de comenzar esta evaluación deberías de haber leído los artículos de este módulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprobar si has comprendido las tablas HTML y las características asociadas.</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_incio">Punto de incio</h2> + +<p>Para comenzar esta evaluación, crea una copia local de <a href="https://github.com/mdn/learning-area/blob/master/html/tables/assessment-start/blank-template.html">blank-template.html</a>, <a href="https://github.com/mdn/learning-area/blob/master/html/tables/assessment-start/minimal-table.css">minimal-table.css</a>, y <a href="https://github.com/mdn/learning-area/blob/master/html/tables/assessment-start/planets-data.txt">planets-data.txt</a> en una nueva carpeta de tu ordenador.</p> + +<div class="note"> +<p><strong>Nota</strong>: Como alternativa, puedes usar una web como <a class="external external-icon" href="https://jsbin.com/">JSBin</a> o <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> para realizar tu evaluación. Puedes pegar el HTML, CSS y JavaScript en uno de estos editores online. Si el editor online que estas usando no tiene paneles separados para JavaScript/CSS, sientete libre de ponerlos en línea dentro del mismo HTML mediante el uso de <code><script></code>/<code><style></code>.</p> +</div> + +<h2 id="Resumen_del_proyecto">Resumen del proyecto</h2> + +<p>Estás trabajando en la escuela; tus estudiantes están estudiando los planetas de nuestro sistema solar y quieres proporcionarles una forma sencilla de seguir los datos para buscar hechos sobre los planetas. Una tabla HTML sería ideal — tienes que coger los datos que tienes disponibles y convertirlos en una tabla siguiendo los pasos de abajo.</p> + +<p>La tabla finalizada debería de verse así:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14609/assessment-table.png" style="display: block; margin: 0 auto;"></p> + +<p>También puedes ver el ejemplo <a href="https://mdn.github.io/learning-area/html/tables/assessment-finished/planets-data.html">aquí</a> (no mires el código fuente — ¡no hagas trampas!)</p> + +<ul> +</ul> + +<h2 id="Pasos_para_completarlo">Pasos para completarlo</h2> + +<p>Los siguientes pasos describen lo que necesitas para completar el ejemplo de la tabla. Todos los datos que necesitarás están en el archivo <code>planets-data.txt</code>.<font face="consolas, Liberation Mono, courier, monospace"> </font>Si tienes problemas para visualizar los datos, mira el ejemplo de arriba o intentalo dibujando un diagrama.</p> + +<ol> + <li>Abre tu copia de <code>blank-template.html</code>, y comienza la tabla dándole un contenedor exterior, una cabecera y un cuerpo. No necesitas un pie de tabla en este ejemplo.</li> + <li>Añade el subtítulo proporcionado a tu tabla.</li> + <li>Añade una línea a la cabecera que contenga todos los encabezados de columna.</li> + <li>Crea todas las líneas con su contenido, asegurandote marcar como cabecera aquellas celdas que lo sean.</li> + <li>Asegurate de que el contenido esta insertado en las celdas correctas — en los datos del .txt, cada línea del planeta esta al lado de su planeta asociado.</li> + <li>Añade atributos para que las líneas y columnas del encabezado no se puedan confundir con las líneas, columnas o grupos de líneas a las que encabezan.</li> + <li>Añade un borde negro alrededor de la columna que contiene los nombres de los planetas y sus encabezados.</li> +</ol> + +<h2 id="Pistas_y_consejos">Pistas y consejos</h2> + +<ul> + <li>La primera celda de la línea de enbezado tiene que estar en blanco y unir dos columnas.</li> + <li>Los encabezados de la filas agrupadas (p. ej. <em>Jovian planets</em>) que están a la izquierda de los encabezados de nombres de planetas (p. ej. <em>Saturn</em>) son algo complicados de resolver — asegurate de que cada uno agrupa el número correcto de líneas y columnas</li> + <li>Una manera de asociar encabezados con sus líneas/columnas es mucha más fácil que la otra.</li> +</ul> + +<h2 id="Evaluación">Evaluación</h2> + +<p>Si estas siguiendo esta evaluación como parte de un curso organizado, deberías de ser capaz de entregar tu trabajo a tu profesor(a)/mentor para ver la puntuación. Si estas aprendiendo por tu cuenta, puedes obtener la guía de puntuación preguntando en <a href="https://discourse.mozilla-community.org/t/learning-web-development-marking-guides-and-questions/16294">Learning Area Discourse thread</a> o en el canal IRC <a href="irc://irc.mozilla.org/mdn">#mdn</a> en <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Intenta hacer el ejercicio primero — ¡haciendo trampas no aprenderás nada!</p> + +<p>{{PreviousMenu("Learn/HTML/Tables/Advanced", "Learn/HTML/Tables")}}</p> diff --git a/files/es/learn/index.html b/files/es/learn/index.html new file mode 100644 index 0000000000..a032b43e2d --- /dev/null +++ b/files/es/learn/index.html @@ -0,0 +1,135 @@ +--- +title: Aprende sobre desarrollo web +slug: Learn +tags: + - Ayuda + - CSS + - HTML + - Inicio + - Landing + - Principiante + - TopicStub + - Web +translation_of: Learn +--- +<p>{{LearnSidebar}}</p> + +<p class="summary">¡Hola! Bienvenido al área de aprendizaje de MDN. Si quieres aprender a crear tus propias páginas web, sitios o aplicaciones, has venido al lugar indicado.</p> + +<p>El objetivo de esta área de MDN no es llevarte de «principiante» a «experto», sino de «principiante» a «cómodo». A partir de ese punto, deberías poder comenzar a abrirte camino, aprendiendo del {{web.link("/es/", "resto de MDN")}} y de otras fuentes de niveles intermedio hasta avanzado, las cuales asumen que tienes un vasto conocimiento previamente adquirido.</p> + +<p>Si eres del todo un principiante, el desarrollo web puede ser un reto —pero no te preocupes, te llevaremos de la mano y te proveeremos de suficientes detalles para hacerte sentir cómodo y que aprendas los temas apropiadamente—. Para que te sientas como en casa, ya seas un estudiante (por tu cuenta o como parte de un grupo), un maestro buscando material para sus clases, un aficionado o alguien que simplemente desea entender mejor cómo funcionan las tecnologías web.</p> + +<h2 id="Novedades">Novedades</h2> + +<p>El contenido del área de aprendizaje se amplía con regularidad. Se han comenzado a guardar {{web.link("/es/docs/Learn/Release_notes", "notas de publicación del área de aprendizaje")}} para mostrar lo que ha cambiado. ¡Revísalas frecuentemente para mantenerte actualizado!</p> + +<p>Si tienes preguntas sobre temas que te gustaría que se abordaran o te parece que faltan, envía un mensaje en el <a href="https://discourse.mozilla.org/c/mdn">Foro de discusión</a>, de la comunidad Mozilla (sitio en inglés).</p> + +<div class="in-page-callout webdev"> +<h3 id="¿Quieres_convertirte_en_un_desarrollador_de_interfaz_de_usuario_web">¿Quieres convertirte en un desarrollador de interfaz de usuario web?</h3> + +<p>Hemos elaborado un curso que incluye toda la información esencial que necesitas para alcanzar tu objetivo.</p> + +<p><a class="cta primary" href="/docs/Learn/Front-end_web_developer">Empieza aquí</a></p> +</div> + +<h2 id="Dónde_empezar">Dónde empezar</h2> + +<p>Para continuar, piensa cuál de las siguientes afirmaciones te describe mejor y ve a la página de inicio enlazada:</p> + +<ul class="card-grid"> + <li><span>Soy un principiante</span>: ¡Bienvenido! Si eres un completo novel en desarrollo web, definitivamente el mejor lugar para empezar es el módulo {{web.link("/es/docs/Learn/Getting_started_with_the_web", "Primeros pasos en la web")}}. Una introducción práctica que te dará las bases necesarias para iniciar y avanzar en el desarrollo web.</li> + <li><span>Conozco la web</span>: ¡Muy bien! Si ya tienes un poco de conocimiento en ese caso te sugerimos profundizar en el corazón de las tecnologías web. El siguiente paso es conocer en detalle {{Glossary("HTML")}} y {{Glossary("CSS")}}: empieza con el módulo de introducción a {{web.link("/es/docs/Learn/HTML", "Introducción a HTML")}} y sigue con el módulo de {{web.link("/es/docs/Learn/CSS","primeros pasos en CSS")}}.</li> + <li><span>Me interesa javascript</span>: Si ya te sientes cómodo con el HTML y el CSS, o principalmente estás interesado en la codificación, querrás pasar al desarrollo de {{Glossary("JavaScript")}} o al desarrollo de lado del servidor. Comienza con los módulos de {{web.link("/es/docs/Learn/JavaScript/First_steps", "primeros pasos con JavaScript")}} y {{web.link("/es/docs/Learn/Server-side/Primeros_pasos", "primeros pasos en la programación de lado del servidor")}}.</li> + <li><span>Soy experto en la web</span>: ¡Excelente! Después de dominar los fundamentos del HTML, CSS y JavaScript puedes estar interesado en explorar las {{web.link("/es/docs/Web/Guide", "Guías avanzadas")}} y {{web.link("/es/docs/Web/Tutoriales", "Tutoriales")}}. Otra excelente idea es aprender sobre las {{web.link("/es/docs/Learn/Tools_and_testing/Understanding_client-side_tools", "herramientas de desarrollo web de lado del cliente")}} y luego considerar ahondar en los {{web.link("/es/docs/Learn/Tools_and_testing/Client-side_JavaScript_frameworks", "marcos de desarrollo («frameworks») de JavaScript de lado del cliente")}}, y la {{web.link("/es/docs/Learn/Server-side", "Programación de sitios web de lado del servidor")}}. Finalmente deberías considerar {{web.link("/es/docs/Learn/como_Contribuir", "Contribuir al Área de Aprendizaje")}}.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: el {{web.link("/es/docs/Glossary", "glosario")}} proporciona definición de términos. Además, si tienes una pregunta específica sobre el desarrollo web, la sección de {{web.link("/es/docs/Learn/Common_questions", "preguntas frecuentes")}} te puede brindar información de gran utilidad.</p> +</div> + +<p>{{LearnBox({"title":"Entrada aleatoria del glosario"})}}</p> + +<h2 id="Temas_tratados">Temas tratados</h2> + +<p>La siguiente es una lista de todos los temas tratados en el área de aprendizaje de MDN.</p> + +<dl> + <dt>{{web.link("/es/docs/Learn/Getting_started_with_the_web", "Primeros pasos en la web")}}</dt> + <dd>Proporciona una introducción práctica al desarrollo de la web para principiantes.</dd> + <dt>{{web.link("/es/docs/Learn/HTML", "HTML")}}</dt> + <dd>HTML es el lenguaje utilizado para estructurar las diferentes partes del contenido y definir su significado o propósito. Este tema enseña el HTML en detalle.</dd> + <dt>{{web.link("/es/docs/Learn/CSS", "CSS")}}</dt> + <dd>CSS es el lenguaje que se utiliza para estilizar y organizar el contenido web, así como para añadir comportamiento tal como la animación. Este tema proporciona una amplia cobertura de CSS.</dd> + <dt>{{web.link("/es/docs/Learn/JavaScript", "JavaScript — Scripts dinámicos de lado del cliente")}}</dt> + <dd>JavaScript es el lenguaje de scripts usado para añadir funcionalidad dinámica a las páginas web. Este tema enseña todo lo esencial necesario para sentirte cómodo con la escritura y comprensión de JavaScript.</dd> + <dt>{{web.link("/es/docs/Learn/HTML/Forms", "Formularios HTML")}}</dt> + <dd>Los formularios HTML son un potente instrumento para interactuar con los usuarios — frecuentemente se utilizan para reunir datos de los usuarios, o permitirte controlar la interfaz de usuario. En los artículos enumerados a continuación, se cubrirán todos los aspectos esenciales de la estructuración, estilizado e interacción con los formularios web.</dd> + <dt>{{web.link("/es/docs/Learn/Accessibility", "Accesibilidad")}}</dt> + <dd>La accesibilidad es la práctica de hacer que el contenido web esté disponible para tantas personas como sea posible, independientemente de la discapacidad, el dispositivo, la ubicación u otros factores diferenciadores. Este tema te da todo lo que necesitas saber.</dd> + <dt>{{web.link("/es/docs/Learn/Performance", "Rendimiento web — hace que los sitios web sean rápidos y responsivos")}}</dt> + <dd>El rendimiento web es el arte de asegurarte de que las aplicaciones web se descarguen rápidamente y respondan a la interacción del usuario, independientemente del ancho de banda, el tamaño de la pantalla, la red o las capacidades del dispositivo del usuario.</dd> + <dt>{{web.link("/es/docs/Learn/Herramientas_y_pruebas", "Herramientas y pruebas")}}</dt> + <dd>Este tema abarca las herramientas que los desarrolladores utilizan para facilitar su trabajo, como las herramientas de prueba entre navegadores, analizadores de errores de código fuente, formateadores, herramientas de transformación, sistemas de control de versiones, herramientas de despliegue y marcos de desarrollo JavaScript de lado del cliente.</dd> + <dt>{{web.link("/es/docs/Learn/Server-side", "Programación del lado servidor")}}</dt> + <dd>Aunque te concentres en el desarrollo web de lado del cliente, sigue siendo útil saber cómo funcionan los servidores y las características del código del lado del servidor. Este tema proporciona una introducción general a cómo funciona el lado del servidor y tutoriales detallados que muestran cómo construir una aplicación de lado del servidor utilizando dos marcos de desarrollo populares: Django (Python) y Express (Node.js).</dd> +</dl> + +<h2 id="Obtener_el_código_de_los_ejemplos">Obtener el código de los ejemplos</h2> + +<p>Todo el código de los ejemplos propuestos en el área de aprendizaje se encuentra disponible en <a href="https://github.com/mdn/learning-area//">GitHub</a>. Si quieres, los puedes copiar para tenerlos en tu ordenador, la manera más fácil es <a href="https://github.com/mdn/learning-area/archive/master.zip">descargar un ZIP de la última rama del código maestro</a>.</p> + +<p>Si prefieres copiar el código de una forma más flexible que te permita actualizaciones automáticas, puedes seguir estas instrucciones más complejas:</p> + +<ol> + <li><a href="https://git-scm.com/downloads">Instala Git</a> en tu máquina. Este es el sistema de control de versiones de software con el que trabaja GitHub principalmente.</li> + <li>Abre tu <a href="https://www.lifewire.com/how-to-open-command-prompt-2618089">consola de comandos</a> (Windows) o terminal (<a href="https://help.ubuntu.com/community/UsingTheTerminal">Linux</a>, <a href="http://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line">MacOS X</a>)</li> + <li>Para copiar el repositorio del área de aprendizaje a un directorio llamado <code>learning-area</code> en la ubicación actual, en la ventana de tu Terminal o en la línea de comandos, debes usar el siguiente comando. + <pre class="brush: bash notranslate">git clone https://github.com/mdn/learning-area</pre> + </li> + <li>Ahora puedes entrar en el directorio y encontrar todos los archivos que descargaste (posiblemente con el explorador de archivos o el <a href="https://es.wikipedia.org/wiki/Chdir">comando <code>cd</code></a>).</li> +</ol> + +<p>Puedes actualizar el repositorio <code>learning-area</code> con los últimos cambios que se hayan hecho a la versión principal en GitHub con los siguientes pasos:</p> + +<ol> + <li>En tu intérprete de comandos/terminal, ve dentro del directorio <code>learning-area</code> usando <code>cd</code>. Por ejemplo, si estuvieras en el directorio padre: + + <pre class="brush: bash notranslate">cd learning-area</pre> + </li> + <li>Puedes realizar actualizaciones al repositorio usando el siguiente comando: + <pre class="brush: bash notranslate">git pull</pre> + </li> +</ol> + +<h2 id="Contáctanos">Contáctanos</h2> + +<p>Si tienes alguna pregunta o deseas saber hacia dónde ir, Mozilla es una comunidad mundial de entusiastas de la web, incluyendo mentores y profesores, encantados de ayudarte. Ponte en contacto con ellos mediante WebMaker: Conoce y dialoga con los mentores y profesores en el <a href="https://discourse.mozilla.org/c/community-portal/mozilla-hispano/">Foro de Discusión en Español</a>. Encuentra <a href="https://foro.mozilla-hispano.org/c/difusion-eventos">Eventos</a> y aprende acerca de la Web con profesionales. Nos gustaría saber cualquier cosa de ti, si bien crees que algo está mal o falta en el sitio, o quieres solicitar nuevos temas de aprendizaje, solicitar ayuda con elementos que no comprendes o cualquier otra pregunta o inquietud que tengas.</p> + +<p>Si estás interesado en ayudar a desarrollar/mejorar el contenido, consulta {{web.link("/es/docs/Learn/Como_Contribuir", "cómo puedes ayudar")}} y, ¡pónte en contacto!; estaremos más que felices de hablar contigo, bien seas un alumno, un maestro, un desarrollador web experimentado o alguien más, interesado en ayudar a mejorar la experiencia de aprendizaje.</p> + +<h2 id="Ve_también">Ve también</h2> + +<dl> + <dt><a href="https://www.mozilla.org/es/newsletter/developer/">Boletín informativo para desarrolladores de Mozilla</a></dt> + <dd>Nuestro boletín para desarrolladores web, es un excelente recurso para todos los niveles de experiencia.</dd> + <dt><a href="https://learnjavascript.online/">Aprende JavaScript</a></dt> + <dd>Un excelente recurso para los aspirantes a desarrolladores web — aprende JavaScript en un entorno interactivo, con lecciones breves y pruebas interactivas, guiado por una evaluación automatizada. Las primeras 40 lecciones son gratuitas y el curso completo está disponible por un pequeño pago único.</dd> + <dt><a href="https://www.youtube.com/playlist?list=PLo3w8EB99pqLEopnunz-dOOBJ8t-Wgt2g">Web desmitificada</a></dt> + <dd>Una gran serie de videos que explican los fundamentos de la web, dirigida a principiantes absolutos en el desarrollo web. Creada por <a href="https://twitter.com/JeremiePat">Jérémie Patonnier</a>.</dd> + <dt><a href="https://www.codecademy.com/" rel="noopener">Codecademy</a></dt> + <dd>Un gran sitio interactivo para aprender lenguajes de programación desde cero.</dd> + <dt><a href="https://www.bitdegree.org/learn/">BitDegree</a></dt> + <dd>Teoría básica de la codificación con un proceso de aprendizaje ludificado. Enfocado principalmente a principiantes.</dd> + <dt><a href="https://code.org/">Code.org</a></dt> + <dd>Teoría y práctica de codificación básica, principalmente dirigida a niños/principiantes.</dd> + <dt><a href="https://exlskills.com/learn-en/courses">EXLskills</a></dt> + <dd>Cursos gratuitos y abiertos para aprender habilidades tecnológicas, con tutorías y aprendizaje basado en proyectos.</dd> + <dt><a href="https://www.freecodecamp.org/">freeCodeCamp.org</a></dt> + <dd>Sitio interactivo con tutoriales y proyectos para aprender desarrollo web.</dd> + <dt><a href="https://foundation.mozilla.org/en/initiatives/web-literacy/core-curriculum/">Mapa de alfabetización web</a></dt> + <dd>Un marco de desarrollo para la alfabetización web a nivel de entrada y las habilidades del siglo XXI, que también brindan acceso a actividades de enseñanza clasificadas por categoría.</dd> + <dt><a href="https://edabit.com/challenges/javascript">Edabit</a></dt> + <dd>Miles de desafíos interactivos de JavaScript.</dd> +</dl> diff --git a/files/es/learn/javascript/asynchronous/async_await/index.html b/files/es/learn/javascript/asynchronous/async_await/index.html new file mode 100644 index 0000000000..3487b11664 --- /dev/null +++ b/files/es/learn/javascript/asynchronous/async_await/index.html @@ -0,0 +1,411 @@ +--- +title: Haciendo la programación asíncrona más fácil con async y await +slug: Learn/JavaScript/Asynchronous/Async_await +translation_of: Learn/JavaScript/Asynchronous/Async_await +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}}</div> + +<p class="summary">Las incorporaciones más recientes al lenguaje JavaScript, son las <a href="/en-US/docs/Web/JavaScript/Reference/Statements/async_function">funciones async</a> y la palabra clave <code>await</code>, parte de la edición ECMAScript 2017 (véase <a href="/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_Next_support_in_Mozilla">ECMAScript Next support in Mozilla</a>). Estas características, básicamente, actúan como azúcar sintáctico, haciendo el código asíncrono fácil de escribir y leer más tarde. Hacen que el código asíncrono se parezca más al código síncrono de la vieja escuela, por lo que merece la pena aprenderlo. </p> + +<p>Este artículo le da lo que usted necesita saber. </p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Conocimientos básicos de informática, entender de manera razonable los fundamentos de JavaScript y entender el código asíncrono en general y las promesas. </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender las promesas y cómo usarlas</td> + </tr> + </tbody> +</table> + +<h2 id="Los_fundamentos_de_asyncawait">Los fundamentos de async/await</h2> + +<p>Hay dos partes a la hora de usar async/await en su código.</p> + +<h3 id="La_palabra_clave_async">La palabra clave async</h3> + +<p>Primero tenemos la palabra clave "async", que se coloca delante de la declaración de una función, para convertirla en función "async"(asíncrona). Una función "async", es una función que sabe cómo esperar la posibilidad de que la palabra clave "await" sea utilizada para invocar código asíncrono. </p> + +<p>Intenta escribir las siguientes líneas en la consola de tu navegador. </p> + +<pre class="brush: js notranslate">function hello() { return "Hello" }; +hello();</pre> + +<p>La función returna "Hello" — nada especial, verdad?</p> + +<p>Pero, qué pasa si convertimos esto en una función async? Trata lo siguiente:</p> + +<pre class="brush: js notranslate">async function hello() { return "Hello" }; +hello();</pre> + +<p>Ah!. Ahora cuando invocamos la función, retorna una promesa(promise). Esta es una de las características particulares de las funciones async — los valores que retornan están garantizados para ser convertidos en promesas.</p> + +<p>También puedes crear una <a href="/en-US/docs/Web/JavaScript/Reference/Operators/async_function">expresión de función async</a>, así:</p> + +<pre class="brush: js notranslate">let hello = async function() { return "Hello" }; +hello();</pre> + +<p>Y puedes utilizar funciones flecha(arrow functions):</p> + +<pre class="brush: js notranslate">let hello = async () => { return "Hello" };</pre> + +<p>Todos estos hacen básicamente lo mismo.</p> + +<p>Para realmente consumir el valor retornado cuando la promesa se cumple, ya que se está devolviendo una promesa, podemos utilizar un bloque <code>then()</code>: </p> + +<pre class="brush: js notranslate">hello().then((value) => console.log(value))</pre> + +<p>o incluso sólo un shorthand como</p> + +<pre class="brush: js notranslate">hello().then(console.log)</pre> + +<p>Como vimos en el último artículo.</p> + +<p>La palabra clave <code>async</code> se añade a las funciones para decirles que devuelvan una promesa en lugar de devolver directamente el valor. Adicionamente, esto permite que las funciones síncronas eviten cualquier potencial sobrecarga que viene con correr con el soporte por usar <code>async</code>. Cuando una función es declarada <code>async</code> con sólo añadir la manipulación necesaria, el motor de JavaScript puede optimizar su programa por usted. Dulce!</p> + +<p>So the <code>async</code> keyword is added to functions to tell them to return a promise rather than directly returning the value. In addition, this lets synchronous functions avoid any potential overhead that comes with running with support for using <code>await</code>. By only adding the necessary handling when the function is declared <code>async</code>, the JavaScript engine can optimize your program for you. Sweet!</p> + +<h3 id="La_palabra_clave_await">La palabra clave await</h3> + +<p>La ventaja real de las funciones asincronas aparecen cuando las combinas con la palabra clave <a href="/en-US/docs/Web/JavaScript/Reference/Operators/await">await</a> — en efecto, <strong><code>await</code> solo trabaja dentro de las funciones async</strong>. Esta puede ser puesta frente a cualquier funcion async basada en una promesa para pausar tu codigo en esa linea hasta que se cumpla la promesa, entonces retorna el valor resultante. Mientras tanto, otro código que puede estar esperando una oportunidad para ejecutarse, puede hacerlo.</p> + +<p>Puedes usar <code>await</code> cuando llames cualquier funcion que retorna una Promesa, incluyendo funciones web API.</p> + +<p>Este es un ejemplo trivial:</p> + +<pre class="brush: js notranslate">async function hello() { + return greeting = await Promise.resolve("Hello"); +}; + +hello().then(alert);</pre> + +<p>Por supuesto, el ejemplo anterior no es muy util, aunque este sirve para ilustrar la syntaxis. Vamos a ver un ejemplo real.</p> + +<h2 id="Reescribiendo_el_código_de_las_promesas_con_asyncawait">Reescribiendo el código de las promesas con async/await</h2> + +<p>Let's look back at a simple fetch example that we saw in the previous article:</p> + +<pre class="brush: js notranslate">fetch('coffee.jpg') +.then(response => { + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } else { + return response.blob(); + } +}) +.then(myBlob => { + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}) +.catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); +});</pre> + +<p>By now, you should have a reasonable understanding of promises and how they work, but let's convert this to use async/await to see how much simpler it makes things:</p> + +<pre class="brush: js notranslate">async function myFetch() { + let response = await fetch('coffee.jpg'); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } else { + let myBlob = await response.blob(); + + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); + } +} + +myFetch() +.catch(e => { + console.log('There has been a problem with your fetch operation: ' + e.message); +});</pre> + +<p>It makes code much simpler and easier to understand — no more <code>.then()</code> blocks everywhere!</p> + +<p>Since an <code>async</code> keyword turns a function into a promise, you could refactor your code to use a hybrid approach of promises and await, bringing the second half of the function out into a new block to make it more flexible:</p> + +<pre class="brush: js notranslate">async function myFetch() { + let response = await fetch('coffee.jpg'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } else { + return await response.blob(); + } +} + +myFetch().then((blob) => { + let objectURL = URL.createObjectURL(blob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}).catch(e => console.log(e));</pre> + +<p>You can try typing in the example yourself, or running our <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await.html">live example</a> (see also the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await.html">source code</a>).</p> + +<h3 id="But_how_does_it_work">But how does it work?</h3> + +<p>You'll note that we've wrapped the code inside a function, and we've included the <code>async</code> keyword before the <code>function</code> keyword. This is necessary — you have to create an async function to define a block of code in which you'll run your async code; as we said earlier, <code>await</code> only works inside of async functions.</p> + +<p>Inside the <code>myFetch()</code> function definition you can see that the code closely resembles the previous promise version, but there are some differences. Instead of needing to chain a <code>.then()</code> block on to the end of each promise-based method, you just need to add an <code>await</code> keyword before the method call, and then assign the result to a variable. The <code>await</code> keyword causes the JavaScript runtime to pause your code on this line, allowing other code to execute in the meantime, until the async function call has returned its result. Once that's complete, your code continues to execute starting on the next line. For example:</p> + +<pre class="brush: js notranslate">let response = await fetch('coffee.jpg');</pre> + +<p>The response returned by the fulfilled <code>fetch()</code> promise is assigned to the <code>response</code> variable when that response becomes available, and the parser pauses on this line until that occurs. Once the response is available, the parser moves to the next line, which creates a <code><a href="/en-US/docs/Web/API/Blob">Blob</a></code> out of it. This line also invokes an async promise-based method, so we use <code>await</code> here as well. When the result of operation returns, we return it out of the <code>myFetch()</code> function.</p> + +<p>This means that when we call the <code>myFetch()</code> function, it returns a promise, so we can chain a <code>.then()</code> onto the end of it inside which we handle displaying the blob onscreen.</p> + +<p>You are probably already thinking "this is really cool!", and you are right — fewer <code>.then()</code> blocks to wrap around code, and it mostly just looks like synchronous code, so it is really intuitive.</p> + +<h3 id="Adding_error_handling">Adding error handling</h3> + +<p>And if you want to add error handling, you've got a couple of options.</p> + +<p>You can use a synchronous <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch">try...catch</a></code> structure with <code>async</code>/<code>await</code>. This example expands on the first version of the code we showed above:</p> + +<pre class="brush: js notranslate">async function myFetch() { + try { + let response = await fetch('coffee.jpg'); + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } else { + let myBlob = await response.blob(); + let objectURL = URL.createObjectURL(myBlob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); + } + } catch(e) { + console.log(e); + } +} + +myFetch();</pre> + +<p>The <code>catch() {}</code> block is passed an error object, which we've called <code>e</code>; we can now log that to the console, and it will give us a detailed error message showing where in the code the error was thrown.</p> + +<p>If you wanted to use the second (refactored) version of the code that we showed above, you would be better off just continuing the hybrid approach and chaining a <code>.catch()</code> block onto the end of the <code>.then()</code> call, like this:</p> + +<pre class="brush: js notranslate">async function myFetch() { + let response = await fetch('coffee.jpg'); + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } else { + return await response.blob(); + } +} + +myFetch().then((blob) => { + let objectURL = URL.createObjectURL(blob); + let image = document.createElement('img'); + image.src = objectURL; + document.body.appendChild(image); +}) +.catch((e) => + console.log(e) +);</pre> + +<p>This is because the <code>.catch()</code> block will catch errors occurring in both the async function call and the promise chain. If you used the <code>try</code>/<code>catch</code> block here, you might still get unhandled errors in the <code>myFetch()</code> function when it's called.</p> + +<p>You can find both of these examples on GitHub:</p> + +<ul> + <li><a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html">simple-fetch-async-await-try-catch.html</a> (see <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-try-catch.html">source code</a>)</li> + <li><a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html">simple-fetch-async-await-promise-catch.html</a> (see <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/simple-fetch-async-await-promise-catch.html">source code</a>)</li> +</ul> + +<h2 id="Awaiting_a_Promise.all">Awaiting a Promise.all()</h2> + +<p>async/await is built on top of <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promises</a>, so it's compatible with all the features offered by promises. This includes <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all">Promise.all()</a></code> — you can quite happily await a <code>Promise.all()</code> call to get all the results returned into a variable in a way that looks like simple synchronous code. Again, let's return to <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/promises/promise-all.html">an example we saw in our previous article</a>. Keep it open in a separate tab so you can compare and contrast with the new version shown below.</p> + +<p>Converting this to async/await (see <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-all-async-await.html">live demo</a> and <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-all-async-await.html">source code</a>), this now looks like so:</p> + +<pre class="brush: js notranslate">async function fetchAndDecode(url, type) { + let response = await fetch(url); + + let content; + + if (!response.ok) { + throw new Error(`HTTP error! status: ${response.status}`); + } else { + if(type === 'blob') { + content = await response.blob(); + } else if(type === 'text') { + content = await response.text(); + } + + return content; + } + +} + +async function displayContent() { + let coffee = fetchAndDecode('coffee.jpg', 'blob'); + let tea = fetchAndDecode('tea.jpg', 'blob'); + let description = fetchAndDecode('description.txt', 'text'); + + let values = await Promise.all([coffee, tea, description]); + + let objectURL1 = URL.createObjectURL(values[0]); + let objectURL2 = URL.createObjectURL(values[1]); + let descText = values[2]; + + let image1 = document.createElement('img'); + let image2 = document.createElement('img'); + image1.src = objectURL1; + image2.src = objectURL2; + document.body.appendChild(image1); + document.body.appendChild(image2); + + let para = document.createElement('p'); + para.textContent = descText; + document.body.appendChild(para); +} + +displayContent() +.catch((e) => + console.log(e) +);</pre> + +<p>You'll see that the <code>fetchAndDecode()</code> function has been converted easily into an async function with just a few changes. See the <code>Promise.all()</code> line:</p> + +<pre class="brush: js notranslate">let values = await Promise.all([coffee, tea, description]);</pre> + +<p>By using <code>await</code> here we are able to get all the results of the three promises returned into the <code>values</code> array, when they are all available, in a way that looks very much like sync code. We've had to wrap all the code in a new async function, <code>displayContent()</code>, and we've not reduced the code by a lot of lines, but being able to move the bulk of the code out of the <code>.then()</code> block provides a nice, useful simplification, leaving us with a much more readable program.</p> + +<p>For error handling, we've included a <code>.catch()</code> block on our <code>displayContent()</code> call; this will handle errors ocurring in both functions.</p> + +<div class="blockIndicator note"> +<p><strong>Note</strong>: It is also possible to use a sync <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/try...catch#The_finally_clause">finally</a></code> block within an async function, in place of a <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/finally">.finally()</a></code> async block, to show a final report on how the operation went — you can see this in action in our <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/promise-finally-async-await.html">live example</a> (see also the <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/promise-finally-async-await.html">source code</a>).</p> +</div> + +<h2 id="The_downsides_of_asyncawait">The downsides of async/await</h2> + +<p>Async/await is really useful to know about, but there are a couple of downsides to consider.</p> + +<p>Async/await makes your code look synchronous, and in a way it makes it behave more synchronously. The <code>await</code> keyword blocks execution of all the code that follows until the promise fulfills, exactly as it would with a synchronous operation. It does allow other tasks to continue to run in the meantime, but your own code is blocked.</p> + +<p>This means that your code could be slowed down by a significant number of awaited promises happening straight after one another. Each <code>await</code> will wait for the previous one to finish, whereas actually what you want is for the promises to begin processing simultaneously, like they would do if we weren't using async/await.</p> + +<p>There is a pattern that can mitigate this problem — setting off all the promise processes by storing the <code>Promise</code> objects in variables, and then awaiting them all afterwards. Let's have a look at some examples that prove the concept.</p> + +<p>We've got two examples available — <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/slow-async-await.html">slow-async-await.html</a> (see <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/slow-async-await.html">source code</a>) and <a href="https://mdn.github.io/learning-area/javascript/asynchronous/async-await/fast-async-await.html">fast-async-await.html</a> (see <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/async-await/fast-async-await.html">source code</a>). Both of them start off with a custom promise function that fakes an async process with a <code><a href="/en-US/docs/Web/API/WindowOrWorkerGlobalScope/setTimeout">setTimeout()</a></code> call:</p> + +<pre class="brush: js notranslate">function timeoutPromise(interval) { + return new Promise((resolve, reject) => { + setTimeout(function(){ + resolve("done"); + }, interval); + }); +};</pre> + +<p>Then each one includes a <code>timeTest()</code> async function that awaits three <code>timeoutPromise()</code> calls:</p> + +<pre class="brush: js notranslate">async function timeTest() { + ... +}</pre> + +<p>Each one ends by recording a start time, seeing how long the <code>timeTest()</code> promise takes to fulfill, then recording an end time and reporting how long the operation took in total:</p> + +<pre class="brush: js notranslate">let startTime = Date.now(); +timeTest().then(() => { + let finishTime = Date.now(); + let timeTaken = finishTime - startTime; + alert("Time taken in milliseconds: " + timeTaken); +})</pre> + +<p>It is the <code>timeTest()</code> function that differs in each case.</p> + +<p>In the <code>slow-async-await.html</code> example, <code>timeTest()</code> looks like this:</p> + +<pre class="brush: js notranslate">async function timeTest() { + await timeoutPromise(3000); + await timeoutPromise(3000); + await timeoutPromise(3000); +}</pre> + +<p>Here we simply await all three <code>timeoutPromise()</code> calls directly, making each one alert for 3 seconds. Each subsequent one is forced to wait until the last one finished — if you run the first example, you'll see the alert box reporting a total run time of around 9 seconds.</p> + +<p>In the <code>fast-async-await.html</code> example, <code>timeTest()</code> looks like this:</p> + +<pre class="brush: js notranslate">async function timeTest() { + const timeoutPromise1 = timeoutPromise(3000); + const timeoutPromise2 = timeoutPromise(3000); + const timeoutPromise3 = timeoutPromise(3000); + + await timeoutPromise1; + await timeoutPromise2; + await timeoutPromise3; +}</pre> + +<p>Here we store the three <code>Promise</code> objects in variables, which has the effect of setting off their associated processes all running simultaneously.</p> + +<p>Next, we await their results — because the promises all started processing at essentially the same time, the promises will all fulfill at the same time; when you run the second example, you'll see the alert box reporting a total run time of just over 3 seconds!</p> + +<p>You'll have to test your code carefully, and bear this in mind if performance starts to suffer.</p> + +<p>Another minor inconvenience is that you have to wrap your awaited promises inside an async function.</p> + +<h2 id="Asyncawait_class_methods">Async/await class methods</h2> + +<p>As a final note before we move on, you can even add <code>async</code> in front of class/object methods to make them return promises, and <code>await</code> promises inside them. Take a look at the <a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance#ECMAScript_2015_Classes">ES class code we saw in our object-oriented JavaScript article</a>, and then look at our modified version with an <code>async</code> method:</p> + +<pre class="brush: js notranslate">class Person { + constructor(first, last, age, gender, interests) { + this.name = { + first, + last + }; + this.age = age; + this.gender = gender; + this.interests = interests; + } + + async greeting() { + return await Promise.resolve(`Hi! I'm ${this.name.first}`); + }; + + farewell() { + console.log(`${this.name.first} has left the building. Bye for now!`); + }; +} + +let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']);</pre> + +<p>The first class method could now be used something like this:</p> + +<pre class="brush: js notranslate">han.greeting().then(console.log);</pre> + +<h2 id="Browser_support">Browser support</h2> + +<p>One consideration when deciding whether to use async/await is support for older browsers. They are available in modern versions of most browsers, the same as promises; the main support problems come with Internet Explorer and Opera Mini.</p> + +<p>If you want to use async/await but are concerned about older browser support, you could consider using the <a href="https://babeljs.io/">BabelJS</a> library — this allows you to write your applications using the latest JavaScript and let Babel figure out what changes if any are needed for your user’s browsers. On encountering a browser that does not support async/await, Babel's polyfill can automatically provide fallbacks that work in older browsers.</p> + +<h2 id="Conclusion">Conclusion</h2> + +<p>And there you have it — async/await provide a nice, simplified way to write async code that is simpler to read and maintain. Even with browser support being more limited than other async code mechanisms at the time of writing, it is well worth learning and considering for use, both for now and in the future.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Asynchronous/Promises", "Learn/JavaScript/Asynchronous/Choosing_the_right_approach", "Learn/JavaScript/Asynchronous")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">General asynchronous programming concepts</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducing asynchronous JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">Cooperative asynchronous JavaScript: Timeouts and intervals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Graceful asynchronous programming with Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Making asynchronous programming easier with async and await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Choosing the right approach</a></li> +</ul> diff --git a/files/es/learn/javascript/asynchronous/concepts/index.html b/files/es/learn/javascript/asynchronous/concepts/index.html new file mode 100644 index 0000000000..df3feb2117 --- /dev/null +++ b/files/es/learn/javascript/asynchronous/concepts/index.html @@ -0,0 +1,162 @@ +--- +title: General asynchronous programming concepts +slug: Learn/JavaScript/Asynchronous/Concepts +tags: + - Aprender + - Hilos + - JavaScript + - Promesas + - Threads + - bloques +translation_of: Learn/JavaScript/Asynchronous/Concepts +--- +<div>{{LearnSidebar}}{{NextMenu("Learn/JavaScript/Asynchronous/Introducing", "Learn/JavaScript/Asynchronous")}}</div> + +<p>En este artículo, repasaremos una serie de conceptos importantes relacionados con la programación asincrónica y cómo se ve esto en los navegadores web y JavaScript. Debe comprender estos conceptos antes de trabajar con los demás artículos del módulo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td>Literatura básica de computadora, un razonable entendimiento de los fundamentos de JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender los conceptos básicos detrás de la programación asincrónica, y cómo se manifiesta en los exploradores web y JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Asincrónico">¿Asincrónico?</h2> + +<p>Normalmente, el código de un programa determinado se ejecuta directamente, y solo sucede una cosa a la vez. Si una función se basa en el resultado de otra función, tiene que esperar a que la otra función termine y regrese, y hasta que eso suceda, todo el programa se detiene esencialmente desde la perspectiva del usuario.</p> + +<p>Los usuarios de Mac, por ejemplo, a veces experimentan esto como un cursor giratorio multicolor (o "beachball" - "bola de playa" - como es llamado frecuentemente). Este cursor es la manera que tiene el sistema operativo de decir "el actual programa que está usando tiene que parar y esperar que algo termine, y está tomando tanto tiempo que me preocupa que pienses qué está sucediendo."</p> + +<p><img alt="Multi-colored macOS beachball busy spinner" src="https://mdn.mozillademos.org/files/16577/beachball.jpg" style="display: block; float: left; height: 256px; margin: 0px 30px 0px 0px; width: 250px;"></p> + +<p>Esto es una experiencia frustrante y no es un buen uso del poder de procesamiento de una computadora - especialmente en una era donde las computadoras tienen múltiples procesadores disponibles. No tiene sentido sentarse allí a esperar algo cuando podrías dejar que la otra tarea se ejecute en otro procesador y le notifique cuando termine. Mientras tanto, esto le permitiría terminar otros trabajos, lo cual es la base de la <strong>programación asincrónica</strong>. Depende del entorno de programación que esté usando (exploradores web, en caso de desarrollo web) proveer de APIs que le permitan ejecutar dichas tareas de manera asincrónica.</p> + +<h2 id="Código_de_bloqueo_Blocking">Código de bloqueo (Blocking)</h2> + +<p>Las técnicas asincrónicas son muy útiles, particularmente en programación web. Cuando una app web se ejeucta en el navegador y ejecuta un gran bloque de código sin retornar el control al navegador, este mismo puede parecer que se congela. Esto es llamado <strong>blocking</strong>; el navegador es bloqueado para que el usuario pueda seguir interactuando y realizando otras tareas hasta que la app web retorne el control sobre el procesador.</p> + +<p>Vamos a ver algunos ejemplos que muestren lo que significa blocking.</p> + +<p>En nuestro ejemplo <a href="https://github.com/mdn/learning-area/tree/master/javascript/asynchronous/introducing/simple-sync.html">simple-sync.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync.html">véalo en vivo</a>), agregamos un detector del evento click ("click event listener") a un botón con el fin de que cuando sea clickeado, ejecute una operación de un gran consumo de tiempo (calcula 10 millones de fechas y luego muestra la última en la consola) y luego agrega un párrafo al DOM:</p> + +<pre class="brush: js notranslate">const btn = document.querySelector('button'); +btn.addEventListener('click', () => { + let myDate; + for(let i = 0; i < 10000000; i++) { + let date = new Date(); + myDate = date + } + + console.log(myDate); + + let pElem = document.createElement('p'); + pElem.textContent = 'This is a newly-added paragraph.'; + document.body.appendChild(pElem); +});</pre> + +<p>Cuando ejecute el ejemplo, abra su consola de JavaScript y haga click en el botón — notará que el párrafo no aparece hasta que las fechas hayan sido calculadas en su totalidad y el mensaje en la consola haya sido logueado. EL código se ejecuta en el orden en que aparece (de arriba hacia abajo), y la última operación no se ejecuta hasta que la anterior haya terminado.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: El ejemplo anterior es poco realista. ¡Nunca se van a calcular 10 millones de fechas en una app web real! Sin embargo, sirve para dar una idea básica.</p> +</div> + +<p>En nuestro segundo ejemplo, <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-ui-blocking.html">simple-sync-ui-blocking.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-ui-blocking.html">véalo en vivo</a>), se simula algo un poco más realista con el que se puede encontrar en una página real. Se bloquea la interacción del usuario con la carga ("rendering") de la UI. En este ejemplo, se tienen dos botones:</p> + +<ul> + <li>Un botón "Fill canvas" que cuando es clickeado llena con 1 millón de círculos azules al {{htmlelement("canvas")}} disponible.</li> + <li>Un botón "Click me for alert" que cuando es clickeado muestra un mensaje de alerta.</li> +</ul> + +<pre class="brush: js notranslate">function expensiveOperation() { + for(let i = 0; i < 1000000; i++) { + ctx.fillStyle = 'rgba(0,0,255, 0.2)'; + ctx.beginPath(); + ctx.arc(random(0, canvas.width), random(0, canvas.height), 10, degToRad(0), degToRad(360), false); + ctx.fill() + } +} + +fillBtn.addEventListener('click', expensiveOperation); + +alertBtn.addEventListener('click', () => + alert('You clicked me!') +);</pre> + +<p>Si se clickea el primer botón y rápidamente se clickea el segundo, se verá que la alerta no aparece hasta que los círculos hayan terminado de representarse. La primer operación blockea a la segunda hasta que esta haya terminado de ejecutarse.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: OK, nuestro caso es feo y estamos fingiendo el efecto de bloqueo, pero es un problema común con el que los desarrolladores de aplicaciones reales batallan todo el tiempo.</p> +</div> + +<p>¿Por qué es esto? La respuesta es porque JavaScript, en general, es de <strong>"un solo hilo" (single-threaded)</strong>. En este punto, se tiene que introduce el concepto de <strong>"hilos" (threads)</strong>.</p> + +<h2 id="Threads">Threads</h2> + +<p>Un <strong>hilo (thread)</strong> es básicamente un proceso simple que un programa puede usar para completar tareas ("tasks"). Cada hilo solo puede realizar una tarea a la vez:</p> + +<pre class="notranslate">Task A --> Task B --> Task C</pre> + +<p>Cada tarea se va a ejecutar secuencialmente; una tarea tiene que completarse antes de que la próxima empiece.</p> + +<p>Como se dijo previamente, muchas computadores actualmente tienen múltiples procesadores, por lo que pueden realizar múltiples tareas a la vez. Los lenguajes de programación que pueden manejar múltiples hilos pueden usar múltiples procesadores para completar múltiples tareas en simultáneo. </p> + +<pre class="notranslate">Thread 1: Task A --> Task B +Thread 2: Task C --> Task D</pre> + +<h3 id="JavaScript_es_single-threaded">JavaScript es single-threaded</h3> + +<p>JavScript es tradicionalmente single-threaded. Aún con múltiples procesadores, solo se puede ejecutar tareas en un solo hilo, llamado el <strong>hilo principal (main thread)</strong>. El ejemplo de arriba se ejecuta de la siguiente manera:</p> + +<pre class="notranslate">Main thread: Render circles to canvas --> Display alert()</pre> + +<p>Después de un tiempo, JavaScript ganó algunas herramientas que ayudaron con dichos problemas. <a href="/en-US/docs/Web/API/Web_Workers_API">Web workers</a> permiten que se envíe parte del procesamiento de JavaScript a un hilo separado, llamado worker con el fin de que puedan ejecutar múltiples pedazos de JavaScript en simultáneo. Generalmente se usará un worker para ejectuar procesos de mucho consumo del hilo principal (main thread) con el fin de que no se bloquee la interacción del usuario.</p> + +<pre class="notranslate"> Main thread: Task A --> Task C +Worker thread: Expensive task B</pre> + +<p>Con esto en mente, miremos el ejemplo <a href="https://github.com/mdn/learning-area/blob/master/javascript/asynchronous/introducing/simple-sync-worker.html">simple-sync-worker.html</a> (<a href="https://mdn.github.io/learning-area/javascript/asynchronous/introducing/simple-sync-worker.html">véalo ejecutándose en vivo</a>) nuevamente con la consola de JavaScript del navegador abierta. Esto es una re-escritura del ejemplo anterior que calculaba 10 millones de fechas en hilos worker separados. Ahora si se clickea el botón, el navegador tiene permitido mostrar el párrafo antes de que las fechas haya terminado de calcularse. La primer operación ya no bloquea a la segunda.</p> + +<h2 id="Código_asincrónico">Código asincrónico</h2> + +<p>Los web workers son muy útiles, pero tienen limitaciones. La mayor es que no pueden acceder al {{Glossary("DOM")}} — no se puede logar que un worker modifique directamente algo de la UI. No se puede representar 1 millón de círculos azules en un worker; básicamente solo puede hacer el cálculo numérico.</p> + +<p>El segundo problema es que a pesar de que el código se ejecuta en un worker no es bloqueador, es simplemente sincrónico. Esto se convierte en un problema cuando una función depender en los resultados de múltiples procesos previos para funcionar. Considere el siguiente diagrama de hilos:</p> + +<pre class="notranslate">Main thread: Task A --> Task B</pre> + +<p>En este caso, digamos que la Tarea A (Task A) está haciendo algo como buscando una imagen de un servidor y la Tarea B (Task B) luego hace algo con la imagen, como aplicarle un filtro. Si se ejecuta la Tarea A y luego inmediatamente se trata de ejecutar la Tarea B, se obtendrá un error, porque la imagen todavía no estará disponible.</p> + +<pre class="notranslate"> Main thread: Task A --> Task B --> |Task D| +Worker thread: Task C -----------> | |</pre> + +<p>En este caso, digamos que la Tarea D hace uso de los resultados de la Tarea B y la Tarea C. Se se puede garantizar que esos resultados estarán disponibles al mismo tiempo, entonces tal vez estemos OK, pero es poco probable. Si la Tarea D trata de ejecutarse cuando uno de sus inputs no está disponible, disparará un error.</p> + +<p>Para arreglar dichos problemas, los navegadores nos permiten ejecutar ciertas operaciones asincrónicamente. Características como las <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a> (Promesas) permiten establecer la ejecución de una operación (por ejemplo, buscar una imagen desde un servidor), y luego esperar hasta que el resultado sea retornado antes de ejecutar otra operación. </p> + +<pre class="notranslate">Main thread: Task A Task B + Promise: |__async operation__|</pre> + +<p>Como la operación está sucediendo en otro lugar, el hilo principal no está bloqueado mientras la operación asincrónica está siendo procesada.</p> + +<p>Vamos a empezar a ver cómo se puede escribir código asincrónico en el próximo artículo. Cosas emocionantes, ¿eh? ¡Siga leyendo!</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>El diseño del software moderno gira cada más entorno a la programación asincrónica, para permiterle a los programas hacer más de una cosa a la vez. A medida que use nuevas y más poderosas APIs, encontrará más casos donde la única forma de realizar las cosas es asincrónicamente. Era muy difícil escribir el código asincrónico. Todavía lleva tiempo acostumbrarse, pero se ha vuelto mucho más sencillo. En el resto de este módulo, exploraremos porqué el código asincrónico importa y cómo diseñar código que evite algunos de los problemas que hemos descrito en este artículo.</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">Conceptos generales de programación asincrónica</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introducción a JavaScript asincrónico</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Timeouts_and_intervals">JavaScript asincrónico cooperativo: Timeouts e intervalos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Programación asincrónica elegante con Promesas</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Programación asincrónica más sencilla con async y await</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Eligiendo el correcto enfoque</a></li> +</ul> diff --git a/files/es/learn/javascript/asynchronous/index.html b/files/es/learn/javascript/asynchronous/index.html new file mode 100644 index 0000000000..b2fb697803 --- /dev/null +++ b/files/es/learn/javascript/asynchronous/index.html @@ -0,0 +1,43 @@ +--- +title: JavaScript asíncrono +slug: Learn/JavaScript/Asynchronous +translation_of: Learn/JavaScript/Asynchronous +--- +<div>{{LearnSidebar}}</div> + +<p class="summary"><span class="seoSummary">En este módulo echamos un vistazo a {{Glossary("JavaScript")}} {{Glossary("asíncrono")}}, por qué es importante y cómo se puede utilizar para manejar eficazmente las posibles operaciones de bloqueo, como recuperar recursos desde un servidor</span></p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>JavaScript asíncrono es un tema bastante avanzado, y se recomienda trabajar con los primeros pasos de JavaScript y los módulos de <a href="/en-US/docs/Learn/JavaScript/Building_blocks">bloques de construcción de JavaScript</a> antes de intentarlo.</p> + +<p>Si no está familiarizado con el concepto de programación asincrónica, definitivamente debe comenzar con el artículo <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">Conceptos generales de programación asincrónica</a> en este módulo. Si es así, probablemente pueda pasar al <a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">módulo Introducción a JavaScript asíncrono</a>.</p> + +<div class="note"> +<p><strong>Nota: </strong>Si está trabajando en una computadora / tableta / otro dispositivo donde no tiene la capacidad de crear sus propios archivos, puede probar (la mayoría de) los ejemplos de código en un programa de codificación en línea como <a href="http://jsbin.com/">JSBin</a> o <a href="https://glitch.com">Glitch</a></p> +</div> + +<h2 id="Guias">Guias</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Concepts">Conceptos generales de programación asincrónica</a></dt> + <dd> + <p>En este artículo revisaremos una serie de conceptos importantes relacionados con la programación asincrónica y cómo se ve esto en los navegadores web y JavaScript. Debe comprender estos conceptos antes de trabajar en los otros artículos del módulo.</p> + </dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Introducing">Introduciendo JavaScript asincrónico</a></dt> + <dd>En este artículo recapitulamos brevemente los problemas asociados con JavaScript síncrono, y echamos un primer vistazo a algunas de las diferentes técnicas de JavaScript asíncrono que encontrarás, mostrando cómo pueden ayudarnos a resolver tales problemas.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Loops_and_intervals">JavaScript asíncrono cooperativo: tiempos de espera e intervalos</a></dt> + <dd>Aquí observamos los métodos tradicionales que JavaScript tiene disponibles para ejecutar código de forma asíncrona después de que haya transcurrido un período de tiempo establecido, o en un intervalo regular (por ejemplo, un número establecido de veces por segundo), hablemos sobre para qué son útiles y observe su Problemas inherentes.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Promises">Manejo de operaciones asincrónas con Promises</a></dt> + <dd>Las promesas son una característica relativamente nueva de JavaScript que le permite diferir más acciones hasta que la acción anterior se haya completado o responder en caso de tener una falla o error durante su ejecución. Esto es realmente útil para configurar una secuencia de operaciones para que funcione correctamente. Este artículo te muestra cómo funcionan las promesas, dónde las verá en uso en una WebAPI y cómo escribir las tuyas de la manera adecuada.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Async_await">Hacer la programación asincróna más fácil con async y await</a> </dt> + <dd>Las promesas pueden ser algo complejas de configurar y comprender, por lo que los navegadores modernos han implementado funciones <code>async</code> y el operador de <code>await</code>. El primero permite que las funciones estándar se comporten implícitamente de forma asíncrona con las promesas, mientras que el segundo puede usarse dentro de las funciones <code>async</code> para esperar las promesas antes de que la función continúe. Esto hace que las promesas de encadenamiento sean más simples y fáciles de leer.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Asynchronous/Choosing_the_right_approach">Elegir el enfoque correcto</a></dt> + <dd>Para finalizar este módulo, consideraremos las diferentes técnicas y características de codificación que hemos discutido a lo largo de todo, y veremos cuáles deberias usar cuando, con recomendaciones y recordatorios de dificultades comunes, sea lo más apropiado.</dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://eloquentjavascript.net/11_async.html">Asynchronous Programming</a> from the fantastic <a href="https://eloquentjavascript.net/">Eloquent JavaScript</a> online book by Marijn Haverbeke.</li> +</ul> diff --git a/files/es/learn/javascript/building_blocks/bucle_codigo/index.html b/files/es/learn/javascript/building_blocks/bucle_codigo/index.html new file mode 100644 index 0000000000..e26509afc5 --- /dev/null +++ b/files/es/learn/javascript/building_blocks/bucle_codigo/index.html @@ -0,0 +1,923 @@ +--- +title: Bucles +slug: Learn/JavaScript/Building_blocks/Bucle_codigo +translation_of: Learn/JavaScript/Building_blocks/Looping_code +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">Los lenguajes de programación son muy útiles para completar rápidamente tareas repetitivas, desde múltimples cálculos básicos hasta cualquier otra situación en donde tengas un montón de elementos de trabajo similares que completar. Aquí vamos a ver las estructuras de bucles disponibles en JavaScript que pueden manejar tales necesidades.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de computación, entendimiento básico de HTML y CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender cómo usar bucles en JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Mantente_en_el_Bucle">Mantente en el Bucle</h2> + +<p>Bucles, bucles, bucles. Además de ser conocidos como un cereal de desayuno popular, montañas rusas y producción músical, también son un concepto muy importante en programación. Los bucles de programación están relacionados con todo lo referente a hacer una misma cosa una y otra vez — que se denomina como <strong>iteración </strong>en el idioma de programación.</p> + +<p>Consideremos el caso de un agricultor que se asegura de tener suficiente comida para alimentar a su familia durante la semana. Podría usar el siguiente bucle para lograr esto:</p> + +<p><br> + <img alt="" src="https://mdn.mozillademos.org/files/13755/loop_js-02-farm.png" style="display: block; margin: 0 auto;"></p> + +<p>Un bucle cuenta con una o más de las siguientes características:</p> + +<ul> + <li> Un <strong>contador,</strong> que se inicia con un determinado valor — este será el valor del punto inicial del bucle ("Inicio: No tengo comida",mirar arriba).</li> + <li>Una <strong>condicion de salida</strong>, que será el criterio bajo el cual, el bucle se romperá — normalmente un contador que alcanza un determinado valor. Aquí se ilustra como "¿Tengo suficiente comida?", arriba. Digamos que son necesarias 10 porciones de comida para alimentar a su familia.</li> + <li>Un <strong>iterador, </strong>que generalmente incrementa el valor del contador en una cantidad pequeña a cada paso del bucle, hasta que alcanza la condición de salida. No hemos ilustrado esto de manera explícita arriba, pero podríamos pensar que el granjero está recolectando 2 porciones de comida cada hora. Después de cada hora, la cantidad de comida recolectada se incrementa en dos, y comprueba si tiene suficiente comida. Si alcanza los 10 puntos (la condición de salida), puede parar la recolecta e irse para casa.</li> +</ul> + +<p>En {{glossary("pseudocódigo")}},esto se vería como sigue:</p> + +<pre class="notranslate">bucle(comida = 0; comidaNecesaria = 10) { + if (comida = comidaNecesaria) { + salida bucle; + // Tenemos suficiente comida; vamonos para casa + } else { + comida += 2; // Pasar una hora recogiendo 2 más de comida + // Comenzar el bucle de nuevo + } +}</pre> + +<p>Así que la cantidad necesaria de comida se establece en 10, y la cantidad incial del granjero en 0. En cada iteración del bucle comprobamos si la cantidad de comida del granjero es mayor o igual a la cantidad que necesita. Si lo es, podemos salir del bucle. Si no, el granjero se pasará una hora más recogiendo dos porciones de comida, y el bucle arrancará de nuevo.</p> + +<h3 id="¿Por_qué_molestarse">¿Por qué molestarse?</h3> + +<p><span class="tlid-translation translation" lang="es"><span title="">En este punto, probablemente entiendas los conceptos de alto nivel que hay detrás de los bucles,</span></span> pero probablemente estés pensando "OK, fantástico, pero ¿cómo me ayuda esto a escribir un mejor codigo JavaScript?". Como dijimos antes, <strong>los bucles tienen que ver con hacer lo mismo una y otra vez</strong>, lo cual es bueno para <strong>completar rápidamente tareas repetitivas</strong>.</p> + +<p>Muchas veces, el código será ligeramente diferente en cada iteracción sucesiva del bucle, lo que significa que puedes completar una carga completa de tareas que son similares, pero ligeramente diferentes — si tienes muchos calculos diferentes que hacer, quieres hacer cada uno de ellos, ¡no el mismo una y otra vez!</p> + +<p>Vamos a ver un ejemplo para ilustrar perfectamente por qué los bucles son tan útiles. Digamos que queremos dibujar 100 círculos aleatorios en un elemento {{htmlelement("canvas")}} (presiona el botón <em>Update</em> para ejecutar el ejemplo una y otra vez y ver diferentes configuraciones aleatorias):</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Random canvas circles</title> + <style> + html { + width: 100%; + height: inherit; + background: #ddd; + } + + canvas { + display: block; + } + + body { + margin: 0; + } + + button { + position: absolute; + top: 5px; + left: 5px; + } + </style> + </head> + <body> + + <button>Update</button> + + <canvas></canvas> + + + <script> + var btn = document.querySelector('button'); + var canvas = document.querySelector('canvas'); + var ctx = canvas.getContext('2d'); + + var WIDTH = document.documentElement.clientWidth; + var HEIGHT = document.documentElement.clientHeight; + + canvas.width = WIDTH; + canvas.height = HEIGHT; + + function random(number) { + return Math.floor(Math.random()*number); + } + + function draw() { + ctx.clearRect(0,0,WIDTH,HEIGHT); + for (var i = 0; i < 100; i++) { + ctx.beginPath(); + ctx.fillStyle = 'rgba(255,0,0,0.5)'; + ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); + ctx.fill(); + } + } + + btn.addEventListener('click',draw); + + </script> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>No tienes que entender todo el código por ahora, pero vamos a echar un vistazo a la parte de código que dibuja los 100 círculos:</p> + +<pre class="brush: js notranslate">for (var i = 0; i < 100; i++) { + ctx.beginPath(); + ctx.fillStyle = 'rgba(255,0,0,0.5)'; + ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); + ctx.fill(); +}</pre> + +<p>Debes quedarte con la idea básica. — utilizamos un bucle para ejecutar 100 iteracciones de este código, cada una de las cuales dibuja un círculo en una posición aleatoria de la página. La cantidad de código necesario sería el mismo si dibujáramos 100, 1000, o 10,000 círculos. Solo necesitamos cambiar un número.</p> + +<p>Si no usáramos un bucle aquí, tendríamos que repetir el siguiente código por cada círculo que quisiéramos dibujar:</p> + +<pre class="brush: js notranslate">ctx.beginPath(); +ctx.fillStyle = 'rgba(255,0,0,0.5)'; +ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); +ctx.fill();</pre> + +<p>Esto sería muy aburrido y difícil de mantener de forma rápida. Los bucles son realmente lo mejor.</p> + +<h2 id="El_bucle_estándar_for">El bucle estándar <code>for</code></h2> + +<p>Exploremos algunos constructores de bucles específicos. El primero, que usarás la mayoría de las veces, es el bucle <a href="/es/docs/Web/JavaScript/Referencia/Sentencias/for">for</a> - este tiene la siguiente sintaxis:</p> + +<pre class="notranslate">for (inicializador; condición de salida; expresión final) { + // código a ejecutar +}</pre> + +<p>Aquí tenemos:</p> + +<ol> + <li>La palabra reservada <code>for</code>, seguida por algunos paréntesis.</li> + <li>Dentro de los paréntesis tenemos tres ítems, separados por punto y coma (;): + <ol> + <li>Un <strong>inicializador</strong> - Este es usualmente una variable con un número asignado, que aumenta el número de veces que el bucle ha sijo ejecutado. También se le llama <strong>contador</strong> o <strong>variable de conteo</strong>.</li> + <li>Una <strong>condición de salida</strong> - como se mencionó previamente, ésta define cuando el bucle debería detenerse. Generalmente es una expresión que contiene un operador de comparación, una prueba para verificar ue la condición de término o salida ha sido cumplida.</li> + <li>Una <strong>expresión final</strong> - que es siempre evaluada o ejecutada cada vez que el bucle ha completado una iteración. Usualmente sirve para modificar al contador (incrementando su valor o algunas veces disminuyendolo), para aproximarse a la condición de salida.</li> + </ol> + </li> + <li>Algunos corchetes curvos que contienen un bloque de código - este código se ejecutará cada vez que se repita el bucle.</li> +</ol> + +<p>Observa un ejemplo real para poder entender esto más claramente.</p> + +<pre class="brush: js notranslate">var cats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin']; +var info = 'My cats are called '; +var para = document.querySelector('p'); + +for (var i = 0; i < cats.length; i++) { + info += cats[i] + ', '; +} + +para.textContent = info;</pre> + +<p>Esto nos da el siguiente resultado:</p> + +<div class="hidden"> +<h6 id="Hidden_code_2">Hidden code 2</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Basic for loop example</title> + <style> + + </style> + </head> + <body> + + <p></p> + + + <script> + var cats = ['Bill', 'Jeff', 'Pete', 'Biggles', 'Jasmin']; + var info = 'My cats are called '; + var para = document.querySelector('p'); + + for (var i = 0; i < cats.length; i++) { + info += cats[i] + ', '; + } + + para.textContent = info; + + </script> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code_2', '100%', 60, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar este <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/basic-for.html">ejemplo de código en GitHub</a> también (además puedes <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/basic-for.html">verlo ejecutar en vivo</a>).</p> +</div> + +<p>Esto muestra un bucle siendo usado para iterar sobre los elementos de un arreglo (matriz), y hacer algo con cada uno de ellos - un patrón muy común en JavaScript. Aquí:</p> + +<ol> + <li>El iterador, <code>i</code>, inicia en <code>0</code> (<code>var i = 0</code>).</li> + <li>Se le ha dicho que debe ejecutarse hasta que no sea menor que la longitud del arreglo <code>cats</code>. Esto es importante - la condición de salida muestra la condicion bajo la cual el bucle seguirá iterando. Así, en este caso, mientras <code>i < cats.length</code> sea verdadero, el bucle seguirá ejecutándose.</li> + <li>Dentro del bucle, concatenamos el elemento del bucle actual (<code>cats[i]</code> es <code>cats[lo que sea i en ese momento]</code>) junto con una coma y un espacio, al final de la variable <code>info</code>. Así: + <ol> + <li>Durante la primera ejecución, <code>i = 0</code>, así <code>cats[0] + ', '</code> se concatenará con la información ("Bill, ").</li> + <li>Durante la segunda ejecución, <code>i = 1</code>, así <code>cats[1] + ', '</code> agregará el siguiente nombre ("Jeff, ").</li> + <li>Y así sucesivamente. Después de cada vez que se ejecute el bucle, se incrementará en 1 el valod de i (<code>i++</code>), entonces el proceso comenzará de nuevo.</li> + </ol> + </li> + <li>Cuando <code>i</code> sea igual a <code>cats.length</code>, el bucle se detendrá, y el navegador se moverá al siguiente segmento de código bajo el bucle.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Hemos programado la condición de salidad como <code>i < cats.length</code>, y no como <code>i <= cats.length</code>, porque los computadores cuentan desde 0, no 1 - inicializamos la variable i en 0, para llegar a <code>i = 4</code> (el índice del último elemento del arreglo). <code>cats.length</code> responde 5, ya que existen 5 elementos en el arreglo, pero no queremos que i = 5, dado que respondería <code>undefined</code> para el último elemento (no existe un elemento en el arreglo con un índice 5). for the last item (there is no array item with an index of 5). Por ello, queremos llegar a 1 menos que <code>cats.length</code> (<code>i <</code>), que no es lo mismo que <code>cats.length</code> (<code>i <=</code>).</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Un error común con la condición de salida es utilizar el comparador "igual a" (<code>===</code>) en vez de "menor o igual a" (<code><=</code>). Si queremos que nuestro bucle se ejecute hasta que <code>i = 5</code>, la condición de salida debería ser <code>i <= cats.length</code>. Si la declaramos <code>i === cats.length</code>, el bucle no debería ejecutarse , porque <code>i</code> no es igual a <code>5</code> en la primera iteración del bucle, por lo que debería detenerse inmediatamente.</p> +</div> + +<p>Un pequeño problema que se presenta es que la frase de salida final no está muy bien formada:</p> + +<blockquote> +<p>My cats are called Bill, Jeff, Pete, Biggles, Jasmin,</p> +</blockquote> + +<p>Idealmente querríamos cambiar la concatenacion al final de la última iteracion del bucle, así no tendríamos una coma en el final de la frase. Bueno, no hay problema - podemos insertar un condicional dentro de nuestro bucle para solucionar este caso especial:</p> + +<pre class="brush: js notranslate">for (var i = 0; i < cats.length; i++) { + if (i === cats.length - 1) { + info += 'and ' + cats[i] + '.'; + } else { + info += cats[i] + ', '; + } +}</pre> + +<div class="note"> +<p><strong>Note</strong>: You can find this <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/basic-for-improved.html">example code on GitHub</a> too (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/basic-for-improved.html">see it running live</a>).</p> +</div> + +<div class="warning"> +<p><strong>Importante</strong>: Con <code>for</code> - como con todos los bucles - debes estar seguro de que el inicializador es repetido hasta que eventualemtne alcance la condición de salida. Si no, el bucle seguirá repitiéndose indefinidamente, y puede que el navegador lo fuerce a detenerse o se interrumpa. Esto se denomina <strong>bucle infinito</strong>.</p> +</div> + +<h2 id="Salir_de_un_bucle_con_break">Salir de un bucle con <code>break</code></h2> + +<p>Si deseas salir de un bucle antes de que se hayan completado todas las iteraciones, puedes usar la declaración <a href="/es/docs/Web/JavaScript/Referencia/Sentencias/break">break</a>. Ya la vimos en el artículo previo cuando revisamos la declaración <a href="/es/docs/Web/JavaScript/Referencia/Sentencias/switch">switch</a> - cuando un caso en una declaración <code>switch</code> coincide con la expresión de entrada, la declaración <code>break</code> inmediatamente sale de la declaración <code>switch</code> y avanza al código que se encuentra después.</p> + +<p>Ocurre lo mismo con los bucles - una declaración <code>break</code> saldrá inmediatamente del bucle y hará que el navegador siga con el código que sigue después.</p> + +<p>Digamos que queremos buscar a través de un arreglo de contactos y números telefónicos y retornar sólo el número que queríamos encontrar. primero, un simple HTML - un {{htmlelement("input")}} de texto que nos permita ingresar un nombre para buscar, un elemento {{htmlelement("button")}} para enviar la búsqueda, y un elemento {{htmlelement("p")}} para mostrar el resultado:</p> + +<pre class="brush: html notranslate"><label for="search">Search by contact name: </label> +<input id="search" type="text"> +<button>Search</button> + +<p></p></pre> + +<p>Ahora en el JavaScript:</p> + +<pre class="brush: js notranslate">var contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975']; +var para = document.querySelector('p'); +var input = document.querySelector('input'); +var btn = document.querySelector('button'); + +btn.addEventListener('click', function() { + var searchName = input.value; + input.value = ''; + input.focus(); + for (var i = 0; i < contacts.length; i++) { + var splitContact = contacts[i].split(':'); + if (splitContact[0] === searchName) { + para.textContent = splitContact[0] + '\'s number is ' + splitContact[1] + '.'; + break; + } else { + para.textContent = 'Contact not found.'; + } + } +});</pre> + +<div class="hidden"> +<h6 id="Hidden_code_3">Hidden code 3</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Simple contact search example</title> + <style> + + </style> + </head> + <body> + + <label for="search">Search by contact name: </label> + <input id="search" type="text"> + <button>Search</button> + + <p></p> + + + <script> + var contacts = ['Chris:2232322', 'Sarah:3453456', 'Bill:7654322', 'Mary:9998769', 'Dianne:9384975']; + var para = document.querySelector('p'); + var input = document.querySelector('input'); + var btn = document.querySelector('button'); + + btn.addEventListener('click', function() { + var searchName = input.value; + input.value = ''; + input.focus(); + for (var i = 0; i < contacts.length; i++) { + var splitContact = contacts[i].split(':'); + if (splitContact[0] === searchName) { + para.textContent = splitContact[0] + '\'s number is ' + splitContact[1] + '.'; + break; + } else { + para.textContent = 'Contact not found.'; + } + } + }); + </script> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code_3', '100%', 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<ol> + <li>First of all we have some variable definitions — we have an array of contact information, with each item being a string containing a name and phone number separated by a colon.</li> + <li>Next, we attach an event listener to the button (<code>btn</code>), so that when it is pressed, some code is run to perform the search and return the results.</li> + <li>We store the value entered into the text input in a variable called <code>searchName</code>, before then emptying the text input and focusing it again, ready for the next search.</li> + <li>Now onto the interesting part, the for loop: + <ol> + <li>We start the counter at <code>0</code>, run the loop until the counter is no longer less than <code>contacts.length</code>, and increment <code>i</code> by 1 after each iteration of the loop.</li> + <li>Inside the loop we first split the current contact (<code>contacts[i]</code>) at the colon character, and store the resulting two values in an array called <code>splitContact</code>.</li> + <li>We then use a conditional statement to test whether <code>splitContact[0]</code> (the contact's name) is equal to the inputted <code>searchName</code>. If it is, we enter a string into the paragraph to report what the contact's number is, and use <code>break</code> to end the loop.</li> + </ol> + </li> + <li>If the contact name does not match the entered search, the paragraph text is set to "Contact not found.", and the loop continues iterating.</li> +</ol> + +<div class="note"> +<p>Note: You can view the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/contact-search.html">full source code on GitHub</a> too (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/contact-search.html">see it running live</a>).</p> +</div> + +<h2 id="Skipping_iterations_with_continue">Skipping iterations with continue</h2> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Statements/continue">continue</a> statement works in a similar manner to <code>break</code>, but instead of breaking out of the loop entirely, it skips to the next iteration of the loop. Let's look at another example that takes a number as an input, and returns only the numbers that are squares of integers (whole numbers).</p> + +<p>The HTML is basically the same as the last example — a simple text input, and a paragraph for output. The JavaScript is mostly the same too, although the loop itself is a bit different:</p> + +<pre class="brush: js notranslate">var num = input.value; + +for (var i = 1; i <= num; i++) { + var sqRoot = Math.sqrt(i); + if (Math.floor(sqRoot) !== sqRoot) { + continue; + } + + para.textContent += i + ' '; +}</pre> + +<p>Here's the output:</p> + +<div class="hidden"> +<h6 id="Hidden_code_4">Hidden code 4</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Integer squares generator</title> + <style> + + </style> + </head> + <body> + + <label for="number">Enter number: </label> + <input id="number" type="text"> + <button>Generate integer squares</button> + + <p>Output: </p> + + + <script> + var para = document.querySelector('p'); + var input = document.querySelector('input'); + var btn = document.querySelector('button'); + + btn.addEventListener('click', function() { + para.textContent = 'Output: '; + var num = input.value; + input.value = ''; + input.focus(); + for (var i = 1; i <= num; i++) { + var sqRoot = Math.sqrt(i); + if (Math.floor(sqRoot) !== sqRoot) { + continue; + } + + para.textContent += i + ' '; + } + }); + </script> + + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code_4', '100%', 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<ol> + <li>In this case, the input should be a number (<code>num</code>). The <code>for</code> loop is given a counter starting at 1 (as we are not interested in 0 in this case), an exit condition that says the loop will stop when the counter becomes bigger than the input <code>num</code>, and an iterator that adds 1 to the counter each time.</li> + <li>Inside the loop, we find the square root of each number using <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/sqrt">Math.sqrt(i)</a>, then check whether the square root is an integer by testing whether it is the same as itself when it has been rounded down to the nearest integer (this is what <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/floor">Math.floor()</a> does to the number it is passed).</li> + <li>If the square root and the rounded down square root do not equal one another (<code>!==</code>), it means that the square root is not an integer, so we are not interested in it. In such a case, we use the <code>continue</code> statement to skip on to the next loop iteration without recording the number anywhere.</li> + <li>If the square root IS an integer, we skip past the if block entirely so the <code>continue</code> statement is not executed; instead, we concatenate the current <code>i</code> value plus a space on to the end of the paragraph content.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: You can view the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/integer-squares.html">full source code on GitHub</a> too (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/integer-squares.html">see it running live</a>).</p> +</div> + +<h2 id="while_and_do_..._while">while and do ... while</h2> + +<p><code>for</code> is not the only type of loop available in JavaScript. There are actually many others and, while you don't need to understand all of these now, it is worth having a look at the structure of a couple of others so that you can recognize the same features at work in a slightly different way.</p> + +<p>First, let's have a look at the <a href="/en-US/docs/Web/JavaScript/Reference/Statements/while">while</a> loop. This loop's syntax looks like so:</p> + +<pre class="notranslate">initializer +while (exit-condition) { + // code to run + + final-expression +}</pre> + +<p>This works in a very similar way to the for loop, except that the initializer variable is set before the loop, and the final-expression is included inside the loop after the code to run — rather than these two items being included inside the parentheses. The exit-condition is included inside the parentheses, which are preceded by the <code>while</code> keyword rather than <code>for</code>.</p> + +<p>The same three items are still present, and they are still defined in the same order as they are in the for loop — this makes sense, as you still have to have an initializer defined before you can check whether it has reached the exit-condition; the final-condition is then run after the code inside the loop has run (an iteration has been completed), which will only happen if the exit-condition has still not been reached.</p> + +<p>Let's have a look again at our cats list example, but rewritten to use a while loop:</p> + +<pre class="brush: js notranslate">var i = 0; + +while (i < cats.length) { + if (i === cats.length - 1) { + info += 'and ' + cats[i] + '.'; + } else { + info += cats[i] + ', '; + } + + i++; +}</pre> + +<div class="note"> +<p><strong>Note</strong>: This still works just the same as expected — have a look at it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/while.html">running live on GitHub</a> (also view the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/while.html">full source code</a>).</p> +</div> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Statements/do...while">do...while</a> loop is very similar, but provides a variation on the while structure:</p> + +<pre class="notranslate">initializer +do { + // code to run + + final-expression +} while (exit-condition)</pre> + +<p>In this case, the initializer again comes first, before the loop starts. The <code>do</code> keyword directly precedes the curly braces containing the code to run and the final-expression.</p> + +<p>The differentiator here is that the exit-condition comes after everything else, wrapped in parentheses and preceded by a <code>while</code> keyword. In a <code>do...while</code> loop, the code inside the curly braces is always run once before the check is made to see if it should be executed again (in while and for, the check comes first, so the code might never be executed).</p> + +<p>Let's rewrite our cat listing example again to use a <code>do...while</code> loop:</p> + +<pre class="brush: js notranslate">var i = 0; + +do { + if (i === cats.length - 1) { + info += 'and ' + cats[i] + '.'; + } else { + info += cats[i] + ', '; + } + + i++; +} while (i < cats.length);</pre> + +<div class="note"> +<p><strong>Note</strong>: Again, this works just the same as expected — have a look at it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/do-while.html">running live on GitHub</a> (also view the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/do-while.html">full source code</a>).</p> +</div> + +<div class="warning"> +<p><strong>Important</strong>: With while and do...while — as with all loops — you must make sure that the initializer is iterated so that it eventually reaches the exit condition. If not, the loop will go on forever, and either the browser will force it to stop, or it will crash. This is called an <strong>infinite loop</strong>.</p> +</div> + +<h2 id="Active_learning_Launch_countdown!">Active learning: Launch countdown!</h2> + +<p>In this exercise, we want you to print out a simple launch countdown to the output box, from 10 down to Blast off. Specifically, we want you to:</p> + +<ul> + <li>Loop from 10 down to 0. We've provided you with an initializer — <code>var i = 10;</code>.</li> + <li>For each iteration, create a new paragraph and append it to the output <code><div></code>, which we've selected using <code>var output = document.querySelector('.output');</code>. In comments, we've provided you with three code lines that need to be used somewhere inside the loop: + <ul> + <li><code>var para = document.createElement('p');</code> — creates a new paragraph.</li> + <li><code>output.appendChild(para);</code> — appends the paragraph to the output <code><div></code>.</li> + <li><code>para.textContent =</code> — makes the text inside the paragraph equal to whatever you put on the right hand side, after the equals sign.</li> + </ul> + </li> + <li>Different iteration numbers require different text to be put in the paragraph for that iteration (you'll need a conditional statement and multiple <code>para.textContent =</code> lines): + <ul> + <li>If the number is 10, print "Countdown 10" to the paragraph.</li> + <li>If the number is 0, print "Blast off!" to the paragraph.</li> + <li>For any other number, print just the number to the paragraph.</li> + </ul> + </li> + <li>Remember to include an iterator! However, in this example we are counting down after each iteration, not up, so you <strong>don't</strong> want <code>i++</code> — how do you iterate downwards?</li> +</ul> + +<p>If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.</p> + +<div class="hidden"> +<h6 id="Active_learning">Active learning</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> +<div class="output" style="height: 410px;overflow: auto;"> + +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> +<textarea id="code" class="playable-code" style="height: 300px;width: 95%"> +var output = document.querySelector('.output'); +output.innerHTML = ''; + +// var i = 10; + +// var para = document.createElement('p'); +// para.textContent = ; +// output.appendChild(para); +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<p class="brush: js"></p> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var output = document.querySelector(\'.output\');\noutput.innerHTML = \'\';\n\nvar i = 10;\n\nwhile(i >= 0) {\n var para = document.createElement(\'p\');\n if(i === 10) {\n para.textContent = \'Countdown \' + i;\n } else if(i === 0) {\n para.textContent = \'Blast off!\';\n } else {\n para.textContent = i;\n }\n\n output.appendChild(para);\n\n i--;\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> + +<p class="brush: js"></p> +</div> + +<p>{{ EmbedLiveSample('Active_learning', '100%', 880, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Active_learning_Filling_in_a_guest_list">Active learning: Filling in a guest list</h2> + +<p>In this exercise, we want you to take a list of names stored in an array, and put them into a guest list. But it's not quite that easy — we don't want to let Phil and Lola in because they are greedy and rude, and always eat all the food! We have two lists, one for guests to admit, and one for guests to refuse.</p> + +<p>Specifically, we want you to:</p> + +<ul> + <li>Write a loop that will iterate from 0 to the length of the <code>people</code> array. You'll need to start with an initializer of <code>var i = 0;</code>, but what exit condition do you need?</li> + <li>During each loop iteration, check if the current array item is equal to "Phil" or "Lola" using a conditional statement: + <ul> + <li>If it is, concatenate the array item to the end of the <code>refused</code> paragraph's <code>textContent</code>, followed by a comma and a space.</li> + <li>If it isn't, concatenate the array item to the end of the <code>admitted</code> paragraph's <code>textContent</code>, followed by a comma and a space.</li> + </ul> + </li> +</ul> + +<p>We've already provided you with:</p> + +<ul> + <li><code>var i = 0;</code> — Your initializer.</li> + <li><code>refused.textContent +=</code> — the beginnings of a line that will concatenate something on to the end of <code>refused.textContent</code>.</li> + <li><code>admitted.textContent +=</code> — the beginnings of a line that will concatenate something on to the end of <code>admitted.textContent</code>.</li> +</ul> + +<p>Extra bonus question — after completing the above tasks successfully, you will be left with two lists of names, separated by commas, but they will be untidy — there will be a comma at the end of each one. Can you work out how to write lines that slice the last comma off in each case, and add a full stop to the end? Have a look at the <a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Useful string methods</a> article for help.</p> + +<p>If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.</p> + +<div class="hidden"> +<h6 id="Active_learning_2">Active learning 2</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> +<div class="output" style="height: 100px;overflow: auto;"> + <p class="admitted">Admit: </p> + <p class="refused">Refuse: </p> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> +<textarea id="code" class="playable-code" style="height: 400px;width: 95%"> +var people = ['Chris', 'Anne', 'Colin', 'Terri', 'Phil', 'Lola', 'Sam', 'Kay', 'Bruce']; + +var admitted = document.querySelector('.admitted'); +var refused = document.querySelector('.refused'); +admitted.textContent = 'Admit: '; +refused.textContent = 'Refuse: ' + +// var i = 0; + +// refused.textContent += ; +// admitted.textContent += ; + +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var people = [\'Chris\', \'Anne\', \'Colin\', \'Terri\', \'Phil\', \'Lola\', \'Sam\', \'Kay\', \'Bruce\'];\n\nvar admitted = document.querySelector(\'.admitted\');\nvar refused = document.querySelector(\'.refused\');\n\nadmitted.textContent = \'Admit: \';\nrefused.textContent = \'Refuse: \'\nvar i = 0;\n\ndo {\n if(people[i] === \'Phil\' || people[i] === \'Lola\') {\n refused.textContent += people[i] + \', \';\n } else {\n admitted.textContent += people[i] + \', \';\n }\n i++;\n} while(i < people.length);\n\nrefused.textContent = refused.textContent.slice(0,refused.textContent.length-2) + \'.\';\nadmitted.textContent = admitted.textContent.slice(0,admitted.textContent.length-2) + \'.\';'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Active_learning_2', '100%', 680, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Which_loop_type_should_you_use">Which loop type should you use?</h2> + +<p>For basic uses, <code>for</code>, <code>while</code>, and <code>do...while</code> loops are largely interchangeable. They can all be used to solve the same problems, and which one you use will largely depend on your personal preference — which one you find easiest to remember or most intuitive. Let's have a look at them again.</p> + +<p>First <code>for</code>:</p> + +<pre class="notranslate">for (initializer; exit-condition; final-expression) { + // code to run +}</pre> + +<p><code>while</code>:</p> + +<pre class="notranslate">initializer +while (exit-condition) { + // code to run + + final-expression +}</pre> + +<p>and finally <code>do...while</code>:</p> + +<pre class="notranslate">initializer +do { + // code to run + + final-expression +} while (exit-condition)</pre> + +<p>We would recommend <code>for</code>, at least to begin with, as it is probably the easiest for remembering everything — the initializer, exit-condition, and final-expression all have to go neatly into the parentheses, so it is easy to see where they are and check that you aren't missing them.</p> + +<div class="note"> +<p><strong>Note</strong>: There are other loop types/features too, which are useful in advanced/specialized situations and beyond the scope of this article. If you want to go further with your loop learning, read our advanced <a href="/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration">Loops and iteration guide</a>.</p> +</div> + +<h2 id="Conclusion">Conclusion</h2> + +<p>This article has revealed to you the basic concepts behind, and different options available when, looping code in JavaScript. You should now be clear on why loops are a good mechanism for dealing with repetitive code, and be raring to use them in your own examples!</p> + +<p>If there is anything you didn't understand, feel free to read through the article again, or <a href="/en-US/Learn#Contact_us">contact us</a> to ask for help.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration">Loops and iteration in detail</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/for">for statement reference</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/while">while</a> and <a href="/en-US/docs/Web/JavaScript/Reference/Statements/do...while">do...while</a> references</li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/break">break</a> and <a href="/en-US/docs/Web/JavaScript/Reference/Statements/continue">continue</a> references</li> + <li> + <p class="entry-title"><a href="https://www.impressivewebs.com/javascript-for-loop/">What’s the Best Way to Write a JavaScript For Loop?</a> — some advanced loop best practices</p> + </li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/conditionals","Learn/JavaScript/Building_blocks/Functions", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> +<gdiv></gdiv> diff --git a/files/es/learn/javascript/building_blocks/conditionals/index.html b/files/es/learn/javascript/building_blocks/conditionals/index.html new file mode 100644 index 0000000000..7a0fdcb91d --- /dev/null +++ b/files/es/learn/javascript/building_blocks/conditionals/index.html @@ -0,0 +1,778 @@ +--- +title: Tomando decisiones en tu código — condicionales +slug: Learn/JavaScript/Building_blocks/conditionals +tags: + - Aprendizaje + - Artículo + - Codificación + - Condicionales + - JavaScript + - Principiante +translation_of: Learn/JavaScript/Building_blocks/conditionals +--- +<div> +<p>{{LearnSidebar}}</p> + +<p>{{NextMenu("Learn/JavaScript/Building_blocks/Looping_code", "Learn/JavaScript/Building_blocks")}}</p> +</div> + +<p class="summary">En cualquier lenguaje de programación, el código necesita realizar decisiones y llevar a cabo diferentes acciones acordes dependiendo de distintas entradas. Por ejemplo, en un juego, si el el numero de vidas del jugador es 0, entonces se termina el juego. En una aplicación del clima, si se observa en la mañana, se despliega una gráfica del amanecer; muestra estrellas y una luna si es de noche. En este artículo, exploraremos cómo las llamadas declaraciones condicionales funcionan en JavaScript.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de informática, básico entendimiento de HTML y CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript primeros pasos</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender como se usan las extructuras condicionales en JavaScript. </td> + </tr> + </tbody> +</table> + +<h2 id="Puedes_hacerlo_en_una_condición..!">Puedes hacerlo en una condición..!</h2> + +<p>Los seres humanos (y otros animales) toman decisiones todo el tiempo que afectan sus vidas, desde la más insignificante ("¿Debería comer una galleta o dos?") hasta la más grande (¿Debería quedarme en mi país y trabajar en la granja de mi padre, o debería mudarme a Estados Unidos y estudiar astrofísica?). </p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13703/cookie-choice-small.png" style="display: block; margin: 0 auto;"></p> + +<h2 id="Declaraciones_if_..._else">Declaraciones if ... else </h2> + +<p>Echemos un vistazo a la declaración condicional más común que usarás en JavaScript.</p> + +<p> — El humilde <code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/if...else">if ... else</a></code><a href="/en-US/docs/Web/JavaScript/Reference/Statements/if...else"> statement</a>.</p> + +<h3 id="Sintaxis_if_..._else_básica.">Sintaxis if ... else básica. </h3> + +<p>Una sintaxis básica <code>if...else</code> luce así. {{glossary("pseudocode")}}:</p> + +<pre class="notranslate">if (condición) { + código a ejecutar si la condición es verdadera +} else { + ejecuta este otro código si la condición es falsa +}</pre> + +<p>Aquí tenemos:</p> + +<ol> + <li>La palabra clave <code>if</code> seguida de unos paréntesis.</li> + <li>Una condición a probar, puesta dentro de los paréntesis (típicamente "¿es este valor mayor que este otro valor?", o "¿existe este valor?"). Esta condición usará los <a href="/en-US/Learn/JavaScript/First_steps/Math#Comparison_operators">operadores de comparación</a> que hemos hablado en el módulo anterior y retorna un valor <code>true</code> o <code>false (verdadero o falso)</code>.</li> + <li>Un conjunto de llaves, en las cuales tenemos algún código — puede ser cualquier código que deseemos, código que se ejecutará sólamente si la condición retorna <code>true</code>.</li> + <li>La palabra clave <code>else</code>.</li> + <li>Otro conjunto de llaves, dentro de las cuales tendremos otro código — puede ser cualquier código que deseemos, y sólo se ejecutará si la condición no es <code>true</code>.</li> +</ol> + +<p>Este código es fácil de leer — está diciendo "<strong>si (if) </strong> la <strong>condición</strong> retorna verdadero (<code>true)</code>, entonces ejecute el código A, <strong>sino (else)</strong> ejecute el código B"</p> + +<p>Habrás notado que no tienes que incluir <code>else</code> y el segundo bloque de llaves — La siguiente declaración también es perfectmaente legal. </p> + +<pre class="notranslate">if (condición) { + ejecuta el código de al ser verdadera la condición +} + +ejecuta otro código</pre> + +<p>Sin embargo, hay que ser cuidadosos — en este caso, el segundo bloque no es controlado por una declaración condicional, así que <strong>siempre</strong> se ejecutará, sin importar si la condicional devuelve <code>true</code> o <code>false</code>. Esto no es necesariemente algo malo, pero puede ser algo que no quieras — a menudo desearás ejecutar un bloque de código u otro, no ambos.</p> + +<p>Como punto final, habrán ocaciones donde veas delcaraciones <code>if...else</code> escritas sin un conjunto de llaves, de esta manera:</p> + +<pre class="notranslate">if (condición) ejecuta código de ser verdadero (true) +else ejecuta este otro código </pre> + +<p>Este código es perfectamente valido, pero no es recomendado usarlo — es mucho más fácil leer el código y determinar qué sucede haciendo uso de las llaves para delimitar los bloques de código y usar varias líneas y sangrías.</p> + +<h3 id="Un_ejemplo_real">Un ejemplo real</h3> + +<p>Para comprender mejor la sintaxis, realicemos un ejemplo real. Imagínese a un niño a quien su madre o padre le pide ayuda con una tarea. El padre podría decir: "¡Hola, cariño! Si me ayudas yendo y haciendo las compras, te daré un subsidio adicional para que puedas pagar ese juguete que querías". En JavaScript, podríamos representar esto así:</p> + +<pre class="brush: js notranslate">let compraRealizada = false; + +if (compraRealizada === true) { + let subsidioAdicional = 10; +} else { + let subsidioAdicional = 5; +}</pre> + +<p>La variable <code>compraRealizada</code> escrita en este código dará siempre como resultado un retorno de valor <code>false</code>, lo cuál significa una desilusión para nuestro pobre hijo. Depende de nosotros proporcionar un mecanismo para que el padre cambie el valor de la variable <code>compraRealizada</code> a <code>true</code> si el niño realizó la compra.</p> + +<div class="note"> +<p><strong>Nota</strong>: Podrás ver una versión más completa de <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/allowance-updater.html">este ejemplo en GitHub</a> (también podrás verlo <a href="https://mdn.github.io/learning-area/javascript/building-blocks/allowance-updater.html">corriendo en vivo.</a>)</p> +</div> + +<h3 id="else_if">else if</h3> + +<p>El último ejemplo nos proporcionó dos opciones o resultados, pero ¿qué ocurre si queremos más de dos?</p> + +<p>Hay una forma de encadenar opciones / resultados adicionales extras a <code>if...else</code> — usando <code>else if</code>. Cada opción extra requiere un bloque adicional para poner en medio de bloque <code>if() { ... }</code> y <code>else { ... }</code> — Vea el siguiente ejemplo un poco más complicado, que podría ser parte de una aplicación para un simple pronóstico del tiempo:</p> + +<pre class="brush: html notranslate"><label for="clima">Seleccione el tipo de clima de hoy: </label> +<select id="clima"> + <option value="">--Haga una elección--</option> + <option value="soleado">Soleado</option> + <option value="lluvioso">Lluvioso</option> + <option value="nevando">Nevando</option> + <option value="nublado">Nublado</option> +</select> + +<p></p></pre> + +<pre class="brush: js notranslate">let seleccionar = document.querySelector('select'); +let parrafo = document.querySelector('p'); + +seleccionar.addEventListener('change', establecerClima); + +function establecerClima() { + let eleccion = seleccionar.value; + + if (eleccion === 'soleado') { + parrafo.textContent = 'El día esta agradable y soleado hoy. ¡Use pantalones cortos! Ve a la playa o al parque y come un helado.'; + } else if (eleccion === 'lluvioso') { + parrafo.textContent = 'Está lloviendo, tome un abrigo para lluvia y un paraguas, y no se quede por fuera mucho tiempo.'; + } else if (eleccion === 'nevando') { + parrafo.textContent = 'Está nevando ─ ¡está congelando! Lo mejor es quedarse en casa con una taza caliente de chocolate, o hacer un muñeco de nieve.'; + } else if (eleccion === 'nublado') { + parrafo.textContent = 'No está lloviendo, pero el cielo está gris y nublado; podría llover en cualquier momento, así que lleve un saco solo por si acaso.'; + } else { + parrafo.textContent = ''; + } +} + +</pre> + +<p>{{ EmbedLiveSample('else_if', '100%', 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<ol> + <li>Aquí tenemos un elemento HTML {{htmlelement("select")}} que nos permite realizar varias elecciones sobre el clima, y un parrafo simple.</li> + <li>En el JavaScript, estamos almacenando una referencia para ambos elementos {{htmlelement("select")}} y {{htmlelement("p")}} , y añadiendo un Event Listener o en español un Detector de Eventos al elemento <code><select></code> así cuando su valor cambie se ejecuta la función <code>establecerClima</code><code>().</code></li> + <li>Cuando la función es ejecutada, primero establecemos la variable <code>eleccion</code> con el valor obtenido del elemento <code><select>.</code> Luego usamos una declaración condicinal para mostrar distintos textos dentro del párrafo {{htmlelement("p")}} dependiendo del valor de la variable <code>eleccion</code>. Note como todas las condicinales son probadas en los bloques <code>else if() {...}</code> , a excepción del primero, el cual es probado en el primer bloque <code>if() {...}</code>.</li> + <li>La ultima elección, dentro del bloque <code>else {...}</code>, es básicamente el "último recurso" como opción— El código dentro de este bloque se ejecutará si nunguna de las condiciones es <code>true</code>. En este caso, sirve para vaciar el contenido del párrafo si nada ha sido seleccionado, por ejemplo, si el usuario decide elegir de nuevo "--Haga una elección--" mostrado al inicio.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-else-if.html"> este ejemplo en GitHub</a> (También podrás verlo <a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-else-if.html">correr en vivo</a>.)</p> +</div> + +<h3 id="Una_nota_en_los_operadores_de_comparación">Una nota en los operadores de comparación </h3> + +<p>Los operadores de comparación son usados para probar las condiciones dentro de nuestra declaración condicional. Vimos estos operadores en el artículo <a href="/en-US/Learn/JavaScript/First_steps/Math#Comparison_operators">Matématica básica en JavaScript — Números y operadores</a>. Nuestras opciones son:</p> + +<ul> + <li><code>===</code> y <code>!==</code> — prueba si un valor es exactamente igual a otro, o sino es indentico a otro valor.</li> + <li><code><</code> y <code>></code> — prueba si un valor es menor o mayor que otro.</li> + <li><code><=</code> y <code>>=</code> — prueba si un valor es menor e igual o mayor e igual que otro.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Revisa el material en los enlaces previos para refrescar la memoria en estos temas. </p> +</div> + +<p>Queremos hacer una mención especial al probar los valores (<code>true</code>/<code>false</code>) , y un patrón común que te encontrarás una y otra vez. Cualquier valor que no sea <code>false</code>, <code>undefined</code>, <code>null</code>, <code>0</code>, <code>NaN</code>, o una cadena vacía string (<code>''</code>) realmente retorna el valor <code>true</code> cuando es probada como una declaración condicional, por lo tanto puedes simplemente usar el nombre de una variable para probar si es <code>true</code>, o si al menos existe (i.e. no está definido.) Por ejemplo:</p> + +<pre class="brush: js notranslate">let queso = 'Cheddar'; + +if (queso) { + console.log('¡Siii! Hay queso para hacer tostadas con queso.'); +} else { + console.log('No hay tostadas con queso para ti hoy :(.'); +}</pre> + +<p>En el ejemplo anterior la variable <code>queso</code> contiene el valor 'Cheddar', y como su valor está definido o no es <code>false</code>, <code>undefined</code>, <code>null</code>, <code>0</code>, <code>NaN</code> y <code>(' ')</code> es considerado como <code>true</code> lo cual hará mostrar el mensaje dentro del primer bloque de llaves. </p> + +<p>Y, devolviéndonos al ejemplo previo del niño haciendo las compras para su padre, lo podrías haber escrito así:</p> + +<pre class="brush: js notranslate">let compraRealizada = false; + +if (compraRealizada) { //no necesitas especificar explícitamente '=== true' + let subsidioAdicional = 10; +} else { + let subsidioAdicional = 5; +}</pre> + +<h3 id="Anidando_if_..._else">Anidando if ... else</h3> + +<p>Está perfectamente permitido poner una declaración <code>if...else</code> dentro de otra declaración <code>if...else</code> — para anidarlas. Por ejemplo, podemos actualizar nuestra aplicación del clima para mostrar una serie de opciones dependiendo de cual sea la temperatura:</p> + +<pre class="brush: js notranslate">if (elección === 'soleado') { + if (temperatura < 86) { + parrafo.textContent = 'Está a ' + temperatura + ' grados afuera — agradable y soleado. Vamos a la playa, o al parque, y comer helado.'; + } else if (temperatura >= 86) { + parrafo.textContent = 'Está a ' + temperatura + ' grados afuera — ¡QUÉ CALOR! Si deseas salir, asegúrate de aplicarte bloqueador solar.'; + } +}</pre> + +<p>Aunque el código funciona en conjunto, cada declaración <code>if...else</code> funciona complentamente independiente del otro.</p> + +<h3 id="Operadores_lógicos_AND_OR_y_NOT">Operadores lógicos: AND, OR y NOT</h3> + +<p>Si quieres probar multiples condiciones sin escribir declaraciones <code>if...else </code>anidados, los <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators">operadores lógicos</a> pueden ayudarte. Cuando se usa en condiciones, los primeros dos hacen lo siguiente:</p> + +<ul> + <li><code>&&</code> — AND; le permite encadenar dos o más expresiones para que todas ellas se tengan que evaluar individualmente <code>true</code> para que expresión entera retorne <code>true</code>.</li> + <li><code>||</code> — OR; le permite encadenar dos o más expresiones para que una o más de ellas se tengan que evaluar individualmente <code>true</code> para que expresión entera retorne <code>true</code>.</li> +</ul> + +<p>Para poner un ejemplo de AND, el anterior código puede ser reescrito de esta manera:</p> + +<pre class="brush: js notranslate">if (eleccion === 'soleado' && temperatura < 86) { + parrafo.textContent = 'Está a ' + temperatura + ' grados afuera — agradable y soleado. Vamos a la playa, o al parque, y comer helado.'; +} else if (eleccion === 'soleado' && temperatura >= 86) { + parrafo.textContent = 'Está a ' + temperatura + ' grados afuera — ¡QUÉ CALOR! Si deseas salir, asegúrate de aplicarte bloqueador solar.'; +}</pre> + +<p>Así que por ejemplo, el primer bloque solo se ejecutará si la variable <code>eleccion === 'soleado'</code> <em>y </em><code>temperatura < 86</code> devuelven un valor verdadero o <code>true</code>.</p> + +<p>Observemos un ejemplo rápido del operador OR:</p> + +<pre class="brush: js notranslate">if (carritoDeHelados || estadoDeLaCasa === 'en llamas') { + console.log('Debes salir de la casa rápidamente.'); +} else { + console.log('Es mejor que te quedes dentro de casa'); +}</pre> + +<p>El último tipo de operador lógico, NOT, es expresado con el operador <code>!</code>, puede ser usado para negar una expresión. Vamos a combinarlo con el operador OR en el siguiente ejemplo:</p> + +<pre class="brush: js notranslate">if (!(carritoDeHelados || estadoDeLaCasa === 'en llamas')) { + console.log('Es mejor que te quedes dentro de casa'); +} else { + console.log('Debes salir de la casa rápidamente.'); +}</pre> + +<p>En el anterior ejemplo, si las declaraciones del operador OR retornan un valor <code>true</code>, el operador NOT negará toda la expresión dentro de los paréntesis, por lo tanto retornará un valor <code>false</code>.</p> + +<p>Puedes combinar los operadores que quieras dentro de las sentencias, en cualquier estructura. El siguiente ejemplo ejecuta el código dentro del condicional solo si ambas sentencias OR devuelven verdadero, lo que significa que la instrucción general AND devolverá verdadero:</p> + +<pre class="brush: js notranslate">if ((x === 5 || y > 3 || z <= 10) && (logueado || nombreUsuario === 'Steve')) { + // ejecuta el código +}</pre> + +<p>Un error comun cuando se utiliza el operador OR en las declaraciones condicionales es intentar verificar el valor de la variable una sola vez, y luego darle una lista de valores que podrían retornar verdadero separados por operadores ||. Por ejemplo:</p> + +<pre class="example-bad brush: js notranslate">if (x === 5 || 7 || 10 || 20) { + // ejecuta mi código +}</pre> + +<p>En este caso la condición <code>if(...)</code> siempre evaluará a verdadero siendo que 7 (u otro valor que no sea 0) siempre será verdadero. Esta condición lo que realmente está diciendo es que "if x es igual a 5, o 7 es verdadero— lo cual siempre es". ¡Esto no es lógicamente lo que queremos! Para hacer que esto funcione, tenemos que especificar una prueba completa para cada lado del operador OR:</p> + +<pre class="brush: js notranslate">if (x === 5 || x === 7 || x === 10 ||x === 20) { + // ejecuta mi código +}</pre> + +<h2 id="Declaraciones_con_switch">Declaraciones con switch</h2> + +<p><code>El </code>condicional<code> if...else</code> hace un buen trabajo permitiéndonos realizar un buen código, pero esto viene con sus desventajas. Hay variedad de casos donde necesitarás realizar varias elecciones, y cada una requiere una cantidad razonable de código para ser ejecutado y/o sus condicionales son complejas (i.e. operadores lógicos múltiples). Para los casos en los que solo se desea establecer una variable para una determinada opción de valores o imprimir una declaración particular dependiendo de una condición, la sintaxis puede ser un poco engorrosa, especialmente si se tiene una gran cantidad de opciones.</p> + +<p>Para estos casos los <a href="/en-US/docs/Web/JavaScript/Reference/Statements/switch"><code>switch</code> statements</a> son de gran ayuda — toman una sola expresión / valor como una entrada, y luego pasan a través de una serie de opciones hasta que encuentran una que coincida con ese valor, ejecutando el código correspondiente que va junto con ella. Aquí hay un pseudocódigo más para hacerte una idea:</p> + +<pre class="notranslate">switch (expresion) { + case choice1: + ejecuta este código + break; + + case choice2: + ejecuta este código + break; + + // Se pueden incluir todos los casos que quieras + + default: + por si acaso, corre este código +}</pre> + +<p>Aquí tenemos:</p> + +<ol> + <li><code><font face="Open Sans, arial, x-locale-body, sans-serif"><span style="background-color: #ffffff;">La palabra clave </span></font>switch</code>, seguida por un conjunto de paréntesis.</li> + <li>Una expresión o valor dentro de los paréntesis.</li> + <li>La palabra clave <code>case</code>, seguida de una elección con la expresión / valor que podría ser, seguido de dos puntos.</li> + <li>Algún código a correr si la elección coincide con la expresión.</li> + <li>Un declaración llamada <code>break</code>, seguida de un punto y coma. Si la elección previa coincide con la expresión / valor, el explorador dejará de ejecutar el bloque de código aquí, y continuará a la siguiente línea de código. Si la opción anterior coincide con la expresión / valor, aquí el navegador deja de ejecutar el bloque de código y pasa a cualquier código que aparezca debajo de la declaración de <code>switch</code>.</li> + <li>Como muchos otros casos, los que quieras.</li> + <li>La palabra clave <code>default</code>, seguido exactamente del mismo patrón de código que en los casos anteriores , excepto que el valor predeterminado no tiene opciónes después de él, y no es necesario que se use <code>break</code> porque no hay nada que ejecutar después de este bloque de todas formas. Esta es la opción predeterminada o por defecto que se ejecuta si ninguna de las opciones coincide.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: No tiene que incluir la sección <code>default</code>; se puede omitir con seguridad si no hay posibilidades de que la expresión termine igualando un valor desconocido. Sin embargo, si existe la posibilidad de que esto ocurra, debe incluirlo para evitar casos desconocidos o comportamientos extraños en tu código.</p> +</div> + +<h3 id="Un_ejemplo_con_switch">Un ejemplo con switch</h3> + +<p>Let's have a look at a real example — we'll rewrite our weather forecast application to use a switch statement instead:</p> + +<pre class="brush: html notranslate"><label for="weather">Select the weather type today: </label> +<select id="weather"> + <option value="">--Make a choice--</option> + <option value="sunny">Sunny</option> + <option value="rainy">Rainy</option> + <option value="snowing">Snowing</option> + <option value="overcast">Overcast</option> +</select> + +<p></p></pre> + +<pre class="brush: js notranslate">let select = document.querySelector('select'); +let para = document.querySelector('p'); + +select.addEventListener('change', setWeather); + + +function setWeather() { + let choice = select.value; + + switch (choice) { + case 'sunny': + para.textContent = 'It is nice and sunny outside today. Wear shorts! Go to the beach, or the park, and get an ice cream.'; + break; + case 'rainy': + para.textContent = 'Rain is falling outside; take a rain coat and a brolly, and don\'t stay out for too long.'; + break; + case 'snowing': + para.textContent = 'The snow is coming down — it is freezing! Best to stay in with a cup of hot chocolate, or go build a snowman.'; + break; + case 'overcast': + para.textContent = 'It isn\'t raining, but the sky is grey and gloomy; it could turn any minute, so take a rain coat just in case.'; + break; + default: + para.textContent = ''; + } +}</pre> + +<p>{{ EmbedLiveSample('A_switch_example', '100%', 100, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>Nota</strong>: Tambien puedes<a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-switch.html"> encontrar este ejemplo en GitHub</a> (tambien puedes verlo <a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-switch.html">en ejecución aquí</a>.)</p> +</div> + +<h2 id="Operador_Ternario">Operador Ternario</h2> + +<p>Hay una última sintaxis que queremos presentarte antes de que juegues con algunos ejemplos. El <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">operador ternario o condicional</a> es una pequeña sintaxis que prueba una condición y devuelve un valor/expresión, si es <code>true</code>, y otro si es <code>false</code> — Esto puede ser útil en algunas situaciones, y puede ocupar mucho menos código que un bloque <code>if...else</code> si simplemente tienes dos opciones que se eligen a través de una condición <code>true</code>/<code>false</code>. El pseudocódigo se ve así:</p> + +<pre class="notranslate">( condición ) ? ejecuta este código : ejecuta este código en su lugar</pre> + +<p>Veamos un ejemplo simple:</p> + +<pre class="brush: js notranslate">let greeting = ( isBirthday ) ? 'Happy birthday Mrs. Smith — we hope you have a great day!' : 'Good morning Mrs. Smith.';</pre> + +<p>Aquí tenemos una variable llamada <code>isBirthday</code> — si esta es <code>true</code>, le damos a nuestro invitado un mensaje de feliz cumpleaños; si no, le damos el saludo diario estándar.</p> + +<h3 id="Ejemplo_con_operador_ternario">Ejemplo con operador ternario</h3> + +<p>No solo puedes establecer valores variables con el operador ternario; También puedes ejecutar funciones o líneas de código — lo que quieras. El siguiente ejemplo muestra un selector de tema simple donde el estilo del sitio se aplica utilizando un operador ternario.</p> + +<pre class="brush: html notranslate"><label for="theme">Select theme: </label> +<select id="theme"> + <option value="white">White</option> + <option value="black">Black</option> +</select> + +<h1>This is my website</h1></pre> + +<pre class="brush: js notranslate">let select = document.querySelector('select'); +let html = document.querySelector('html'); +document.body.style.padding = '10px'; + +function update(bgColor, textColor) { + html.style.backgroundColor = bgColor; + html.style.color = textColor; +} + +select.onchange = function() { + ( select.value === 'black' ) ? update('black','white') : update('white','black'); +} +</pre> + +<p>{{ EmbedLiveSample('Ternary_operator_example', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Aquí tenemos un elemento {{htmlelement('select')}} para elegir un tema (blanco o negro), más un simple (black or white), plus a simple {{htmlelement('h1')}} para mostrar el título de un sitio web. También tenemos una función llamada <code>update()</code>, que toma dos colores como parámetros (entradas). El color de fondo del sitio web se establece en el primer color proporcionado y el color del texto se establece en el segundo color proporcionado.</p> + +<p>Finalmente, también tenemos un detector de eventos <a href="/en-US/docs/Web/API/GlobalEventHandlers/onchange">onchange</a> que sirve para ejecutar una función que contiene un operador ternario. Comienza con una condición de prueba — <code>select.value === 'black'</code>. Si esto devuelve <code>true</code>, ejecutamos la función <code>update()</code> con parámetros de blanco y negro, lo que significa que terminamos con un color de fondo negro y un color de texto blanco. Si devuelve <code>false</code>, ejecutamos las función <code>update()</code> con parámetros de blanco y negro, lo que significa que el color del sitio está invertido.</p> + +<div class="note"> +<p><strong>Nota</strong>: También puedes <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/simple-ternary.html">encontrar este ejemplo en GitHub</a> (y verlo <a href="http://mdn.github.io/learning-area/javascript/building-blocks/simple-ternary.html">en ejecución aquí</a>.)</p> +</div> + +<h2 id="Aprendizaje_activo_Un_calendario_simple">Aprendizaje activo: Un calendario simple</h2> + +<p>En este ejemplo, nos ayudará a terminar una aplicación de calendario simple. En el código tienes:</p> + +<ul> + <li>Un elemento {{htmlelement("select")}} para permitir al usuario elegir entre direfentes meses.</li> + <li>Un controlador de eventos <code>onchange</code> para detectar cuándo se cambia el valor seleccionado en el menú de <code><select></code>.</li> + <li>Una función llamada <code>createCalendar()</code> que dibuja el calendario y muestra el mes correcto en el elemento {{htmlelement("h1")}}.</li> +</ul> + +<p>Necesitamos que escriba una declaración condicional dentro de la función del controlador <code>onchange</code> justo debajo del comentario <code>// ADD CONDITIONAL HERE.</code> Debería:</p> + +<ol> + <li>Mire el mes seleccionado (almacenado en la variable <code>choice</code>. Este será el valor del elemento <code><select></code> después de que cambie el valor, por ejemplo "January")</li> + <li>Establezca una variable llamada <code>days</code> para que sea igual al número de días del mes seleccionado. Para hacer esto, tendrá que buscar el número de días en cada mes del año. Puede ignorar los años bisiestos a los efectos de este ejemplo.</li> +</ol> + +<p>Sugerencias:</p> + +<ul> + <li>Se le aconseja que utilice el operador lógico OR para agrupar varios meses en una sola condición; Muchos de ellos comparten el mismo número de días.</li> + <li>Piense qué número de días es le más común y utilícelo como valor predeterminado.</li> +</ul> + +<p>Si comete un error, siempre puede restablecer el ejemplo con el botón "Reset". Si se queda realmente atascado, presione "Show solution" para ver una solución.</p> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> +<div class="output" style="height: 500px;overflow: auto;"> + <label for="month">Select month: </label> + <select id="month"> + <option value="January">January</option> + <option value="February">February</option> + <option value="March">March</option> + <option value="April">April</option> + <option value="May">May</option> + <option value="June">June</option> + <option value="July">July</option> + <option value="August">August</option> + <option value="September">September</option> + <option value="October">October</option> + <option value="November">November</option> + <option value="December">December</option> + </select> + + <h1></h1> + + <ul></ul> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 400px;width: 95%"> +var select = document.querySelector('select'); +var list = document.querySelector('ul'); +var h1 = document.querySelector('h1'); + +select.onchange = function() { + var choice = select.value; + + // ADD CONDITIONAL HERE + + createCalendar(days, choice); +} + +function createCalendar(days, choice) { + list.innerHTML = ''; + h1.textContent = choice; + for (var i = 1; i <= days; i++) { + var listItem = document.createElement('li'); + listItem.textContent = i; + list.appendChild(listItem); + } +} + +createCalendar(31,'January'); +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: css notranslate">.output * { + box-sizing: border-box; +} + +.output ul { + padding-left: 0; +} + +.output li { + display: block; + float: left; + width: 25%; + border: 2px solid white; + padding: 5px; + height: 40px; + background-color: #4A2DB6; + color: white; +} + +html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var select = document.querySelector(\'select\');\nvar list = document.querySelector(\'ul\');\nvar h1 = document.querySelector(\'h1\');\n\nselect.onchange = function() {\n var choice = select.value;\n var days = 31;\n if(choice === \'February\') {\n days = 28;\n } else if(choice === \'April\' || choice === \'June\' || choice === \'September\'|| choice === \'November\') {\n days = 30;\n }\n\n createCalendar(days, choice);\n}\n\nfunction createCalendar(days, choice) {\n list.innerHTML = \'\';\n h1.textContent = choice;\n for(var i = 1; i <= days; i++) {\n var listItem = document.createElement(\'li\');\n listItem.textContent = i;\n list.appendChild(listItem);\n }\n }\n\ncreateCalendar(31,\'January\');'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', '100%', 1110, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Aprendizaje_activo_Más_opciones_de_colores!">Aprendizaje activo: Más opciones de colores!</h2> + +<p>In this example, you are going to take the ternary operator example we saw earlier and convert the ternary operator into a switch statement that will allow us to apply more choices to the simple website. Look at the {{htmlelement("select")}} — this time you'll see that it has not two theme options, but five. You need to add a switch statement just underneath the <code>// ADD SWITCH STATEMENT</code> comment:</p> + +<ul> + <li>It should accept the <code>choice</code> variable as its input expression.</li> + <li>For each case, the choice should equal one of the possible values that can be selected, i.e. white, black, purple, yellow, or psychedelic. Note that the values are case sensitive, and should equal the <code><option></code> element <code>value</code> values rather than the visual labels.</li> + <li>For each case, the <code>update()</code> function should be run, and be passed two color values, the first one for the background color, and the second one for the text color. Remember that color values are strings, so need to be wrapped in quotes. </li> +</ul> + +<p>If you make a mistake, you can always reset the example with the "Reset" button. If you get really stuck, press "Show solution" to see a solution.</p> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> +<div class="output" style="height: 300px;"> + <label for="theme">Select theme: </label> + <select id="theme"> + <option value="white">White</option> + <option value="black">Black</option> + <option value="purple">Purple</option> + <option value="yellow">Yellow</option> + <option value="psychedelic">Psychedelic</option> + </select> + + <h1>This is my website</h1> +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 450px;width: 95%"> +var select = document.querySelector('select'); +var html = document.querySelector('.output'); + +select.onchange = function() { + var choice = select.value; + + // ADD SWITCH STATEMENT +} + +function update(bgColor, textColor) { + html.style.backgroundColor = bgColor; + html.style.color = textColor; +}</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var select = document.querySelector(\'select\');\nvar html = document.querySelector(\'.output\');\n\nselect.onchange = function() {\n var choice = select.value;\n\n switch(choice) {\n case \'black\':\n update(\'black\',\'white\');\n break;\n case \'white\':\n update(\'white\',\'black\');\n break;\n case \'purple\':\n update(\'purple\',\'white\');\n break;\n case \'yellow\':\n update(\'yellow\',\'darkgray\');\n break;\n case \'psychedelic\':\n update(\'lime\',\'purple\');\n break;\n }\n}\n\nfunction update(bgColor, textColor) {\n html.style.backgroundColor = bgColor;\n html.style.color = textColor;\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', '100%', 950, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>And that's all you really need to know about conditional structures in JavaScript right now! I'm sure you'll have understood these concepts and worked through the examples with ease; if there is anything you didn't understand, feel free to read through the article again, or <a href="/en-US/Learn#Contact_us">contact us</a> to ask for help.</p> + +<h2 id="Revisa_también">Revisa también</h2> + +<ul> + <li><a href="/en-US/Learn/JavaScript/First_steps/Math#Comparison_operators">Comparison operators</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Control_flow_and_error_handling#Conditional_statements">Conditional statements in detail</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Statements/if...else">if...else reference</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator">Conditional (ternary) operator reference</a></li> +</ul> + +<p>{{NextMenu("Learn/JavaScript/Building_blocks/Looping_code", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/Building_blocks/conditionals">Tomando decisiones en tu código - Condicionales</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> diff --git a/files/es/learn/javascript/building_blocks/construyendo_tu_propia_funcion/index.html b/files/es/learn/javascript/building_blocks/construyendo_tu_propia_funcion/index.html new file mode 100644 index 0000000000..5f9bcc7c8b --- /dev/null +++ b/files/es/learn/javascript/building_blocks/construyendo_tu_propia_funcion/index.html @@ -0,0 +1,252 @@ +--- +title: Construye tu propia función +slug: Learn/JavaScript/Building_blocks/Construyendo_tu_propia_funcion +tags: + - Aprender + - Artículo + - Construir + - Funciones + - Guía + - JavaScript + - Principiante + - Tutorial +translation_of: Learn/JavaScript/Building_blocks/Build_your_own_function +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">Con la mayor parte de la teoría esencial tratada en el artículo anterior, este artículo proporciona experiencia práctica. Aquí obtendrás práctica construyendo tu propia función personalizada. En el camino, también explicaremos algunos detalles útiles sobre cómo tratar las funciones.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Conocimientos básicos de computación, una comprensión básica de HTML y CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>, <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a>.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>Para proporcionar algo de práctica en la construcción de una función personalizada, y explicar algunos detalles asociados más útiles.</td> + </tr> + </tbody> +</table> + +<h2 id="Aprendizaje_activo_construyamos_una_función.">Aprendizaje activo: construyamos una función.</h2> + +<p>La función personalizada que vamos a construir se llamará <code>displayMessage()</code>. Mostrará un cuadro de mensaje personalizado en una página web y actuará como un reemplazo personalizado para la función de <a href="/en-US/docs/Web/API/Window/alert">alert()</a> incorporada de un navegador. Hemos visto esto antes, pero solo refresquemos nuestros recuerdos. Escriba lo siguiente en la consola de JavaScript de su navegador, en la página que desee:</p> + +<pre class="brush: js">alert('This is a message');</pre> + +<p>La función <code>alert</code> tiene un argumento — el string que se muestra en la alerta. Prueba a variar el string para cambiar el mensaje.</p> + +<p>La función <code>alert</code> es limitada: pueder cambiar el mensaje, pero no puedes cambiar de manera sencilla nada más, como el color, icono o cualquier otra cosa. Construiremos uno que resultará ser más divertido.</p> + +<div class="note"> +<p><strong>Nota</strong>: Este ejemplo debería funcionar bien en todos los navegadores modernos, pero el estilo puede parecer un poco divertido en los navegadores un poco más antiguos. Te recomendamos que hagas este ejercicio en un navegador moderno como Firefox, Opera o Chrome.</p> +</div> + +<h2 id="La_función_básica">La función básica</h2> + +<p>Para empezar, vamos a poner juntos una función básica.</p> + +<div class="note"> +<p><strong>Nota</strong>: Para las convenciones de nombres de las funciones, debes seguir las mismas reglas que <a href="/en-US/Learn/JavaScript/First_steps/Variables#An_aside_on_variable_naming_rules">convecion de nombres de variables</a>. Esto está bien, ya que puede distinguirlos: los nombres de las funciones aparecen entre paréntesis después de ellos y las variables no.</p> +</div> + +<ol> + <li>Comience accediendo al archivo <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-start.html">function-start.html</a> y haciendo una copia local. Verás que el HTML es simple — el body unicamente tiene un botón. También hemos propocionado algunos estilos básicos de CSS para customizar el mensaje y un elemento {{htmlelement("script")}} vacío para poner nuestro JavaScript dentro.</li> + <li>Luego añade lo siguiente dentro del elemento <code><script></code>: + <pre class="brush: js">function displayMessage() { + +}</pre> + Comenzamos con la palabra clave función, lo que significa que estamos definiendo una función. A esto le sigue el nombre que queremos darle a nuestra función, un conjunto de paréntesis y un conjunto de llaves. Todos los parámetros que queremos darle a nuestra función van dentro de los paréntesis, y el código que se ejecuta cuando llamamos a la función va dentro de las llaves.</li> + <li>Finalmente, agregue el siguiente código dentro de las llaves: + <pre class="brush: js">let html = document.querySelector('html'); + +let panel = document.createElement('div'); +panel.setAttribute('class', 'msgBox'); +html.appendChild(panel); + +let msg = document.createElement('p'); +msg.textContent = 'This is a message box'; +panel.appendChild(msg); + +let closeBtn = document.createElement('button'); +closeBtn.textContent = 'x'; +panel.appendChild(closeBtn); + +closeBtn.onclick = function() { + panel.parentNode.removeChild(panel); +}</pre> + </li> +</ol> + +<p>Esto es un montón de código por el que pasar, así que lo guiaremos paso a paso.</p> + +<p>La primera línea usa un función DOM API llamada {{domxref("document.querySelector()")}} para seleccionar el elemento {{htmlelement("html")}} y guardar una referencia a él en una variable llamada <code>html</code>, por lo que podemos hacer cosas para más adelante:</p> + +<pre class="brush: js">let html = document.querySelector('html');</pre> + +<p>La siguiente sección usa otra función del DOM API llamada {{domxref("Document.createElement()")}} para crear un elemento {{htmlelement("div")}} y guardar una referencia a él en una variable llamada <code>panel</code>. Este elemento será el contenedor exterior de nuestro cuadro de mensaje.</p> + +<p>Entonces usamos otra función del API DOM llamada {{domxref("Element.setAttribute()")}} para configurar un atributo a <code>class</code> en nuestro panel con un valor de <code>msgBox</code>. Esto es para facilitar el estilo del elemento. — Si echas un vistazo al CSS en la página, verás que estamos utilizando un selector de clases<code>.msgBox</code> para dar estilo al al contenedor del mensaje.</p> + +<p>Finalmente, llamamos a una función del DOM llamada {{domxref("Node.appendChild()")}} en la variable <code>html</code> que hemos guardado anteriormente, que anida un elemento dentro del otro como hijo de él. Hemos especificado el panel <code><div></code> como el hijo que queremos añadir dentro del elemento <code><html></code>. Debemos hacer esto ya que el elemento que creamos no aparecerá en la página por sí solo — tenemos que especificar donde ponerlo.</p> + +<pre class="brush: js">let panel = document.createElement('div'); +panel.setAttribute('class', 'msgBox'); +html.appendChild(panel);</pre> + +<p>Las siguientes dos secciones hacen uso de las mismas funciones <code>createElement()</code> y <code>appendChild()</code> que ya vimos para crear dos nuevos elementos — un {{htmlelement("p")}} y un {{htmlelement("button")}} — e insertarlo en la página como un hijo del panel <code><div></code>. Usamos su propiedad {{domxref("Node.textContent")}} — que representa el contenido de texto de un elemento: para insertar un mensaje dentro del párrafo y una 'x' dentro del botón. Este botón será lo que necesita hacer clic / activar cuando el usuario quiera cerrar el cuadro de mensaje.</p> + +<pre class="brush: js">let msg = document.createElement('p'); +msg.textContent = 'This is a message box'; +panel.appendChild(msg); + +let closeBtn = document.createElement('button'); +closeBtn.textContent = 'x'; +panel.appendChild(closeBtn);</pre> + +<p>Finalmente, usamos el manejador de evento {{domxref("GlobalEventHandlers.onclick")}} para hacerlo de modo que cuando se haga clic en el botón, se ejecute algún código para eliminar todo el panel de la página, para cerrar el cuadro de mensaje.</p> + +<p>Brevemente, el handler <code>onclick</code> es una propiedad disponible en el botón (o, de hecho, en cualquier elemento de la página) que se puede configurar en una función para especificar qué código ejecutar cuando se hace clic en el botón. Aprenderás mucho más sobre esto en nuestro artículo de eventos posteriores. Estamos haciendo el handler <code>onclick</code> igual que una función anónima, que contiene el código para ejecutar cuando se ha hecho click en el botón. La línea dentro de la función usa la función del DOM API {{domxref("Node.removeChild()")}} para especificar que queremos eliminar un elemento secundario específico del elemento HTML— en este caso el panel <code><div></code>.</p> + +<pre class="brush: js">closeBtn.onclick = function() { + panel.parentNode.removeChild(panel); +}</pre> + +<p>Básicamente, todo este bloque de código está generando un bloque de HTML que se ve así, y lo está insertando en la página:</p> + +<pre class="brush: html"><div class="msgBox"> + <p>This is a message box</p> + <button>x</button> +</div></pre> + +<p>Fue un montón de código con el que trabajar: ¡no te preocupes demasiado si no recuerdas exactamente cómo funciona todo ahora! La parte principal en la que queremos centrarnos aquí es la estructura y el uso de la función, pero queríamos mostrar algo interesante para este ejemplo.</p> + +<h2 id="Llamando_a_la_función">Llamando a la función</h2> + +<p>Ahora tienes la definición de tu función escrita en tu elemento <script> bien, pero no hará nada tal como está.</p> + +<ol> + <li>Intente incluir la siguiente línea debajo de su función para llamarla: + <pre class="brush: js">displayMessage();</pre> + Esta línea invoca la función, haciéndola correr inmediatamente. Cuando guarde el código y lo vuelva a cargar en el navegador, verá que el pequeño cuadro de mensaje aparece inmediatamente, solo una vez. Después de todo, solo lo llamamos una vez.</li> + <li> + <p>Ahora abra las herramientas de desarrollo de su navegador en la página de ejemplo, vaya a la consola de JavaScript y escriba la línea nuevamente allí, ¡verá que aparece nuevamente! Así que esto es divertido: ahora tenemos una función reutilizable que podemos llamar en cualquier momento que queramos.</p> + + <p>Pero probablemente queremos que aparezca en respuesta a las acciones del usuario y del sistema. En una aplicación real, tal cuadro de mensaje probablemente se llamará en respuesta a la disponibilidad de nuevos datos, a un error, al usuario que intenta eliminar su perfil ("¿está seguro de esto?"), O al usuario que agrega un nuevo contacto y la operación completando con éxito ... etc.</p> + + <p>En esta demostración, obtendremos el cuadro de mensaje que aparecerá cuando el usuario haga clic en el botón.</p> + </li> + <li>Elimina la línea anterior que agregaste.</li> + <li>A continuación, seleccionaremos el botón y guardaremos una referencia a él en una variable. Agregue la siguiente línea a su código, encima de la definición de la función: + <pre class="brush: js">let btn = document.querySelector('button');</pre> + </li> + <li>Finalmente, agregue la siguiente línea debajo de la anterior: + <pre class="brush: js">btn.onclick = displayMessage;</pre> + De una forma similar que nuestra línea dentro de la función <code>closeBtn.onclick...</code>, aquí estamos llamando a algún código en respuesta a un botón al hacer clic. Pero en este caso, en lugar de llamar a una función anónima que contiene algún código, estamos llamando directamente a nuestro nombre de función.</li> + <li>Intente guardar y actualizar la página: ahora debería ver aparecer el cuadro de mensaje cuando hace clic en el botón.</li> +</ol> + +<p>Quizás te estés preguntando por qué no hemos incluido los paréntesis después del nombre de la función. Esto se debe a que no queremos llamar a la función inmediatamente, solo después de hacer clic en el botón. Si intentas cambiar la línea a</p> + +<pre class="brush: js">btn.onclick = displayMessage();</pre> + +<p>y al guardar y volver a cargar, verás que aparece el cuadro de mensaje sin hacer clic en el botón. Los paréntesis en este contexto a veces se denominan "operador de invocación de función". Solo los utiliza cuando desea ejecutar la función inmediatamente en el ámbito actual. Del mismo modo, el código dentro de la función anónima no se ejecuta inmediatamente, ya que está dentro del alcance de la función.</p> + +<p>Si has intentado el último experimento, asegúrate de deshacer el último cambio antes de continuar.</p> + +<h2 id="Mejora_de_la_función_con_parámetros.">Mejora de la función con parámetros.</h2> + +<p>Tal como está, la función aún no es muy útil, no queremos mostrar el mismo mensaje predeterminado cada vez. Mejoremos nuestra función agregando algunos parámetros, permitiéndonos llamarla con algunas opciones diferentes.</p> + +<ol> + <li>En primer lugar, actualice la primera línea de la función: + <pre class="brush: js">function displayMessage() {</pre> + to this: + + <pre class="brush: js">function displayMessage(msgText, msgType) {</pre> + Ahora, cuando llamamos a la función, podemos proporcionar dos valores variables dentro de los paréntesis para especificar el mensaje que se mostrará en el cuadro de mensaje y el tipo de mensaje que es.</li> + <li>Para utilizar el primer parámetro, actualiza la siguiente línea dentro de su función: + <pre class="brush: js">msg.textContent = 'This is a message box';</pre> + to + + <pre class="brush: js">msg.textContent = msgText;</pre> + </li> + <li>Por último, pero no menos importante, ahora necesita actualizar su llamada de función para incluir un texto de mensaje actualizado. Cambia la siguiente línea: + <pre class="brush: js">btn.onclick = displayMessage;</pre> + to this block: + + <pre class="brush: js">btn.onclick = function() { + displayMessage('Woo, this is a different message!'); +};</pre> + Si queremos especificar parámetros dentro de paréntesis para la función a la que estamos llamando, no podemos llamarla directamente, necesitamos colocarla dentro de una función anónima para que no esté en el ámbito inmediato y, por lo tanto, no se llame de inmediato. Ahora no se llamará hasta que se haga clic en el botón.</li> + <li>Vuelva a cargar e intenta el código nuevamente y verás que aún funciona bien, ¡excepto que ahora también puede variar el mensaje dentro del parámetro para obtener diferentes mensajes mostrados en el cuadro!</li> +</ol> + +<h3 id="Un_parámetro_más_complejo.">Un parámetro más complejo.</h3> + +<p>En el siguiente parámetro. Este va a implicar un poco más de trabajo: lo configuraremos de modo que, dependiendo de la configuración del parámetro msgType, la función mostrará un icono diferente y un color de fondo diferente.</p> + +<ol> + <li>En primer lugar, descargue los iconos necesarios para este ejercicio (<a href="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/functions/icons/warning.png">warning</a> y <a href="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/functions/icons/chat.png">chat</a>) de GitHub. Guárdalos en una nueva carpeta llamada <code>icons</code> en la misma localización que tu HTML. + + <div class="note"><strong>Nota</strong>: los iconos <a href="https://www.iconfinder.com/icons/1031466/alarm_alert_error_warning_icon">warning</a> y <a href="https://www.iconfinder.com/icons/1031441/chat_message_text_icon">chat</a> que se encuentran en iconfinder.com, han sido diseñados por <a href="https://www.iconfinder.com/nazarr">Nazarrudin Ansyari</a>. Gracias!</div> + </li> + <li>A continuación, encuentra el CSS dentro de tu archivo HTML. Haremos algunos cambios para dar paso a los iconos. Primero, actualiza el ancho de .msgBox desde: + <pre class="brush: css">width: 200px;</pre> + to + + <pre class="brush: css">width: 242px;</pre> + </li> + <li>Luego, añade las siguientes líneas dentro de la regla<code>.msgBox p { ... }</code>: + <pre class="brush: css">padding-left: 82px; +background-position: 25px center; +background-repeat: no-repeat;</pre> + </li> + <li>Ahora necesitamos añadir código a la función <code>displayMessage()</code> para manejar la visualización de los iconos. Agrega el siguiente bloque justo encima de la llave de cierre (<code>}</code>) de tu función : + <pre class="brush: js">if (msgType === 'warning') { + msg.style.backgroundImage = 'url(icons/warning.png)'; + panel.style.backgroundColor = 'red'; +} else if (msgType === 'chat') { + msg.style.backgroundImage = 'url(icons/chat.png)'; + panel.style.backgroundColor = 'aqua'; +} else { + msg.style.paddingLeft = '20px'; +}</pre> + </li> + <li>Aquí, si el parámetro <code>msgType</code> se establece como <code>'warning'</code>, se muestra el icono de advertencia y el color de fondo del panel se establece en rojo. Si se establece en <code>'chat'</code>, se muestra el icono de chat y el color de fondo del panel se establece en azul aguamarina. Si el parámetro <code>msgType</code> no está configurado en absoluto (o en algo diferente), entonces la parte <code>else { ... }</code> del código entra en juego, y al párrafo simplemente se le da un relleno predeterminado y ningún icono, sin el conjunto de colores del panel de fondo ya sea. Esto proporciona un estado predeterminado si no se proporciona ningún parámetro <code>msgType</code> , lo que significa que es un parámetro opcional.</li> + <li>Vamos a probar nuestra función actualizada , prueba a actualizar la llamada a <code>displayMessage()</code> con esto: + <pre class="brush: js">displayMessage('Woo, this is a different message!');</pre> + to one of these: + + <pre class="brush: js">displayMessage('Your inbox is almost full — delete some mails', 'warning'); +displayMessage('Brian: Hi there, how are you today?','chat');</pre> + Puedes ver cuán útil se está volviendo nuestra (ahora no tan) poca función.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si estas teniendo problemas con el ejemplo, sientente libre para coger el ejemplo para trabajar con él, <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-stage-4.html">finished version on GitHub</a> (<a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/function-stage-4.html">see it running live</a> también), o pídenos ayuda.</p> +</div> + +<h2 id="Conclusión">Conclusión</h2> + +<p>¡Felicidades por llegar al final! Este artículo lo llevó a través de todo el proceso de creación de una función personalizada y práctica, que con un poco más de trabajo podría trasplantarse en un proyecto real. En el siguiente artículo resumiremos las funciones explicando otro concepto esencial relacionado: valores de retorno.</p> + +<ul> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Functions","Learn/JavaScript/Building_blocks/Return_values", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> diff --git a/files/es/learn/javascript/building_blocks/eventos/index.html b/files/es/learn/javascript/building_blocks/eventos/index.html new file mode 100644 index 0000000000..7bdb81768a --- /dev/null +++ b/files/es/learn/javascript/building_blocks/eventos/index.html @@ -0,0 +1,578 @@ +--- +title: Introducción a eventos +slug: Learn/JavaScript/Building_blocks/Eventos +translation_of: Learn/JavaScript/Building_blocks/Events +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">Los eventos son acciones u ocurrencias que suceden en el sistema que está programando y que el sistema le informa para que pueda responder de alguna manera si lo desea. Por ejemplo, si el usuario hace clic en un botón en una página web, es posible que desee responder a esa acción mostrando un cuadro de información. En este artículo, discutiremos algunos conceptos importantes que rodean los eventos y veremos cómo funcionan en los navegadores. Este no será un estudio exhaustivo; solo lo que necesitas saber en esta etapa.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, entendimiento básico de HTML y CSS, <a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps">Primeros pasos con JavaScript</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender la teoría fundamental de los eventos, cómo funcionan en los navegadores y cómo los eventos pueden diferir en distintos entornos de programación.</td> + </tr> + </tbody> +</table> + +<h2 id="Una_serie_de_eventos_afortunados">Una serie de eventos afortunados</h2> + +<p>Como se mencionó anteriormente, los <strong>eventos</strong> son acciones u ocurrencias que suceden en el sistema que está programando — el sistema disparará una señal de algún tipo cuando un evento ocurra y también proporcionará un mecanismo por el cual se puede tomar algún tipo de acción automáticamente (p.e., ejecutando algún código) cuando se produce el evento. Por ejemplo, en un aeropuerto cuando la pista está despejada para que despegue un avión, se comunica una señal al piloto y, como resultado, comienzan a pilotar el avión.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14077/MDN-mozilla-events-runway.png" style="display: block; margin: 0px auto;"></p> + +<p>En el caso de la Web, los eventos se desencadenan dentro de la ventana del navegador y tienden a estar unidos a un elemento específico que reside en ella — podría ser un solo elemento, un conjunto de elementos, el documento HTML cargado en la pestaña actual o toda la ventana del navegador. Hay muchos tipos diferentes de eventos que pueden ocurrir, por ejemplo:</p> + +<ul> + <li>El usuario hace clic con el mouse sobre un elemento determinado o coloca el cursor sobre un elemento determinado.</li> + <li>El usuario presiona una tecla en el teclado.</li> + <li>El usuario cambia el tamaño o cierra la ventana del navegador.</li> + <li>Una página web termina de cargar.</li> + <li>Un formulario se envía</li> + <li>Un video se reproduce, pausa o finaliza la reproducción.</li> + <li>Un error ocurre.</li> +</ul> + +<p>Se deducirá de esto (y echar un vistazo a MDN <a href="https://developer.mozilla.org/es/docs/Web/Events">Referencia de eventos</a>) que hay <strong>muchos</strong> eventos a los que se puede responder.</p> + +<p>Cada evento disponible tiene un <strong>controlador de eventos</strong>, que es un bloque de código (generalmente una función JavaScript definida por el usuario) que se ejecutará cuando se active el evento. Cuando dicho bloque de código se define para ejecutarse en respuesta a un disparo de evento, decimos que estamos <strong>registrando un controlador de eventos</strong>. Tenga en cuenta que los controladores de eventos a veces se llaman <strong>oyentes de eventos</strong> — son bastante intercambiables para nuestros propósitos, aunque estrictamente hablando, trabajan juntos. El oyente escucha si ocurre el evento y el controlador es el código que se ejecuta en respuesta a que ocurra.</p> + +<div class="note"> +<p><strong>Nota</strong>: Es útil tener en cuenta que los eventos web no son parte del lenguaje central de JavaScript: se definen como parte de las API integradas en el navegador.</p> +</div> + +<h3 id="Un_ejemplo_simple">Un ejemplo simple</h3> + +<p>Veamos un ejemplo simple para explicar lo que queremos decir aquí. Ya has visto eventos y controladores de eventos en muchos de los ejemplos de este curso, pero vamos a recapitular solo para consolidar nuestro conocimiento. En el siguiente ejemplo, tenemos un solo {{htmlelement ("button")}}, que cuando se presiona, hará que el fondo cambie a un color aleatorio:</p> + +<pre class="brush: html notranslate"><button>Cambiar color</button></pre> + +<div class="hidden"> +<pre class="brush: css notranslate">button { margin: 10px };</pre> +</div> + +<p>El JavaScript se ve así:</p> + +<pre class="brush: js notranslate">const btn = document.querySelector('button'); + +function random(number) { + return Math.floor(Math.random() * (number+1)); +} + +btn.onclick = function() { + const rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; + document.body.style.backgroundColor = rndCol; +}</pre> + +<p>En este código, almacenamos una referencia al botón dentro de una variable llamada <code>btn</code>, usando la función {{domxref ("Document.querySelector ()")}}. También definimos una función que devuelve un número aleatorio. La tercera parte del código es el controlador de eventos. La variable <code>btn</code> apunta a un elemento <code><button></code>, y este tipo de objeto tiene una serie de eventos que pueden activarse y, por lo tanto, los controladores de eventos están disponibles. Estamos escuchando el disparo del evento "click", estableciendo la propiedad del controlador de eventos <code>onclick</code> para que sea igual a una función anónima que contiene código que generó un color RGB aleatorio y establece el <code><body></code> color de fondo igual a este.</p> + +<p>Este código ahora se ejecutará cada vez que se active el evento "click" en el elemento <code><button></code>, es decir, cada vez que un usuario haga clic en él.</p> + +<p>El resultado de ejemplo es el siguiente:</p> + +<p>{{ EmbedLiveSample('A_simple_example', '100%', 200, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="No_son_solo_páginas_web">No son solo páginas web</h3> + +<p>Otra cosa que vale la pena mencionar en este punto es que los eventos no son particulares de JavaScript — la mayoría de los lenguajes de programación tienen algún tipo de modelo de eventos, y la forma en que funciona a menudo diferirá de la forma en que funciona en JavaScript. De hecho, el modelo de eventos en JavaScript para páginas web difiere del modelo de eventos para JavaScript, ya que se utiliza en otros entornos.</p> + +<p>Por ejemplo, <a href="/en-US/docs/Learn/Server-side/Express_Nodejs">Node.js</a> es un entorno en tiempo de ejecución de JavaScript muy popular que permite a los desarrolladores usar JavaScript para crear aplicaciones de red y del lado del servidor. El <a href="https://nodejs.org/docs/latest-v5.x/api/events.html">modelo de eventos de Node.js</a> se basa en que los oyentes (<em>listeners</em>) escuchen eventos y los emisores (<em>emitters</em>) emitan eventos periódicamente — no suena tan diferentes, pero el código es bastante diferente, haciendo uso de funciones como <code>on()</code> para registrar un oyente de eventos, y <code>once()</code> para registrar un oyente de eventos que anula el registro después de que se haya ejecutado una vez. The <a href="https://nodejs.org/docs/latest-v8.x/api/http.html#http_event_connect">documentos de eventos de conexión HTTP</a> proporcionan un buen ejemplo de uso.</p> + +<p>Como otro ejemplo, ahora también puede usar JavaScript para crear complementos de navegadores — mejoras de funcionalidad del navegador — utilizando una tecnología llamada <a href="/en-US/docs/Mozilla/Add-ons/WebExtensions">WebExtensions</a>. El modelo de eventos es similar al modelo de eventos web, pero un poco diferente — las propiedades de los oyentes de eventos se escriben en <em>camel-case</em> (ej. <code>onMessage</code> en lugar de <code>onmessage</code>), y deben combinarse con la función <code>addListener</code>. Consulte la página <a href="/en-US/Add-ons/WebExtensions/API/runtime/onMessage#Examples">runtime.onMessage </a>para ver un ejemplo.</p> + +<p>No necesita comprender nada sobre otros entornos en esta etapa de su aprendizaje; solo queríamos dejar en claro que los eventos pueden diferir en diferentes entornos de programación.</p> + +<h2 id="Diferentes_formas_de_uso_de_eventos">Diferentes formas de uso de eventos</h2> + +<p>Hay muchas maneras distintas en las que puedes agregar event listeners a los sitios web, que se ejecutara cuando el evento asociado se dispare. En esta sección, revisaremos los diferentes mecanismos y discutiremos cuales deberias usar..</p> + +<h3 id="Propiedades_de_manejadores_de_eventos">Propiedades de manejadores de eventos</h3> + +<p>Estas son las propiedades que existen, que contienen codigo de manejadores de eventos(Event Handler) que vemos frecuentemente durante el curso.. Volviendo al ejemplo de arriba:</p> + +<pre class="brush: js notranslate">var btn = document.querySelector('button'); + +btn.onclick = function() { + var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; + document.body.style.backgroundColor = rndCol; +}</pre> + +<p>La propiedad <code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onclick">onclick</a></code> es la propiedad del manejador de eventos que está siendo usada en esta situación. Es escencialmente una propiedad como cualquier otra disponible en el botón (por ejemplo: <code><a href="/en-US/docs/Web/API/Node/textContent">btn.textContent</a></code>, or <code><a href="/en-US/docs/Web/API/HTMLElement/style">btn.style</a></code>), pero es de un tipo especial — cuando lo configura para ser igual a algún código, ese código se ejecutará cuando el evento se dispare en el botón.</p> + +<p>You could also set the handler property to be equal to a named function name (like we saw in <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a>). The following would work just the same:</p> + +<pre class="brush: js notranslate">var btn = document.querySelector('button'); + +function bgChange() { + var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; + document.body.style.backgroundColor = rndCol; +} + +btn.onclick = bgChange;</pre> + +<p>There are many different event handler properties available. Let's do an experiment.</p> + +<p>First of all, make a local copy of <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventhandlerproperty.html">random-color-eventhandlerproperty.html</a>, and open it in your browser. It's just a copy of the simple random color example we've been playing with already in this article. Now try changing <code>btn.onclick</code> to the following different values in turn, and observing the results in the example:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onfocus">btn.onfocus</a></code> and <code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onblur">btn.onblur</a></code> — The color will change when the button is focused and unfocused (try pressing tab to tab on to the button and off again). These are often used to display information about how to fill in form fields when they are focused, or display an error message if a form field has just been filled in with an incorrect value.</li> + <li><code><a href="/en-US/docs/Web/API/GlobalEventHandlers/ondblclick">btn.ondblclick</a></code> — The color will change only when it is double-clicked.</li> + <li><code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onkeypress">window.onkeypress</a></code>, <code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onkeydown">window.onkeydown</a></code>, <code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onkeyup">window.onkeyup</a></code> — The color will change when a key is pressed on the keyboard. <code>keypress</code> refers to a general press (button down and then up), while <code>keydown</code> and <code>keyup</code> refer to just the key down and key up parts of the keystroke, respectively. Note that it doesn't work if you try to register this event handler on the button itself — we've had to register it on the <a href="/en-US/docs/Web/API/Window">window</a> object, which represents the entire browser window.</li> + <li><code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onmouseover">btn.onmouseover</a></code> and <code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onmouseout">btn.onmouseout</a></code> — The color will change when the mouse pointer is moved so it begins hovering over the button, or when it stops hovering over the button and moves off of it, respectively.</li> +</ul> + +<p>Some events are very general and available nearly anywhere (for example an <code>onclick</code> handler can be registered on nearly any element), whereas some are more specific and only useful in certain situations (for example it makes sense to use <a href="/en-US/docs/Web/API/GlobalEventHandlers/GlobalEventHandlers.onplay">onplay</a> only on specific elements, such as {{htmlelement("video")}}).</p> + +<h3 id="Inline_event_handlers_—_dont_use_these">Inline event handlers — don't use these</h3> + +<p>You might also see a pattern like this in your code:</p> + +<pre class="brush: html notranslate"><button onclick="bgChange()">Press me</button> +</pre> + +<pre class="brush: js notranslate">function bgChange() { + var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; + document.body.style.backgroundColor = rndCol; +}</pre> + +<div class="note"> +<p><strong>Note</strong>: You can find the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventhandlerattributes.html">full source code</a> for this example on GitHub (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-eventhandlerattributes.html">see it running live</a>).</p> +</div> + +<p>The earliest method of registering event handlers found on the Web involved <strong>event handler HTML attributes</strong> (aka <strong>inline event handlers</strong>) like the one shown above — the attribute value is literally the JavaScript code you want to run when the event occurs. The above example invokes a function defined inside a {{htmlelement("script")}} element on the same page, but you could also insert JavaScript directly inside the attribute, for example:</p> + +<pre class="brush: html notranslate"><button onclick="alert('Hello, this is my old-fashioned event handler!');">Press me</button></pre> + +<p>You'll find HTML attribute equivalents for many of the event handler properties; however, you shouldn't use these — they are considered bad practice. It might seem easy to use an event handler attribute if you are just doing something really quick, but they very quickly become unmanageable and inefficient.</p> + +<p>For a start, it is not a good idea to mix up your HTML and your JavaScript, as it becomes hard to parse — keeping your JavaScript all in one place is better; if it is in a separate file you can apply it to multiple HTML documents.</p> + +<p>Even in a single file, inline event handlers are not a good idea. One button is OK, but what if you had 100 buttons? You'd have to add 100 attributes to the file; it would very quickly turn into a maintenance nightmare. With JavaScript, you could easily add an event handler function to all the buttons on the page no matter how many there were, using something like this:</p> + +<pre class="brush: js notranslate">var buttons = document.querySelectorAll('button'); + +for (var i = 0; i < buttons.length; i++) { + buttons[i].onclick = bgChange; +}</pre> + +<p class="brush: js">Note that another option here would be to use the <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach">forEach()</a></code> built-in method available on all Array objects:</p> + +<pre class="brush: js notranslate">buttons.forEach(function(button) { + button.onclick = bgChange; +});</pre> + +<div class="note"> +<p><strong>Note</strong>: Separating your programming logic from your content also makes your site more friendly to search engines.</p> +</div> + +<h3 id="addEventListener_and_removeEventListener">addEventListener() and removeEventListener()</h3> + +<p>The newest type of event mechanism is defined in the <a href="https://www.w3.org/TR/DOM-Level-2-Events/">Document Object Model (DOM) Level 2 Events</a> Specification, which provides browsers with a new function — <code><a href="/en-US/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>. This functions in a similar way to the event handler properties, but the syntax is obviously different. We could rewrite our random color example to look like this:</p> + +<pre class="brush: js notranslate">var btn = document.querySelector('button'); + +function bgChange() { + var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; + document.body.style.backgroundColor = rndCol; +} + +btn.addEventListener('click', bgChange);</pre> + +<div class="note"> +<p><strong>Note</strong>: You can find the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-addeventlistener.html">full source code</a> for this example on GitHub (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-addeventlistener.html">see it running live</a>).</p> +</div> + +<p>Inside the <code>addEventListener()</code> function, we specify two parameters — the name of the event we want to register this handler for, and the code that comprises the handler function we want to run in response to it. Note that it is perfectly appropriate to put all the code inside the <code>addEventListener()</code> function, in an anonymous function, like this:</p> + +<pre class="brush: js notranslate">btn.addEventListener('click', function() { + var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; + document.body.style.backgroundColor = rndCol; +});</pre> + +<p>This mechanism has some advantages over the older mechanisms discussed earlier. For a start, there is a counterpart function, <code><a href="/en-US/docs/Web/API/EventTarget/removeEventListener">removeEventListener()</a></code>, which removes a previously added listener. For example, this would remove the listener set in the first code block in this section:</p> + +<pre class="brush: js notranslate">btn.removeEventListener('click', bgChange);</pre> + +<p>This isn't significant for simple, small programs, but for larger, more complex programs it can improve efficiency to clean up old unused event handlers. Plus, for example, this allows you to have the same button performing different actions in different circumstances — all you've got to do is add/remove event handlers as appropriate.</p> + +<p>Second, you can also register multiple handlers for the same listener. The following two handlers would not be applied:</p> + +<pre class="brush: js notranslate">myElement.onclick = functionA; +myElement.onclick = functionB;</pre> + +<p>As the second line would overwrite the value of <code>onclick</code> set by the first. This would work, however:</p> + +<pre class="brush: js notranslate">myElement.addEventListener('click', functionA); +myElement.addEventListener('click', functionB);</pre> + +<p>Both functions would now run when the element is clicked.</p> + +<p>In addition, there are a number of other powerful features and options available with this event mechanism. These are a little out of scope for this article, but if you want to read up on them, have a look at the <code><a href="/en-US/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code> and <code><a href="/en-US/docs/Web/API/EventTarget/removeEventListener">removeEventListener()</a></code> reference pages.</p> + +<h3 id="What_mechanism_should_I_use">What mechanism should I use?</h3> + +<p>Of the three mechanisms, you definitely shouldn't use the HTML event handler attributes — these are outdated, and bad practice, as mentioned above.</p> + +<p>The other two are relatively interchangeable, at least for simple uses:</p> + +<ul> + <li>Event handler properties have less power and options, but better cross-browser compatibility (being supported as far back as Internet Explorer 8). You should probably start with these as you are learning.</li> + <li>DOM Level 2 Events (<code>addEventListener()</code>, etc.) are more powerful, but can also become more complex and are less well supported (supported as far back as Internet Explorer 9). You should also experiment with these, and aim to use them where possible.</li> +</ul> + +<p>The main advantages of the third mechanism are that you can remove event handler code if needed, using <code>removeEventListener()</code>, and you can add multiple listeners of the same type to elements if required. For example, you can call <code>addEventListener('click', function() { ... })</code> on an element multiple times, with different functions specified in the second argument. This is impossible with event handler properties because any subsequent attempts to set a property will overwrite earlier ones, e.g.:</p> + +<pre class="brush: js notranslate">element.onclick = function1; +element.onclick = function2; +etc.</pre> + +<div class="note"> +<p><strong>Note</strong>: If you are called upon to support browsers older than Internet Explorer 8 in your work, you may run into difficulties, as such ancient browsers use different event models from newer browsers. But never fear, most JavaScript libraries (for example <code>jQuery</code>) have built-in functions that abstract away cross-browser differences. Don't worry about this too much at this stage in your learning journey.</p> +</div> + +<h2 id="Other_event_concepts">Other event concepts</h2> + +<p>In this section, we will briefly cover some advanced concepts that are relevant to events. It is not important to understand these fully at this point, but it might serve to explain some code patterns you'll likely come across from time to time.</p> + +<h3 id="Event_objects">Event objects</h3> + +<p>Sometimes inside an event handler function, you might see a parameter specified with a name such as <code>event</code>, <code>evt</code>, or simply <code>e</code>. This is called the <strong>event object</strong>, and it is automatically passed to event handlers to provide extra features and information. For example, let's rewrite our random color example again slightly:</p> + +<pre class="brush: js notranslate">function bgChange(e) { + var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; + e.target.style.backgroundColor = rndCol; + console.log(e); +} + +btn.addEventListener('click', bgChange);</pre> + +<div class="note"> +<p><strong>Note</strong>: You can find the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/random-color-eventobject.html">full source code</a> for this example on GitHub (also <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/random-color-eventobject.html">see it running live</a>).</p> +</div> + +<p>Here you can see that we are including an event object, <strong>e</strong>, in the function, and in the function setting a background color style on <code>e.target</code> — which is the button itself. The <code>target</code> property of the event object is always a reference to the element that the event has just occurred upon. So in this example, we are setting a random background color on the button, not the page.</p> + +<div class="note"> +<p><strong>Note</strong>: You can use any name you like for the event object — you just need to choose a name that you can then use to reference it inside the event handler function. <code>e</code>/<code>evt</code>/<code>event</code> are most commonly used by developers because they are short and easy to remember. It's always good to stick to a standard.</p> +</div> + +<p><code>e.target</code> is incredibly useful when you want to set the same event handler on multiple elements and do something to all of them when an event occurs on them. You might, for example, have a set of 16 tiles that disappear when they are clicked on. It is useful to always be able to just set the thing to disappear as <code>e.target</code>, rather than having to select it in some more difficult way. In the following example (see <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/useful-eventtarget.html">useful-eventtarget.html</a> for the full source code; also see it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/useful-eventtarget.html">running live</a> here), we create 16 {{htmlelement("div")}} elements using JavaScript. We then select all of them using {{domxref("document.querySelectorAll()")}}, then loop through each one, adding an <code>onclick</code> handler to each that makes it so that a random color is applied to each one when clicked:</p> + +<pre class="brush: js notranslate">var divs = document.querySelectorAll('div'); + +for (var i = 0; i < divs.length; i++) { + divs[i].onclick = function(e) { + e.target.style.backgroundColor = bgChange(); + } +}</pre> + +<p>The output is as follows (try clicking around on it — have fun):</p> + +<div class="hidden"> +<h6 id="Hidden_example">Hidden example</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Useful event target example</title> + <style> + div { + height: 100px; + width: 25%; + float: left; + } + </style> + </head> + <body> + <script> + for (var i = 1; i <= 16; i++) { + var myDiv = document.createElement('div'); + myDiv.style.backgroundColor = "red"; + document.body.appendChild(myDiv); + } + + function random(number) { + return Math.floor(Math.random()*number); + } + + function bgChange() { + var rndCol = 'rgb(' + random(255) + ',' + random(255) + ',' + random(255) + ')'; + return rndCol; + } + + var divs = document.querySelectorAll('div'); + + for (var i = 0; i < divs.length; i++) { + divs[i].onclick = function(e) { + e.target.style.backgroundColor = bgChange(); + } + } + </script> + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_example', '100%', 400, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Most event handlers you'll encounter just have a standard set of properties and functions (methods) available on the event object (see the {{domxref("Event")}} object reference for a full list). Some more advanced handlers, however, add specialist properties containing extra data that they need to function. The <a href="/en-US/docs/Web/API/MediaRecorder_API">Media Recorder API</a>, for example, has a <code>dataavailable</code> event, which fires when some audio or video has been recorded and is available for doing something with (for example saving it, or playing it back). The corresponding <a href="/en-US/docs/Web/API/MediaRecorder/ondataavailable">ondataavailable</a> handler's event object has a <code>data</code> property available containing the recorded audio or video data to allow you to access it and do something with it.</p> + +<h3 id="Preventing_default_behavior">Preventing default behavior</h3> + +<p>Sometimes, you'll come across a situation where you want to stop an event doing what it does by default. The most common example is that of a web form, for example, a custom registration form. When you fill in the details and press the submit button, the natural behaviour is for the data to be submitted to a specified page on the server for processing, and the browser to be redirected to a "success message" page of some kind (or the same page, if another is not specified.)</p> + +<p>The trouble comes when the user has not submitted the data correctly — as a developer, you'll want to stop the submission to the server and give them an error message telling them what's wrong and what needs to be done to put things right. Some browsers support automatic form data validation features, but since many don't, you are advised to not rely on those and implement your own validation checks. Let's look at a simple example.</p> + +<p>First, a simple HTML form that requires you to enter your first and last name:</p> + +<pre class="brush: html notranslate"><form> + <div> + <label for="fname">First name: </label> + <input id="fname" type="text"> + </div> + <div> + <label for="lname">Last name: </label> + <input id="lname" type="text"> + </div> + <div> + <input id="submit" type="submit"> + </div> +</form> +<p></p></pre> + +<div class="hidden"> +<pre class="brush: css notranslate">div { + margin-bottom: 10px; +} +</pre> +</div> + +<p>Now some JavaScript — here we implement a very simple check inside an <a href="/en-US/docs/Web/API/GlobalEventHandlers/onsubmit">onsubmit</a> event handler (the submit event is fired on a form when it is submitted) that tests whether the text fields are empty. If they are, we call the <code><a href="/en-US/docs/Web/API/Event/preventDefault">preventDefault()</a></code> function on the event object — which stops the form submission — and then display an error message in the paragraph below our form to tell the user what's wrong:</p> + +<pre class="brush: js notranslate">var form = document.querySelector('form'); +var fname = document.getElementById('fname'); +var lname = document.getElementById('lname'); +var submit = document.getElementById('submit'); +var para = document.querySelector('p'); + +form.onsubmit = function(e) { + if (fname.value === '' || lname.value === '') { + e.preventDefault(); + para.textContent = 'You need to fill in both names!'; + } +}</pre> + +<p>Obviously, this is pretty weak form validation — it wouldn't stop the user validating the form with spaces or numbers entered into the fields, for example — but it is ok for example purposes. The output is as follows:</p> + +<p>{{ EmbedLiveSample('Preventing_default_behavior', '100%', 140, "", "", "hide-codepen-jsfiddle") }}</p> + +<div class="note"> +<p><strong>Note</strong>: for the full source code, see <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/preventdefault-validation.html">preventdefault-validation.html</a> (also see it <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/preventdefault-validation.html">running live</a> here.)</p> +</div> + +<h3 id="Event_bubbling_and_capture">Event bubbling and capture</h3> + +<p>The final subject to cover here is something that you'll not come across often, but it can be a real pain if you don't understand it. Event bubbling and capture are two mechanisms that describe what happens when two handlers of the same event type are activated on one element. Let's look at an example to make this easier — open up the <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/show-video-box.html">show-video-box.html</a> example in a new tab (and the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box.html">source code</a> in another tab.) It is also available live below:</p> + +<div class="hidden"> +<h6 id="Hidden_video_example">Hidden video example</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Show video box example</title> + <style> + div { + position: absolute; + top: 50%; + transform: translate(-50%,-50%); + width: 480px; + height: 380px; + border-radius: 10px; + background-color: #eee; + background-image: linear-gradient(to bottom, rgba(0,0,0,0), rgba(0,0,0,0.1)); + } + + .hidden { + left: -50%; + } + + .showing { + left: 50%; + } + + div video { + display: block; + width: 400px; + margin: 40px auto; + } + + </style> + </head> + <body> + <button>Display video</button> + + <div class="hidden"> + <video> + <source src="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/events/rabbit320.mp4" type="video/mp4"> + <source src="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/events/rabbit320.webm" type="video/webm"> + <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p> + </video> + </div> + + <script> + + var btn = document.querySelector('button'); + var videoBox = document.querySelector('div'); + var video = document.querySelector('video'); + + btn.onclick = function() { + displayVideo(); + } + + function displayVideo() { + if(videoBox.getAttribute('class') === 'hidden') { + videoBox.setAttribute('class','showing'); + } + } + + videoBox.addEventListener('click',function() { + videoBox.setAttribute('class','hidden'); + }); + + video.addEventListener('click',function() { + video.play(); + }); + + </script> + </body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_video_example', '100%', 500, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>This is a pretty simple example that shows and hides a {{htmlelement("div")}} with a {{htmlelement("video")}} element inside it:</p> + +<pre class="brush: html notranslate"><button>Display video</button> + +<div class="hidden"> + <video> + <source src="rabbit320.mp4" type="video/mp4"> + <source src="rabbit320.webm" type="video/webm"> + <p>Your browser doesn't support HTML5 video. Here is a <a href="rabbit320.mp4">link to the video</a> instead.</p> + </video> +</div></pre> + +<p>When the {{htmlelement("button")}} is clicked, the video is displayed, by changing the class attribute on the <code><div></code> from <code>hidden</code> to <code>showing</code> (the example's CSS contains these two classes, which position the box off the screen and on the screen, respectively):</p> + +<pre class="brush: js notranslate">btn.onclick = function() { + videoBox.setAttribute('class', 'showing'); +}</pre> + +<p>We then add a couple more <code>onclick</code> event handlers — the first one to the <code><div></code> and the second one to the <code><video></code>. The idea is that when the area of the <code><div></code> outside the video is clicked, the box should be hidden again; when the video itself is clicked, the video should start to play.</p> + +<pre class="brush: js notranslate">videoBox.onclick = function() { + videoBox.setAttribute('class', 'hidden'); +}; + +video.onclick = function() { + video.play(); +};</pre> + +<p>But there's a problem — currently, when you click the video it starts to play, but it causes the <code><div></code> to also be hidden at the same time. This is because the video is inside the <code><div></code> — it is part of it — so clicking on the video actually runs <em>both</em> the above event handlers.</p> + +<h4 id="Bubbling_and_capturing_explained">Bubbling and capturing explained</h4> + +<p>When an event is fired on an element that has parent elements (e.g. the {{htmlelement("video")}} in our case), modern browsers run two different phases — the <strong>capturing</strong> phase and the <strong>bubbling</strong> phase.</p> + +<p>In the <strong>capturing</strong> phase:</p> + +<ul> + <li>The browser checks to see if the element's outer-most ancestor ({{htmlelement("html")}}) has an <code>onclick</code> event handler registered on it in the capturing phase, and runs it if so.</li> + <li>Then it moves on to the next element inside <code><html></code> and does the same thing, then the next one, and so on until it reaches the element that was actually clicked on.</li> +</ul> + +<p>In the <strong>bubbling</strong> phase, the exact opposite occurs:</p> + +<ul> + <li>The browser checks to see if the element that was actually clicked on has an <code>onclick</code> event handler registered on it in the bubbling phase, and runs it if so.</li> + <li>Then it moves on to the next immediate ancestor element and does the same thing, then the next one, and so on until it reaches the <code><html></code> element.</li> +</ul> + +<p><a href="https://mdn.mozillademos.org/files/14075/bubbling-capturing.png"><img alt="" src="https://mdn.mozillademos.org/files/14075/bubbling-capturing.png" style="display: block; height: 452px; margin: 0px auto; width: 960px;"></a></p> + +<p>(Click on image for bigger diagram)</p> + +<p>In modern browsers, by default, all event handlers are registered in the bubbling phase. So in our current example, when you click the video, the click event bubbles from the <code><video></code> element outwards to the <code><html></code> element. Along the way:</p> + +<ul> + <li>It finds the <code>video.onclick...</code> handler and runs it, so the video first starts playing.</li> + <li>It then finds the <code>videoBox.onclick...</code> handler and runs it, so the video is hidden as well.</li> +</ul> + +<h4 id="Fixing_the_problem_with_stopPropagation">Fixing the problem with stopPropagation()</h4> + +<p>This is annoying behavior, but there is a way to fix it! The standard event object has a function available on it called <code><a href="/en-US/docs/Web/API/Event/stopPropagation">stopPropagation()</a></code>, which when invoked on a handler's event object makes it so that handler is run, but the event doesn't bubble any further up the chain, so no more handlers will be run.</p> + +<p>We can, therefore, fix our current problem by changing the second handler function in the previous code block to this:</p> + +<pre class="brush: js notranslate">video.onclick = function(e) { + e.stopPropagation(); + video.play(); +};</pre> + +<p>You can try making a local copy of the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box.html">show-video-box.html source code</a> and having a go at fixing it yourself, or looking at the fixed result in <a href="http://mdn.github.io/learning-area/javascript/building-blocks/events/show-video-box-fixed.html">show-video-box-fixed.html</a> (also see the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/events/show-video-box-fixed.html">source code</a> here).</p> + +<div class="note"> +<p><strong>Note</strong>: Why bother with both capturing and bubbling? Well, in the bad old days when browsers were much less cross-compatible than they are now, Netscape only used event capturing, and Internet Explorer used only event bubbling. When the W3C decided to try to standardize the behavior and reach a consensus, they ended up with this system that included both, which is the one modern browsers implemented.</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: As mentioned above, by default all event handlers are registered in the bubbling phase, and this makes more sense most of the time. If you really want to register an event in the capturing phase instead, you can do so by registering your handler using <code><a href="/en-US/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>, and setting the optional third property to <code>true</code>.</p> +</div> + +<h4 id="Event_delegation">Event delegation</h4> + +<p>Bubbling also allows us to take advantage of <strong>event delegation</strong> — this concept relies on the fact that if you want some code to run when you click on any one of a large number of child elements, you can set the event listener on their parent and have events that happen on them bubble up to their parent rather than having to set the event listener on every child individually. Remember earlier that we said bubbling involves checking the element the event is fired on for an event handler first, then moving up to the element's parent, etc.?</p> + +<p>A good example is a series of list items — if you want each one of them to pop up a message when clicked, you can set the <code>click</code> event listener on the parent <code><ul></code>, and events will bubble from the list items to the <code><ul></code>.</p> + +<p>This concept is explained further on David Walsh's blog, with multiple examples — see <a href="https://davidwalsh.name/event-delegate">How JavaScript Event Delegation Works</a>.</p> + +<h2 id="Conclusion">Conclusion</h2> + +<p>You should now know all you need to know about web events at this early stage. As mentioned above, events are not really part of the core JavaScript — they are defined in browser Web APIs.</p> + +<p>Also, it is important to understand that the different contexts in which JavaScript is used tend to have different event models — from Web APIs to other areas such as browser WebExtensions and Node.js (server-side JavaScript). We are not expecting you to understand all these areas now, but it certainly helps to understand the basics of events as you forge ahead with learning web development.</p> + +<p>If there is anything you didn't understand, feel free to read through the article again, or <a href="/en-US/Learn#Contact_us">contact us</a> to ask for help.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="http://www.quirksmode.org/js/events_order.html">Event order</a> (discussion of capturing and bubbling) — an excellently detailed piece by Peter-Paul Koch.</li> + <li><a href="http://www.quirksmode.org/js/events_access.html">Event accessing</a> (discussion of the event object) — another excellently detailed piece by Peter-Paul Koch.</li> + <li><a href="/en-US/docs/Web/Events">Event reference</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Return_values","Learn/JavaScript/Building_blocks/Image_gallery", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> diff --git a/files/es/learn/javascript/building_blocks/functions/index.html b/files/es/learn/javascript/building_blocks/functions/index.html new file mode 100644 index 0000000000..d05ae34969 --- /dev/null +++ b/files/es/learn/javascript/building_blocks/functions/index.html @@ -0,0 +1,400 @@ +--- +title: Funciones — bloques de código reutilizables +slug: Learn/JavaScript/Building_blocks/Functions +tags: + - API + - Funciones + - JavaScript + - Métodos + - Navegador +translation_of: Learn/JavaScript/Building_blocks/Functions +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">Otro concepto esencial en la codificación son las <strong>funciones</strong>, que te permiten almacenar un fragmento de código que realiza una única tarea dentro de un bloque definido, y luego llamar a ese código siempre que lo necesites utilizando un único comando breve -- en lugar de tener que escribir el mismo codigo varias veces. En este artículo exploraremos conceptos fundamentales detrás de funciones tales como sintaxis básica, cómo invocarlas y definirlas, alcance(scope) y parámetros.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Conocimientos basicos de informatica, conocimiento basico de HTML y CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>Entender los conceptos fundamentales detras de las funciones JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Dónde_encuentro_las_funciones">¿Dónde encuentro las funciones? </h2> + +<p>En JavaScript vas a encontrar funciones por todos lados. De hecho, nosotros hemos usados funciones todo el tiempo a lo largo del curso; solo que no hemos hablado mucho sobre ellas. Ahora es el momento, igual, para comenzar a hablar explicitamente sobre las funciones y explorar su sintaxis.</p> + +<p>Básicamente cada vez que haces uso de código JavaScript que contiene parentesis como () y no estás usando estructuras de lenguaje como for loop, while, do, do while, estás usando una función! </p> + +<p>Funciones incluídas en los navegadores</p> + +<p>A lo largo de este curso hemos usado muchas funciones incluídas del navegador. Por ejemplo, cuando manipulamos una cadena de texto o <a href="/es/docs/Web/JavaScript/Referencia/Objetos_globales/String">string</a>:</p> + +<pre class="brush: js notranslate">let miTexto = 'Soy una cadena de texto!'; +let nuevaCadena = miTexto.replace('cadena', 'ensalada'); +console.log(nuevaCadena); +// la función de cadena de texto <strong>replace()</strong> toma una cadena, +// reemplaza una palabra por otra, y devuelve +// una nueva cadena con el reemplazo hecho.</pre> + +<p>O cada vez que manipulamos un <a href="/es/docs/Web/JavaScript/Referencia/Objetos_globales/Array">array</a>:</p> + +<pre class="brush: js notranslate">let miArray = ['Yo', 'amo', 'el', 'chocolate', 'y', 'las', 'ranas']; +let armarCadena = miArray.join(' '); +console.log(armarCadena); +// La función join() toma un array, +// une todos sus elementos en una cadena o string +// y devuelve esta nueva cadena.</pre> + +<p>O cada vez que generamos un número al azar:</p> + +<pre class="brush: js notranslate">var miNumero = Math.random(); +console.log(miNumero); +// La función <a href="/es/docs/Web/JavaScript/Referencia/Objetos_globales/Math/random">Math.random()</a> genera un número aleatorio +// entre 0 and 1 y devuelve ese número. +</pre> + +<p>...estamos usando una función!</p> + +<div class="note"> +<p><strong>Nota</strong>: Sientase libre de ingresar esas líneas de código en la consola JavaScript de su navegador, para familiarizarse con sus funcionalidades. </p> +</div> + +<p>El lenguaje JavaScript contiene muchas funciones integradas que te permiten realizar cosas muy utilies sin escribir el código tu mismo. De hecho, parte del código que llamas (una palabra elegante para decir correr o ejecutar) cuando invocas una función integrada puede no estar escrita en JavaScript —muchas de estas funciones están llamando partes del código del navegador de fondo, que está escrito principalmente en lenguajes de sistema de bajo nivel como C ++, no en lenguajes web como JavaScript.</p> + +<p>Bear in mind that some built-in browser functions are not part of the core JavaScript language — some are defined as part of browser APIs, which build on top of the default language to provide even more functionality (refer to <a href="/en-US/Learn/JavaScript/First_steps/What_is_JavaScript#So_what_can_it_really_do">this early section of our course</a> for more descriptions). We'll look at using browser APIs in more detail in a later module.</p> + +<h2 id="Functions_versus_methods">Functions versus methods</h2> + +<p>One thing we need to clear up before we move on — technically speaking, built in browser functions are not functions — they are <strong>methods</strong>. This sounds a bit scary and confusing, but don't worry — the words function and method are largely interchangeable, at least for our purposes, at this stage in your learning.</p> + +<p>The distinction is that methods are functions defined inside objects. Built-in browser functions (methods) and variables (which are called <strong>properties</strong>) are stored inside structured objects, to make the code more efficient and easier to handle.</p> + +<p>You don't need to learn about the inner workings of structured JavaScript objects yet — you can wait until our later module that will teach you all about the inner workings of objects, and how to create your own. For now, we just wanted to clear up any possible confusion of method versus function — you are likely to meet both terms as you look at the available related resources across the Web.</p> + +<h2 id="Custom_functions">Custom functions</h2> + +<p>You've also seen a lot of <strong>custom functions</strong> in the course so far — functions defined in your code, not inside the browser. Anytime you saw a custom name with parentheses straight after it, you were using a custom function. In our <a href="http://mdn.github.io/learning-area/javascript/building-blocks/loops/random-canvas-circles.html">random-canvas-circles.html</a> example (see also the full <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/random-canvas-circles.html">source code</a>) from our <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">loops article</a>, we included a custom <code>draw()</code> function that looked like this:</p> + +<pre class="brush: js notranslate">function draw() { + ctx.clearRect(0,0,WIDTH,HEIGHT); + for (var i = 0; i < 100; i++) { + ctx.beginPath(); + ctx.fillStyle = 'rgba(255,0,0,0.5)'; + ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); + ctx.fill(); + } +}</pre> + +<p>This function draws 100 random circles inside an {{htmlelement("canvas")}} element. Every time we want to do that, we can just invoke the function with this</p> + +<pre class="brush: js notranslate">draw();</pre> + +<p>rather than having to write all that code out again every time we want to repeat it. And functions can contain whatever code you like — you can even call other functions from inside functions. The above function for example calls the <code>random()</code> function three times, which is defined by the following code:</p> + +<pre class="brush: js notranslate">function random(number) { + return Math.floor(Math.random()*number); +}</pre> + +<p>We needed this function because the browser's built-in <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a> function only generates a random decimal number between 0 and 1. We wanted a random whole number between 0 and a specified number.</p> + +<h2 id="Invoking_functions">Invoking functions</h2> + +<p>You are probably clear on this by now, but just in case ... to actually use a function after it has been defined, you've got to run — or invoke — it. This is done by including the name of the function in the code somewhere, followed by parentheses.</p> + +<pre class="brush: js notranslate">function myFunction() { + alert('hello'); +} + +myFunction() +// calls the function once</pre> + +<h2 id="Anonymous_functions">Anonymous functions</h2> + +<p>You may see functions defined and invoked in slightly different ways. So far we have just created a function like so:</p> + +<pre class="brush: js notranslate">function myFunction() { + alert('hello'); +}</pre> + +<p>But you can also create a function that doesn't have a name:</p> + +<pre class="brush: js notranslate">function() { + alert('hello'); +}</pre> + +<p>This is called an <strong>anonymous function</strong> — it has no name! It also won't do anything on its own. You generally use an anonymous function along with an event handler, for example the following would run the code inside the function whenever the associated button is clicked:</p> + +<pre class="brush: js notranslate">var myButton = document.querySelector('button'); + +myButton.onclick = function() { + alert('hello'); +}</pre> + +<p>The above example would require there to be a {{htmlelement("button")}} element available on the page to select and click. You've already seen this structure a few times throughout the course, and you'll learn more about and see it in use in the next article.</p> + +<p>You can also assign an anonymous function to be the value of a variable, for example:</p> + +<pre class="brush: js notranslate">var myGreeting = function() { + alert('hello'); +}</pre> + +<p>This function could now be invoked using:</p> + +<pre class="brush: js notranslate">myGreeting();</pre> + +<p>This effectively gives the function a name; you can also assign the function to be the value of multiple variables, for example:</p> + +<pre class="brush: js notranslate">var anotherGreeting = function() { + alert('hello'); +}</pre> + +<p>This function could now be invoked using either of</p> + +<pre class="brush: js notranslate">myGreeting(); +anotherGreeting();</pre> + +<p>But this would just be confusing, so don't do it! When creating functions, it is better to just stick to this form:</p> + +<pre class="brush: js notranslate">function myGreeting() { + alert('hello'); +}</pre> + +<p>You will mainly use anonymous functions to just run a load of code in response to an event firing — like a button being clicked — using an event handler. Again, this looks something like this:</p> + +<pre class="brush: js notranslate">myButton.onclick = function() { + alert('hello'); + // I can put as much code + // inside here as I want +}</pre> + +<h2 id="Function_parameters">Function parameters</h2> + +<p>Some functions require <strong>parameters</strong> to be specified when you are invoking them — these are values that need to be included inside the function parentheses, which it needs to do its job properly.</p> + +<div class="note"> +<p><strong>Note</strong>: Parameters are sometimes called arguments, properties, or even attributes.</p> +</div> + +<p>As an example, the browser's built-in <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a> function doesn't require any parameters. When called, it always returns a random number between 0 and 1:</p> + +<pre class="brush: js notranslate">var myNumber = Math.random();</pre> + +<p>The browser's built-in string <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a> function however needs two parameters — the substring to find in the main string, and the substring to replace that string with:</p> + +<pre class="brush: js notranslate">var myText = 'I am a string'; +var newString = myText.replace('string', 'sausage');</pre> + +<div class="note"> +<p><strong>Note</strong>: When you need to specify multiple parameters, they are separated by commas.</p> +</div> + +<p>It should also be noted that sometimes parameters are optional — you don't have to specify them. If you don't, the function will generally adopt some kind of default behavior. As an example, the array <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/join">join()</a> function's parameter is optional:</p> + +<pre class="brush: js notranslate">var myArray = ['I', 'love', 'chocolate', 'frogs']; +var madeAString = myArray.join(' '); +// returns 'I love chocolate frogs' +var madeAString = myArray.join(); +// returns 'I,love,chocolate,frogs'</pre> + +<p>If no parameter is included to specify a joining/delimiting character, a comma is used by default.</p> + +<h2 id="Function_scope_and_conflicts">Function scope and conflicts</h2> + +<p>Let's talk a bit about {{glossary("scope")}} — a very important concept when dealing with functions. When you create a function, the variables and other things defined inside the function are inside their own separate <strong>scope</strong>, meaning that they are locked away in their own separate compartments, unreachable from inside other functions or from code outside the functions.</p> + +<p>The top level outside all your functions is called the <strong>global scope</strong>. Values defined in the global scope are accessible from everywhere in the code.</p> + +<p>JavaScript is set up like this for various reasons — but mainly because of security and organization. Sometimes you don't want variables to be accessible from everywhere in the code — external scripts that you call in from elsewhere could start to mess with your code and cause problems because they happen to be using the same variable names as other parts of the code, causing conflicts. This might be done maliciously, or just by accident.</p> + +<p>For example, say you have an HTML file that is calling in two external JavaScript files, and both of them have a variable and a function defined that use the same name:</p> + +<pre class="brush: html notranslate"><!-- Excerpt from my HTML --> +<script src="first.js"></script> +<script src="second.js"></script> +<script> + greeting(); +</script></pre> + +<pre class="brush: js notranslate">// first.js +var name = 'Chris'; +function greeting() { + alert('Hello ' + name + ': welcome to our company.'); +}</pre> + +<pre class="brush: js notranslate">// second.js +var name = 'Zaptec'; +function greeting() { + alert('Our company is called ' + name + '.'); +}</pre> + +<p>Both functions you want to call are called <code>greeting()</code>, but you can only ever access the <code>second.js</code> file's <code>greeting()</code> function — it is applied to the HTML later on in the source code, so its variable and function overwrite the ones in <code>first.js</code>.</p> + +<div class="note"> +<p><strong>Note</strong>: You can see this example <a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/conflict.html">running live on GitHub</a> (see also the <a href="https://github.com/mdn/learning-area/tree/master/javascript/building-blocks/functions">source code</a>).</p> +</div> + +<p>Keeping parts of your code locked away in functions avoids such problems, and is considered best practice.</p> + +<p>It is a bit like a zoo. The lions, zebras, tigers, and penguins are kept in their own enclosures, and only have access to the things inside their enclosures — in the same manner as the function scopes. If they were able to get into other enclosures, problems would occur. At best, different animals would feel really uncomfortable inside unfamiliar habitats — a lion or tiger would feel terrible inside the penguins' watery, icy domain. At worst, the lions and tigers might try to eat the penguins!</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14079/MDN-mozilla-zoo.png" style="display: block; margin: 0 auto;"></p> + +<p>The zoo keeper is like the global scope — he or she has the keys to access every enclosure, to restock food, tend to sick animals, etc.</p> + +<h3 id="Active_learning_Playing_with_scope">Active learning: Playing with scope</h3> + +<p>Let's look at a real example to demonstrate scoping.</p> + +<ol> + <li>First, make a local copy of our <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-scope.html">function-scope.html</a> example. This contains two functions called <code>a()</code> and <code>b()</code>, and three variables — <code>x</code>, <code>y</code>, and <code>z</code> — two of which are defined inside the functions, and one in the global scope. It also contains a third function called <code>output()</code>, which takes a single parameter and outputs it in a paragraph on the page.</li> + <li>Open the example up in a browser and in your text editor.</li> + <li>Open the JavaScript console in your browser developer tools. In the JavaScript console, enter the following command: + <pre class="brush: js notranslate">output(x);</pre> + You should see the value of variable <code>x</code> output to the screen.</li> + <li>Now try entering the following in your console + <pre class="brush: js notranslate">output(y); +output(z);</pre> + Both of these should return an error along the lines of "<a href="/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: y is not defined</a>". Why is that? Because of function scope — <code>y</code> and <code>z</code> are locked inside the <code>a()</code> and <code>b()</code> functions, so <code>output()</code> can't access them when called from the global scope.</li> + <li>However, what about when it's called from inside another function? Try editing <code>a()</code> and <code>b()</code> so they look like this: + <pre class="brush: js notranslate">function a() { + var y = 2; + output(y); +} + +function b() { + var z = 3; + output(z); +}</pre> + Save the code and reload it in your browser, then try calling the <code>a()</code> and <code>b()</code> functions from the JavaScript console: + + <pre class="brush: js notranslate">a(); +b();</pre> + You should see the <code>y</code> and <code>z</code> values output in the page. This works fine, as the <code>output()</code> function is being called inside the other functions — in the same scope as the variables it is printing are defined in, in each case. <code>output()</code> itself is available from anywhere, as it is defined in the global scope.</li> + <li>Now try updating your code like this: + <pre class="brush: js notranslate">function a() { + var y = 2; + output(x); +} + +function b() { + var z = 3; + output(x); +}</pre> + Save and reload again, and try this again in your JavaScript console: + + <pre class="brush: js notranslate">a(); +b();</pre> + Both the <code>a()</code> and <code>b()</code> call should output the value of x — 1. These work fine because even though the <code>output()</code> calls are not in the same scope as <code>x</code> is defined in, <code>x</code> is a global variable so is available inside all code, everywhere.</li> + <li>Finally, try updating your code like this: + <pre class="brush: js notranslate">function a() { + var y = 2; + output(z); +} + +function b() { + var z = 3; + output(y); +}</pre> + Save and reload again, and try this again in your JavaScript console: + + <pre class="brush: js notranslate">a(); +b();</pre> + This time the <code>a()</code> and <code>b()</code> calls will both return that annoying "<a href="/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: z is not defined</a>" error — this is because the <code>output()</code> calls and the variables they are trying to print are not defined inside the same function scopes — the variables are effectively invisible to those function calls.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: The same scoping rules do not apply to loop (e.g. <code>for() { ... }</code>) and conditional blocks (e.g. <code>if() { ... }</code>) — they look very similar, but they are not the same thing! Take care not to get these confused.</p> +</div> + +<div class="note"> +<p><strong>Note</strong>: The <a href="/en-US/docs/Web/JavaScript/Reference/Errors/Not_defined">ReferenceError: "x" is not defined</a> error is one of the most common you'll encounter. If you get this error and you are sure that you have defined the variable in question, check what scope it is in.</p> +</div> + +<ul> +</ul> + +<h3 id="Functions_inside_functions">Functions inside functions</h3> + +<p>Keep in mind that you can call a function from anywhere, even inside another function. This is often used as a way to keep code tidy — if you have a big complex function, it is easier to understand if you break it down into several sub-functions:</p> + +<pre class="brush: js notranslate">function myBigFunction() { + var myValue; + + subFunction1(); + subFunction2(); + subFunction3(); +} + +function subFunction1() { + console.log(myValue); +} + +function subFunction2() { + console.log(myValue); +} + +function subFunction3() { + console.log(myValue); +} +</pre> + +<p>Just make sure that the values being used inside the function are properly in scope. The example above would throw an error <code>ReferenceError: myValue is not defined</code>, because although the <code>myValue</code> variable is defined in the same scope as the function calls, it is not defined inside the function definitions — the actual code that is run when the functions are called. To make this work, you'd have to pass the value into the function as a parameter, like this:</p> + +<pre class="brush: js notranslate">function myBigFunction() { + var myValue = 1; + + subFunction1(myValue); + subFunction2(myValue); + subFunction3(myValue); +} + +function subFunction1(value) { + console.log(value); +} + +function subFunction2(value) { + console.log(value); +} + +function subFunction3(value) { + console.log(value); +}</pre> + +<h2 id="Conclusion">Conclusion</h2> + +<p>This article has explored the fundamental concepts behind functions, paving the way for the next one in which we get practical and take you through the steps to building up your own custom function.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Functions">Functions detailed guide</a> — covers some advanced features not included here.</li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Functions">Functions reference</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Functions/Default_parameters">Default parameters</a>, <a href="/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions">Arrow functions</a> — advanced concept references</li> +</ul> + +<ul> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Looping_code","Learn/JavaScript/Building_blocks/Build_your_own_function", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> +<gdiv></gdiv> diff --git a/files/es/learn/javascript/building_blocks/galeria_de_imagenes/index.html b/files/es/learn/javascript/building_blocks/galeria_de_imagenes/index.html new file mode 100644 index 0000000000..205f1a11aa --- /dev/null +++ b/files/es/learn/javascript/building_blocks/galeria_de_imagenes/index.html @@ -0,0 +1,144 @@ +--- +title: Galería de imágenes +slug: Learn/JavaScript/Building_blocks/Galeria_de_imagenes +translation_of: Learn/JavaScript/Building_blocks/Image_gallery +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary"><span class="tlid-translation translation" lang="es"><span title="">Ahora que hemos analizado los bloques de construcción fundamentales de JavaScript, pongamos a prueba tu conocimiento de bucles, funciones, condicionales y eventos, creando un elemento que comumente vemos en muchos sitios web, una </span> <span title="">Galería de imágenes "motorizada" por JavaScript .</span></span></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Antes de intentar esta evaluación deberías de haber trabajado con todos los artículos en éste módulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Evaluar la comprensión de los bucles, funciones, condicionales y eventos de JavaScript..</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Para realizar esta evaluación, debería descárgarse <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/gallery/gallery-start.zip?raw=true">archivoZip</a> para el ejemplo, descomprímalo en algún lugar de su computadora y haga el ejercicio localmente para empezar.</p> + +<p>Opcionalmente, puedes usar un sitio como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> o <a href="https://glitch.com/">Glitch</a> para realizar tu evaluación. Puede pegar el HTML, CSS y JavaScript dentro de uno de estos editores online. <span class="tlid-translation translation" lang="es"><span title="">Si el editor en línea que está utilizando no tiene paneles JavaScript / CSS separados, siéntase libre de ponerlos en línea <script> / <style> elementos dentro de la página HTML.</span></span></p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Si se atascascas con algo, entonces pregúntenos para ayudarlo — vea la sección de {{anch("evaluación o ayuda adicional")}} al final de esta página.</p> +</div> + +<h2 id="Resumen_del_proyecto">Resumen del proyecto</h2> + +<p>Ha sido provisto con algún contenido de HTML, CSS e imágenes, también algunas líneas de código en JavaScript; necesitas escribir las líneas de código en JavaScript necesatio para transformarse en un programa funcional. El HTML body luce así:</p> + +<pre class="brush: html"><h1>Image gallery example</h1> + +<div class="full-img"> + <img class="displayed-img" src="images/pic1.jpg"> + <div class="overlay"></div> + <button class="dark">Darken</button> +</div> + +<div class="thumb-bar"> + +</div></pre> + +<p>El ejemplo se ve así:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13787/gallery.png" style="display: block; margin: 0 auto;"></p> + +<ul> +</ul> + +<p>Las partes más interesantes del archivo example's CSS :</p> + +<ul> + <li>It absolutely positions the three elements inside the <code>full-img <div></code> — the <code><img></code> in which the full-sized image is displayed, an empty <code><div></code> that is sized to be the same size as the <code><img></code> and put right over the top of it (this is used to apply a darkening effect to the image via a semi-transparent background color), and a <code><button></code> that is used to control the darkening effect.</li> + <li>It sets the width of any images inside the <code>thumb-bar <div></code> (so-called "thumbnail" images) to 20%, and floats them to the left so they sit next to one another on a line.</li> +</ul> + +<p>Your JavaScript needs to:</p> + +<ul> + <li>Loop through all the images, and for each one insert an <code><img></code> element inside the <code>thumb-bar <div></code> that embeds that image in the page.</li> + <li>Attach an <code>onclick</code> handler to each <code><img></code> inside the <code>thumb-bar <div></code> so that when they are clicked, the corresponding image is displayed in the <code>displayed-img <img></code> element.</li> + <li>Attach an <code>onclick</code> handler to the <code><button></code> so that when it is clicked, a darken effect is applied to the full-size image. When it is clicked again, the darken effect is removed again.</li> +</ul> + +<p>To give you more of an idea, have a look at the <a href="http://mdn.github.io/learning-area/javascript/building-blocks/gallery/">finished example</a> (no peeking at the source code!)</p> + +<h2 id="Steps_to_complete">Steps to complete</h2> + +<p>The following sections describe what you need to do.</p> + +<h3 id="Looping_through_the_images">Looping through the images</h3> + +<p>We've already provided you with lines that store a reference to the <code>thumb-bar <div></code> inside a constant called <code>thumbBar</code>, create a new <code><img></code> element, set its <code>src</code> attribute to a placeholder value <code>xxx</code>, and append this new <code><img></code> element inside <code>thumbBar</code>.</p> + +<p>You need to:</p> + +<ol> + <li>Put the section of code below the "Looping through images" comment inside a loop that loops through all 5 images — you just need to loop through five numbers, one representing each image.</li> + <li>In each loop iteration, replace the <code>xxx</code> placeholder value with a string that will equal the path to the image in each case. We are setting the value of the <code>src</code> attribute to this value in each case. Bear in mind that in each case, the image is inside the images directory and its name is <code>pic1.jpg</code>, <code>pic2.jpg</code>, etc.</li> +</ol> + +<h3 id="Adding_an_onclick_handler_to_each_thumbnail_image">Adding an onclick handler to each thumbnail image</h3> + +<p>In each loop iteration, you need to add an <code>onclick</code> handler to the current <code>newImage</code> — this handler should find the value of the <code>src</code> attribute of the current image. Set the <code>src</code> attribute value of the <code>displayed-img <img></code> to the <code>src</code> value passed in as a parameter.</p> + +<h3 id="Writing_a_handler_that_runs_the_darkenlighten_button">Writing a handler that runs the darken/lighten button</h3> + +<p>That just leaves our darken/lighten <code><button></code> — we've already provided a line that stores a reference to the <code><button></code> in a constant called <code>btn</code>. You need to add an <code>onclick</code> handler that:</p> + +<ol> + <li>Checks the current class name set on the <code><button></code> — you can again achieve this by using <code>getAttribute()</code>.</li> + <li>If the class name is <code>"dark"</code>, changes the <code><button></code> class to <code>"light"</code> (using <code><a href="/en-US/docs/Web/API/Element/setAttribute">setAttribute()</a></code>), its text content to "Lighten", and the {{cssxref("background-color")}} of the overlay <code><div></code> to <code>"rgba(0,0,0,0.5)"</code>.</li> + <li>If the class name not <code>"dark"</code>, changes the <code><button></code> class to <code>"dark"</code>, its text content back to "Darken", and the {{cssxref("background-color")}} of the overlay <code><div></code> to <code>"rgba(0,0,0,0)"</code>.</li> +</ol> + +<p>The following lines provide a basis for achieving the changes stipulated in points 2 and 3 above.</p> + +<pre class="brush: js">btn.setAttribute('class', xxx); +btn.textContent = xxx; +overlay.style.backgroundColor = xxx;</pre> + +<h2 id="Hints_and_tips">Hints and tips</h2> + +<ul> + <li>You don't need to edit the HTML or CSS in any way.</li> +</ul> + +<h2 id="Assessment_or_further_help">Assessment or further help</h2> + +<p>If you would like your work assessed, or are stuck and want to ask for help:</p> + +<ol> + <li>Put your work into an online shareable editor such as <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, or <a href="https://glitch.com/">Glitch</a>.</li> + <li>Write a post asking for assessment and/or help at the <a href="https://discourse.mozilla.org/c/mdn/learn">MDN Discourse forum Learning category</a>. Your post should include: + <ul> + <li>A descriptive title such as "Assessment wanted for Image gallery".</li> + <li>Details of what you have already tried, and what you would like us to do, e.g. if you are stuck and need help, or want an assessment.</li> + <li>A link to the example you want assessed or need help with, in an online shareable editor (as mentioned in step 1 above). This is a good practice to get into — it's very hard to help someone with a coding problem if you can't see their code.</li> + <li>A link to the actual task or assessment page, so we can find the question you want help with.</li> + </ul> + </li> +</ol> + +<p>{{PreviousMenu("Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> diff --git a/files/es/learn/javascript/building_blocks/index.html b/files/es/learn/javascript/building_blocks/index.html new file mode 100644 index 0000000000..de9e7c7c4a --- /dev/null +++ b/files/es/learn/javascript/building_blocks/index.html @@ -0,0 +1,71 @@ +--- +title: Elementos básicos de JavaScript +slug: Learn/JavaScript/Building_blocks +tags: + - CodingScripting + - Condicionales + - Evaluación + - Funciones + - Guía + - JavaScript + - Landing + - NeedsTranslation + - Principiante + - TopicStub + - bucles + - eventos + - introducción + - 'l10n:priority' + - modulo +translation_of: Learn/JavaScript/Building_blocks +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">En este módulo, continuamos nuestra cobertura de todas las características clave de JavaScript, tornando nuestra atención a tipos de código comúnmente encontrados tales como enunciados condicionales, bucles (loops), funciones, y eventos. Ya has visto estas cosas en este curso, pero solo de pasada aquí lo hablaremos mas explícitamente.</p> + +<h3 id="Quieres_transformarte_en_un_desarrollador_web_front-end">Quieres transformarte en un desarrollador web front-end?</h3> + +<p>Hemos reunido un curso que incluye toda la información esencial que necesitas para trabajar hacia tu objetivo.</p> + +<p><a class="cta primary" href="https://developer.mozilla.org/docs/Learn/Front-end_web_developer">Empieza aquí</a></p> + +<h2 id="Pre-requisitos">Pre-requisitos</h2> + +<p>Antes de empezar este módulo, deberías ya tener alguna familiaridad con lo básico de <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML">HTML</a> y <a href="/en-US/docs/Learn/CSS/Introduction_to_CSS">CSS</a>, y también deberías haber trabajado todos lo módulos previos, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript primeros pasos</a>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si estas trabajando en una computadora/tablet/otro dispositivo donde no tienes la capacidad de crear tus propios archivos, podrías practicar (la mayoría de) los ejemplos de código en un programa en linea tales como <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="/es/docs/Learn/JavaScript/Building_blocks/conditionals"> Tomando decisiones en tu código — condicionales</a></dt> + <dd>En cualquier lenguaje de programación, el código necesita tomar decisiones y efectuar acciones consiguientemente dependiendo de las diferentes ordenes ingresadas. Por ejemplo, en un juego, si el numero de vidas del jugador es 0, entonces se termina el juego. En una aplicación del clima, si esta siendo vista por la mañana, muestra un gráfico del amanecer; muestra estrellas y una luna si es de noche. En este artículo exploraremos como los condicionales estructuran el trabajo en Javascript.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Building_blocks/Bucle_codigo">Bucles de código</a></dt> + <dd>A veces necesitas que una tarea se haga más de una vez. Por ejemplo, revisar toda una lista de nombres. En programación, los bucles ('<em>loops'</em> en inglés) hacen este trabajo muy bien. Aca veremos la estructura de loops en Javascript.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Building_blocks/Functions">Funciones — bloques de código reusables </a></dt> + <dd>Otro concepto fundamental en código es <strong>funciones. Funciones</strong> te permite almacenar una pieza de código que ejecuta una sola tarea dentro de un bloque definido, y después llamar ese código cuando lo necesitas usando un comando corto en lugar de tener que escribir el mismo código varias veces. En este articulo exploraremos conceptos fundamentales detrás de las funciones tales como sintaxis básica, cómo invocar y definir funciones, ámbito o alcance (scope), y parámetros.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Building_blocks/Construyendo_tu_propia_funcion">Crea tu propia función </a></dt> + <dd>Con la información presentada en el artículo anterior, este artículo, pretende demostrar una parte práctica. Se podrá desarrollar una función propia, y durante el desarrollo se presentarán algunos consejos prácticos y útiles para trabajar con funciones.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Building_blocks/Return_values"> Una función devuelve valores</a></dt> + <dd>Un concepto fundamental que ha de tenerse en cuenta, es que las funciones pueden devolver valores al finalizar su ejecución, aunque algunas funciones también pueden no devolver ningún valor. Es importante entender como son esos valores, qué tipos pueden tener y cómo aprovechar el valor devuelto por la función en el programa.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Building_blocks/Eventos">Introducción a eventos</a></dt> + <dd>Los eventos son acciones u ocurrencias que aparecen durante la ejecución del programa, y que son reportadas por el sistema, de forma que se pueda responder a los eventos de la forma deseada. Por ejemplo, si un usuario hace un click en un botón de una página web, puede que se quiera que ese evento inicie una acción en el que se muestre cierta información en un cuadro de información. En este último artículo se presentarán y describirán los conceptos necesarios con respecto a los eventos, y como funcionan en un navegador.</dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<p>La siguiente evaluación probara tu entendimiento de lo básico de Javascript cubierto en las guias anteriores.</p> + +<dl> + <dt><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Galeria de imagen</a></dt> + <dd>Ahora que hemos visto los bloques constructores fundamentales de JavaScript, probaremos tus conocimientos en bucles, funciones, condicionales y eventos construyendo un item bastante común en muchos sitios web — una galería de imágenes creada con JavaScript. </dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<dl> + <dt><a href="https://learnjavascript.online/">Aprender JavaScript</a></dt> + <dd>Un excelente recurso para aspirantes a desarrolladores web — Aprenda JavaScript en un entorno interactivo, con lecciones cortas y pruebas interactivas, guiadas por una evaluación automatizada. Las primeras 40 lecciones son gratuitas, y el curso completo está disponible por un pequeño pago único.</dd> +</dl> diff --git a/files/es/learn/javascript/building_blocks/return_values/index.html b/files/es/learn/javascript/building_blocks/return_values/index.html new file mode 100644 index 0000000000..2602a7217f --- /dev/null +++ b/files/es/learn/javascript/building_blocks/return_values/index.html @@ -0,0 +1,168 @@ +--- +title: Una función retorna valores +slug: Learn/JavaScript/Building_blocks/Return_values +translation_of: Learn/JavaScript/Building_blocks/Return_values +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</div> + +<p class="summary">Hay un último concepto esencial para que discutamos en este curso, para cerrar nuestra visión de las funciones: — lo valores que se devuelven. Algunas funciones no devuelven un valor significativo después de su finalización, pero otras sí, y es importante comprender cuáles son sus valores, cómo utilizarlos en su código y cómo hacer que sus propias funciones personalizadas devuelvan valores útiles. Cubriremos todos estos a continuación.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td> + <p>Basic computer literacy, a basic understanding of HTML and CSS, <a href="/en-US/docs/Learn/JavaScript/First_steps">JavaScript first steps</a>, <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a>.</p> + </td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>To understand function return values, and how to make use of them.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_son_los_valores_de_retorno">¿Qué son los valores de retorno?</h2> + +<p><strong>Los valores de retorno </strong>son exactamente como suenan: los valores devueltos por la función cuando se completa. Ya has alcanzado los valores de retorno varias veces, aunque es posible que no hayas pensado en ellos explícitamente. Volvamos a un código familiar:</p> + +<pre class="brush: js notranslate">var myText = 'I am a string'; +var newString = myText.replace('string', 'sausage'); +console.log(newString); +// la función de cadena replace () toma una cadena, +// sustituyendo una subcadena con otra y devoviendo +// una cadena nueva con la sustitución realizada</pre> + +<p>Vimos exactamente este bloque de código en nuestro primer artículo de función. Estamos invocando la función <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace ()</a> en la cadena <code>myText</code>, y le pasamos dos parámetros: la subcadena a encontrar y la subcadena con la que reemplazarla. Cuando esta función se completa (termina de ejecutarse), devuelve un valor, que es una nueva cadena con el reemplazo realizado. En el código anterior, estamos guardando este valor de retorno como el valor de la variable <code>newString</code>.</p> + +<p>Si observa la página de referencia MDN de la función de reemplazo, verá una sección llamada <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace#Return_value">Valor de retorno.</a> Es muy útil conocer y comprender qué valores devuelven las funciones, por lo que tratamos de incluir esta información siempre que sea posible.</p> + +<p>Algunas funciones no devuelven un valor de retorno como tal (en nuestras páginas de referencia, el valor de retorno aparece como <code>void</code> o <code>undefined</code> en tales casos). Por ejemplo, en la función <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-stage-4.html#L50">displayMessage ()</a> que creamos en el artículo anterior, no se devuelve ningún valor específico como resultado de la función que se invoca. Simplemente hace que aparezca un cuadro en algún lugar de la pantalla, ¡eso es todo!</p> + +<p>Generalmente, se usa un valor de retorno donde la función es un paso intermedio en un cálculo de algún tipo. Quieres llegar a un resultado final, que involucra algunos valores. Esos valores deben ser calculados por una función, que luego devuelve los resultados para que puedan usarse en la siguiente etapa del cálculo.</p> + +<h3 id="Using_return_values_in_your_own_functions">Using return values in your own functions</h3> + +<p>To return a value from a custom function, you need to use ... wait for it ... the <a href="/en-US/docs/Web/JavaScript/Reference/Statements/return">return</a> keyword. We saw this in action recently in our <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/loops/random-canvas-circles.html">random-canvas-circles.html</a> example. Our <code>draw()</code> function draws 100 random circles somewhere on an HTML {{htmlelement("canvas")}}:</p> + +<pre class="brush: js notranslate">function draw() { + ctx.clearRect(0,0,WIDTH,HEIGHT); + for (var i = 0; i < 100; i++) { + ctx.beginPath(); + ctx.fillStyle = 'rgba(255,0,0,0.5)'; + ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI); + ctx.fill(); + } +}</pre> + +<p>Inside each loop iteration, three calls are made to the <code>random()</code> function, to generate a random value for the current circle's x coordinate, y coordinate, and radius, respectively. The <code>random()</code> function takes one parameter — a whole number — and it returns a whole random number between 0 and that number. It looks like this:</p> + +<pre class="brush: js notranslate">function randomNumber(number) { + return Math.floor(Math.random()*number); +}</pre> + +<p>This could be written as follows:</p> + +<pre class="brush: js notranslate">function randomNumber(number) { + var result = Math.floor(Math.random()*number); + return result; +}</pre> + +<p>But the first version is quicker to write, and more compact.</p> + +<p>We are returning the result of the calculation <code>Math.floor(Math.random()*number)</code> each time the function is called. This return value appears at the point the function was called, and the code continues. So for example, if we ran the following line:</p> + +<pre class="brush: js notranslate">ctx.arc(random(WIDTH), random(HEIGHT), random(50), 0, 2 * Math.PI);</pre> + +<p>and the three <code>random()</code> calls returned the values 500, 200, and 35, respectively, the line would actually be run as if it were this:</p> + +<pre class="brush: js notranslate">ctx.arc(500, 200, 35, 0, 2 * Math.PI);</pre> + +<p>The function calls on the line are run first and their return values substituted for the function calls, before the line itself is then executed.</p> + +<h2 id="Active_learning_our_own_return_value_function">Active learning: our own return value function</h2> + +<p>Let's have a go at writing our own functions featuring return values.</p> + +<ol> + <li>First of all, make a local copy of the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-library.html">function-library.html</a> file from GitHub. This is a simple HTML page containing a text {{htmlelement("input")}} field and a paragraph. There's also a {{htmlelement("script")}} element in which we have stored a reference to both HTML elements in two variables. This little page will allow you to enter a number into the text box, and display different numbers related to it in the paragraph below.</li> + <li>Let's add some useful functions to this <code><script></code> element. Below the existing two lines of JavaScript, add the following function definitions: + <pre class="brush: js notranslate">function squared(num) { + return num * num; +} + +function cubed(num) { + return num * num * num; +} + +function factorial(num) { + var x = num; + while (x > 1) { + num *= x-1; + x--; + } + return num; +}</pre> + The <code>squared()</code> and <code>cubed()</code> functions are fairly obvious — they return the square or cube of the number given as a parameter. The <code>factorial()</code> function returns the <a href="https://en.wikipedia.org/wiki/Factorial">factorial</a> of the given number.</li> + <li>Next, we're going to include a way to print out information about the number entered into the text input. Enter the following event handler below the existing functions: + <pre class="brush: js notranslate">input.onchange = function() { + var num = input.value; + if (isNaN(num)) { + para.textContent = 'You need to enter a number!'; + } else { + para.textContent = num + ' squared is ' + squared(num) + '. ' + + num + ' cubed is ' + cubed(num) + '. ' + + num + ' factorial is ' + factorial(num) + '.'; + } +}</pre> + + <p>Here we are creating an <code>onchange</code> event handler that runs whenever the change event fires on the text input — that is, when a new value is entered into the text input, and submitted (enter a value then press tab for example). When this anonymous function runs, the existing value entered into the input is stored in the <code>num</code> variable.</p> + + <p>Next, we do a conditional test — if the entered value is not a number, we print an error message into the paragraph. The test looks at whether the expression <code>isNaN(num)</code> returns true. We use the <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/isNaN">isNaN()</a> function to test whether the num value is not a number — if so, it returns <code>true</code>, and if not, <code>false</code>.</p> + + <p>If the test returns <code>false</code>, the <code>num</code> value is a number, so we print out a sentence inside the paragraph element stating what the square, cube, and factorial of the number are. The sentence calls the <code>squared()</code>, <code>cubed()</code>, and <code>factorial()</code> functions to get the required values.</p> + </li> + <li>Save your code, load it in a browser, and try it out.</li> +</ol> + +<div class="note"> +<p><strong>Note</strong>: If you have trouble getting the example to work, feel free to check your code against the <a href="https://github.com/mdn/learning-area/blob/master/javascript/building-blocks/functions/function-library-finished.html">finished version on GitHub</a> (<a href="http://mdn.github.io/learning-area/javascript/building-blocks/functions/function-library-finished.html">see it running live</a> also), or ask us for help.</p> +</div> + +<p>At this point, we'd like you to have a go at writing out a couple of functions of your own and adding them to the library. How about the square or cube root of the number, or the circumference of a circle with a radius of length <code>num</code>?</p> + +<p>This exercise has brought up a couple of important points besides being a study on how to use the <code>return</code> statement. In addition, we have:</p> + +<ul> + <li>Looked at another example of writing error handling into our functions. It is generally a good idea to check that any necessary parameters have been provided, and in the right datatype, and if they are optional, that some kind of default value is provided to allow for that. This way, your program will be less likely to throw errors.</li> + <li>Thought about the idea of creating a function library. As you go further into your programming career, you'll start to do the same kinds of things over and over again. It is a good idea to start keeping your own library of utility functions that you use very often — you can then copy them over to your new code, or even just apply it to any HTML pages where you need it.</li> +</ul> + +<h2 id="Conclusion">Conclusion</h2> + +<p>So there we have it — functions are fun, very useful and, although there's a lot to talk about in regards to their syntax and functionality, fairly understandable given the right articles to study.</p> + +<p>If there is anything you didn't understand, feel free to read through the article again, or <a href="/en-US/Learn#Contact_us">contact us</a> to ask for help.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions">Functions in-depth</a> — a detailed guide covering more advanced functions-related information.</li> + <li><a href="https://www.impressivewebs.com/callback-functions-javascript/">Callback functions in JavaScript</a> — a common JavaScript pattern is to pass a function into another function as an argument, which is then called inside the first function. This is a little beyond the scope of this course, but worth studying before too long.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Building_blocks/Build_your_own_function","Learn/JavaScript/Building_blocks/Events", "Learn/JavaScript/Building_blocks")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">Making decisions in your code — conditionals</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">Looping code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">Functions — reusable blocks of code</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">Build your own function</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">Function return values</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introduction to events</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Image_gallery">Image gallery</a></li> +</ul> diff --git a/files/es/learn/javascript/client-side_web_apis/client-side_storage/index.html b/files/es/learn/javascript/client-side_web_apis/client-side_storage/index.html new file mode 100644 index 0000000000..0c03392e7d --- /dev/null +++ b/files/es/learn/javascript/client-side_web_apis/client-side_storage/index.html @@ -0,0 +1,788 @@ +--- +title: Almacenamiento del lado cliente +slug: Learn/JavaScript/Client-side_web_APIs/Client-side_storage +tags: + - API + - Almacenaje + - Article + - CodingScripting + - Guía + - IndexedDB + - JavaScript + - Principiante + - aprende +translation_of: Learn/JavaScript/Client-side_web_APIs/Client-side_storage +--- +<p>{{LearnSidebar}}</p> + +<div>{{PreviousMenu("Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div> + +<p class="summary">Los navegadores web modernos admiten varias formas para que los sitios web almacenen datos en la computadora del usuario, con el permiso del usuario, y luego los recuperen cuando sea necesario. Esto te permite conservar los datos para el almacenamiento a largo plazo, guardar sitios o documentos para su uso sin conexión, conservar la configuración específica del usuario para tu sitio y más. Este artículo explica los conceptos básicos de cómo funcionan.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conceptos básicos de JavaScript (consulta {{web.link("/es/docs/Learn/JavaScript/First_steps", "primeros pasos")}}, {{web.link("/es/docs/Learn/JavaScript/Building_blocks", "bloques de construcción")}}, {{web.link("/es/docs/Learn/JavaScript/Objects", "objetos JavaScript")}}), los {{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Introducción", "conceptos básicos de las APIs de lado del cliente")}}</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender a utilizar las APIs de almacenamiento de lado del cliente para almacenar datos de aplicaciones.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Almacenamiento_de_lado_del_cliente">¿Almacenamiento de lado del cliente?</h2> + +<p>En otra parte del área de aprendizaje de MDN, hablamos sobre la diferencia entre {{web.link("/es/docs/Learn/Server-side/First_steps/Client-Server_overview#Sitios_estaticos", "sitios estáticos")}} y {{web.link("/es/docs/Learn/Server-side/First_steps/Client-Server_overview#Sitios_dinamicos", "sitios dinámicos")}}. La mayoría de los principales sitios web modernos son dinámicos: almacenan datos en el servidor utilizando algún tipo de base de datos (almacenamiento de lado del servidor) y luego ejecutan {{web.link("/es/docs/Learn/Server-side", "de lado del servidor")}} para recuperar los datos necesarios, insertarlos en plantillas de páginas estáticas y entregar el HTML resultante al cliente para que lo muestre el navegador del usuario.</p> + +<p>El almacenamiento de lado del cliente funciona con principios similares, pero tiene diferentes usos. Consiste en una API de JavaScript que te permiten almacenar datos en el cliente (es decir, en la máquina del usuario) y luego recuperarlos cuando sea necesario. Esto tiene muchos usos distintos, como:</p> + +<ul> + <li>Personalizar las preferencias del sitio (por ejemplo, mostrar la elección de un usuario de artilugios personalizados, combinación de colores o tamaño del tipo de letra).</li> + <li>Persistencia de la actividad anterior del sitio (por ejemplo, almacenar el contenido de un carrito de compras de una sesión anterior, recordar si un usuario inició sesión anteriormente).</li> + <li>Guardar datos y activos localmente para que un sitio sea más rápido (y potencialmente menos costoso) de descargar o se pueda usar sin una conexión de red.</li> + <li>Guardar documentos generados por aplicaciones web localmente para usarlos sin conexión</li> +</ul> + +<p>A menudo, el almacenamiento de lado del cliente y de lado del servidor se utilizan juntos. Por ejemplo, puedes descargar un lote de archivos de música (quizás utilizados por un juego web o una aplicación de reproducción de música), almacenarlos dentro de una base de datos de lado del cliente y reproducirlos según sea necesario. El usuario solo tendría que descargar los archivos de música una vez; en las visitas posteriores, se recuperarían de la base de datos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Existen límites en la cantidad de datos que puedes almacenar utilizando las APIs de almacenamiento de lado del cliente (posiblemente tanto por API individual como acumulativamente); el límite exacto varía según el navegador y posiblemente según la configuración del usuario. Consulta {{web.link("/es/docs/Web/API/IndexedDB_API/Browser_storage_limits_and_eviction_criteria", "límites de almacenamiento del navegador y criterios de desalojo")}} para obtener más información.</p> +</div> + +<h3 id="Vieja_escuela_cookies">Vieja escuela: <em>cookies</em></h3> + +<p>El concepto de almacenamiento de lado del cliente existe desde hace mucho tiempo. Desde los primeros días de la web, los sitios han utilizado <em>{{web.link("/es/docs/Web/HTTP/Cookies", "cookies")}}</em> para almacenar información y personalizar la experiencia del usuario en los sitios web. Son la forma más antigua de almacenamiento de lado del cliente que se usa comúnmente en la web.</p> + +<p>En estos días, existen mecanismos más fáciles disponibles para almacenar datos de lado del cliente, por lo tanto, no te enseñaremos cómo usar las <em>cookies</em> en este artículo. Sin embargo, esto no significa que las <em>cookies</em> sean completamente inútiles en la web moderna; todavía se usan comúnmente para almacenar datos relacionados con la personalización y el estado del usuario, p. ej. ID de sesión y fragmentos de acceso. Para obtener más información sobre las <em>cookies</em>, consulta nuestro artículo {{web.link("/es/docs/Web/HTTP/Cookies", "Uso de cookies HTTP")}}.</p> + +<h3 id="Nueva_escuela_almacenamiento_web_e_IndexedDB">Nueva escuela: almacenamiento web e <code>IndexedDB</code></h3> + +<p>Las características "más fáciles" que mencionamos anteriormente son las siguientes:</p> + +<ul> + <li>La {{web.link("/es/docs/Web/API/Web_Storage_API", "API de almacenamiento web")}} proporciona una sintaxis muy simple para almacenar y recuperar elementos de datos más pequeños que constan de un nombre y un valor correspondiente. Esto es útil cuando solo necesitas almacenar algunos datos simples, como el nombre del usuario, si está conectado, qué color usar para el fondo de la pantalla, etc.</li> + <li>La {{web.link("/es/docs/Web/API/IndexedDB_API", "API IndexedDB")}} proporciona al navegador un sistema de base de datos completo para almacenar datos complejos. Esto se puede usar para cosas desde conjuntos completos de registros de clientes, hasta incluso tipos de datos complejos como archivos de audio o video.</li> +</ul> + +<p>Aprenderás más sobre estas APIs a continuación.</p> + +<h3 id="El_futuro_API_de_caché">El futuro: API de caché</h3> + +<p>Algunos navegadores modernos admiten la nueva API {{domxref("Cache")}}. Esta API está diseñada para almacenar respuestas HTTP a solicitudes específicas y es muy útil para hacer cosas como almacenar activos del sitio web sin conexión para que el sitio se pueda usar posteriormente sin una conexión de red. La caché generalmente se usa en combinación con la {{web.link("/es/docs/Web/API/Service_Worker_API", "API del servicio Worker")}}, aunque no necesariamente tiene que ser así.</p> + +<p>El uso de caché y el servicio <em>Workers</em> es un tema avanzado, y no lo cubriremos con gran detalle en este artículo, aunque mostraremos un ejemplo simple en la sección {{anch("Almacenamiento_de_activos_sin_conexion", "Almacenamiento de activos sin conexión")}} a continuación.</p> + +<h2 id="Almacenamiento_de_datos_simples_almacenamiento_web">Almacenamiento de datos simples: almacenamiento web</h2> + +<p>La {{web.link("/es/docs/Web/API/Web_Storage_API", "API de almacenamiento web")}} es muy fácil de usar: almacena pares de datos simples de nombre/valor (limitado a cadenas, números, etc.) y recupera estos valores cuando sea necesario.</p> + +<h3 id="Sintaxis_básica">Sintaxis básica</h3> + +<p>Te mostramos como:</p> + +<ol> + <li> + <p>Primero, ve a nuestra <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/web-storage/index.html">plantilla en blanco de almacenamiento web</a> en GitHub (abre esto en una nueva pestaña).</p> + </li> + <li> + <p>Abre la consola JavaScript de las herramientas de desarrollo de tu navegador.</p> + </li> + <li> + <p>Todos tus datos de almacenamiento web están contenidos en dos estructuras similares a objetos dentro del navegador: {{domxref("Window.sessionStorage", "sessionStorage")}} y {{domxref("Window.localStorage", "localStorage")}}. El primero conserva los datos mientras el navegador está abierto (los datos se pierden cuando se cierra el navegador) y el segundo conserva los datos incluso después de que el navegador se cierra y luego se vuelve a abrir. Usaremos el segundo en este artículo, ya que generalmente es más útil.</p> + + <p>El método {{domxref("Storage.setItem()")}} te permite guardar un elemento de datos en el almacenamiento; toma dos parámetros: el nombre del elemento y su valor. Intenta escribir esto en tu consola de JavaScript (cambia el valor a tu propio nombre, si lo deseas):</p> + + <pre class="brush: js notranslate">localStorage.setItem('nombre','Chris');</pre> + </li> + <li> + <p>El método {{domxref("Storage.getItem()")}} toma un parámetro, el nombre de un elemento de datos que deseas recuperar, y devuelve el valor del elemento. Ahora escribe estas líneas en tu consola JavaScript:</p> + + <pre class="brush: js notranslate">let miNombre = localStorage.getItem('nombre'); +miNombre</pre> + + <p>Al escribir en la segunda línea, deberías ver que la variable <code>miNombre</code> ahora contiene el valor del elemento de datos <code>nombre</code>.</p> + </li> + <li> + <p>El método {{domxref("Storage.removeItem()")}} toma un parámetro, el nombre de un elemento de datos que desea eliminar, y elimina ese elemento del almacenamiento web. Escribe las siguientes líneas en tu consola JavaScript:</p> + + <pre class="brush: js notranslate">localStorage.removeItem('nombre'); +let miNombre = localStorage.getItem('nombre'); +miNombre</pre> + + <p>La tercera línea ahora debería devolver <code>null</code>: el elemento <code>nombre</code> ya no existe en el almacenamiento web.</p> + </li> +</ol> + +<h3 id="¡Los_datos_persisten!">¡Los datos persisten!</h3> + +<p>Una característica clave del almacenamiento web es que los datos persisten entre las cargas de la página (e incluso cuando el navegador está apagado, en el caso de <code>localStorage</code>). Veamos esto en acción.</p> + +<ol> + <li> + <p>Abre nuestra plantilla en blanco de almacenamiento web nuevamente, ¡pero esta vez en un navegador diferente al que tiene abierto este tutorial!; Esto hará que sea más fácil de manejar.</p> + </li> + <li> + <p>Escribe estas líneas en la consola JavaScript del navegador:</p> + + <pre class="brush: js notranslate">localStorage.setItem('nombre','Chris'); +let miNombre = localStorage.getItem('nombre'); +miNombre</pre> + + <p>Deberías ver el nombre del elemento devuelto.</p> + </li> + <li> + <p>Ahora cierre el navegador y ábrelo de nuevo.</p> + </li> + <li> + <p>Ingresa las siguientes líneas nuevamente:</p> + + <pre class="brush: js notranslate">let miNombre = localStorage.getItem('nombre'); +miNombre</pre> + + <p>Deberías ver que el valor aún está disponible, aunque el navegador se haya cerrado y luego se haya abierto nuevamente.</p> + </li> +</ol> + +<h3 id="Almacenamiento_independiente_para_cada_dominio">Almacenamiento independiente para cada dominio</h3> + +<p>Hay un almacén de datos separado para cada dominio (cada dirección web separada cargada en el navegador). Verás que si cargas dos sitios web (por ejemplo, google.com y amazon.com) e intentas almacenar un elemento en un sitio web, no estará disponible para el otro sitio web.</p> + +<p>Esto tiene sentido: ¿puedes imaginar los problemas de seguridad que surgirían si los sitios web pudieran ver los datos de los demás?</p> + +<h3 id="Un_ejemplo_más_complicado">Un ejemplo más complicado</h3> + +<p>Apliquemos este conocimiento recién descubierto escribiendo un sencillo ejemplo para darte una idea de cómo se puede usar el almacenamiento web. Nuestro ejemplo te permitirá ingresar un nombre, luego de lo cual la página se actualizará para darte un saludo personalizado. Este estado también persistirá en las recargas de la página/navegador, porque el nombre se guarda en el almacenamiento web.</p> + +<p>Puede encontrar el HTML de ejemplo en <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/web-storage/personal-greeting.html">personal-greeting.html</a>: contiene un sitio web simple con un encabezado, contenido y pie de página, y un formulario para ingresar tu nombre.</p> + +<p><img alt="Ejemplo de almacenamiento" src="https://mdn.mozillademos.org/files/15735/web-storage-demo.png" style="display: block; margin: 0 auto;"></p> + +<p>Construyamos el ejemplo para que puedas entender cómo funciona.</p> + +<ol> + <li> + <p>Primero, haz una copia local de nuestro archivo <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/web-storage/personal-greeting.html">personal-greeting.html</a> en un nuevo directorio en tu computadora.</p> + </li> + <li> + <p>A continuación, observa cómo nuestro HTML hace referencia a un archivo JavaScript llamado <code>index.js</code> (ve la línea 40). Necesitamos crearlo y escribir nuestro código JavaScript en él. Cree un archivo <code>index.js</code> en el mismo directorio que tu archivo HTML.</p> + </li> + <li> + <p>Comenzaremos creando referencias a todas las características HTML que necesitamos manipular en este ejemplo; las crearemos todas como constantes, ya que estas referencias no necesitan cambiar en el ciclo de vida de la aplicación. Agrega las siguientes líneas a tu archivo JavaScript:</p> + + <pre class="brush: js notranslate">// crea las constantes necesarias +const rememberDiv = document.querySelector('.remember'); +const forgetDiv = document.querySelector('.forget'); +const form = document.querySelector('form'); +const nameInput = document.querySelector('#entername'); +const submitBtn = document.querySelector('#submitname'); +const forgetBtn = document.querySelector('#forgetname'); + +const h1 = document.querySelector('h1'); +const personalGreeting = document.querySelector('.personal-greeting');</pre> + </li> + <li> + <p>A continuación, necesitamos incluir un pequeño escucha de eventos para evitar que el formulario se envíe cuando se presiona el botón de envío, ya que este no es el comportamiento que queremos. Agrega este fragmento debajo de tu código anterior:</p> + + <pre class="brush: js notranslate">// Evita que el formulario se envíe cuando se presiona un botón +form.addEventListener('submit', function(e) { + e.preventDefault(); +});</pre> + </li> + <li> + <p>Ahora necesitamos agregar un escucha de eventos, cuya función controladora se ejecutará cuando se haga clic en el botón "Saludar". Los comentarios explican en detalle qué hace cada bit, pero en esencia aquí tomamos el nombre que el usuario ingresó en el cuadro de entrada de texto y lo guardamos en el almacenamiento web usando <code>setItem()</code>, luego ejecutamos una función llamada <code>nameDisplayCheck()</code> que se encargará de actualizar el texto real del sitio web. Agrega esto al final de tu código:</p> + + <pre class="brush: js notranslate">// ejecuta la función cuando se hace clic en el botón 'Saludar' +submitBtn.addEventListener('click', function() { + // guarda el nombre ingresado en el almacenamiento web + localStorage.setItem('name', nameInput.value); + // ejecuta nameDisplayCheck() para ordenar la visualización del + // saludo personalizado y actualización de la visualización del formulario + nameDisplayCheck(); +});</pre> + </li> + <li> + <p>En este punto, también necesitamos un controlador de eventos para ejecutar una función cuando se hace clic en el botón "Olvidar"; esto solo se muestra después de hacer clic en el botón "Saludar" (los dos estados del formulario se alternan hacia adelante y hacia atrás). En esta función, eliminamos el elemento <code>name</code> del almacenamiento web usando <code>removeItem()</code>, luego ejecutamos nuevamente <code>nameDisplayCheck()</code> para actualizar la pantalla. Agrega esto al final:</p> + + <pre class="brush: js notranslate">// ejecuta la función cuando se hace clic en el botón 'Olvidar' +forgetBtn.addEventListener('click', function() { + // Elimina el nombre guardado del almacenamiento web + localStorage.removeItem('nombre'); + // ejecuta nameDisplayCheck() para ordenar la visualización del + // saludo genérico nuevamente y actualiza la visualización del formulario + nameDisplayCheck(); +});</pre> + </li> + <li> + <p>Ahora es el momento de definir la propia función <code>nameDisplayCheck()</code>. Aquí verificamos si el elemento de nombre se ha guardado en el almacenamiento web utilizando <code>localStorage.getItem('name')</code> como prueba condicional. Si se ha guardado, esta llamada se evaluará como <code>true</code>; si no, será <code>false</code>. Si es <code>true</code>, mostramos un saludo personalizado, mostramos la parte "Olvidar" del formulario y ocultamos la parte "Saludar" del formulario. Si es <code>false</code>, mostramos un saludo genérico y hacemos lo contrario. Nuevamente, pon el siguiente código en la parte inferior:</p> + + <pre class="brush: js notranslate">// definir la función nameDisplayCheck() +function nameDisplayCheck() { + // verifica si el elemento de datos 'name' está guardado en el almacenamiento web + if(localStorage.getItem('name')) { + // Si es así, muestra un saludo personalizado + let name = localStorage.getItem('name'); + h1.textContent = 'Bienvenido, ' + name; + personalGreeting.textContent = '¡Bienvenido a nuestro sitio web, ' + name + '! Esperamos que te diviertas mientras estés aquí.'; + // ocultar la parte 'recordar' del formulario y mostrar la parte 'olvidar' + forgetDiv.style.display = 'block'; + rememberDiv.style.display = 'none'; + } else { + // si no, muestra un saludo genérico + h1.textContent = 'Bienvenido a nuestro sitio web '; + personalGreeting.textContent = 'Bienvenido a nuestro sitio web. Esperamos que se diviertas mientras estés aquí.'; + // ocultar la parte 'olvidar' del formulario y mostrar la parte 'recordar' + forgetDiv.style.display = 'none'; + rememberDiv.style.display = 'block'; + } +}</pre> + </li> + <li> + <p>Por último, pero no menos importante, debemos ejecutar la función <code>nameDisplayCheck()</code> cada vez que se carga la página. Si no hacemos esto, el saludo personalizado no persistirá en las recargas de la página. Agrega lo siguiente al final de tu código:</p> + + <pre class="brush: js notranslate">document.body.onload = nameDisplayCheck;</pre> + </li> +</ol> + +<p>Tu ejemplo está terminado, ¡bien hecho!; Todo lo que queda ahora es guardar tu código y probar tu página HTML en un navegador. Puedes ver nuestra <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/web-storage/personal-greeting.html">versión finalizada en vivo aquí</a>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Hay otro ejemplo un poco más complejo para explorar en {{web.link("/es/docs/Web/API/Web_Storage_API/Using_the_Web_Storage_API", "Uso de la API de almacenamiento web")}}.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: En la línea <code><script src="index.js" defer></script></code> del código fuente de nuestra versión final, el atributo <code>defer</code> especifica que el contenido del elemento {{htmlelement("script")}} no se ejecutará hasta que la página haya terminado de cargarse.</p> +</div> + +<h2 id="Almacenamiento_de_datos_complejos_—_IndexedDB">Almacenamiento de datos complejos — <code>IndexedDB</code></h2> + +<p>La {{web.link("/es/docs/Web/API/IndexedDB_API", "API IndexedDB")}} (a veces abreviada <em>IDB</em>) es un sistema de base de datos completo disponible en el navegador en el que puedes almacenar datos complejos relacionados, tipos de los cuales no se limitan a valores simples como cadenas o números. Puedes almacenar videos, imágenes y casi cualquier otra cosa en una instancia de <code>IndexedDB</code>.</p> + +<p>Sin embargo, esto tiene un costo: <code>IndexedDB</code> es mucho más complejo de usar que la API de almacenamiento web. En esta sección, solo vamos a arañar la superficie de lo que es capaz de hacer, pero te daremos lo suficiente para comenzar.</p> + +<h3 id="Trabajar_con_un_ejemplo_de_almacenamiento_de_notas">Trabajar con un ejemplo de almacenamiento de notas</h3> + +<p>Aquí, mostraremos un ejemplo que te permite almacenar notas en tu navegador y verlas y eliminarlas cuando lo desees, lo cual te permitirá crearlo tú mismo y explicar las partes más fundamentales del <em>IDB</em> a medida que avanzamos.</p> + +<p>La aplicación se parece a esta:</p> + +<p><img alt="IDB en acción" src="https://mdn.mozillademos.org/files/15744/idb-demo.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Cada nota tiene un título y un cuerpo de texto, cada uno editable individualmente. El código JavaScript que veremos a continuación tiene comentarios detallados para ayudarte a comprender lo que está sucediendo.</p> + +<h3 id="Primeros_pasos">Primeros pasos</h3> + +<ol> + <li>En primer lugar, haz copias locales de nuestros archivos <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index.html"><code>index.html</code></a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/style.css"><code>style.css</code></a> y <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index-start.js"><code>index-start.js</code></a> en un nuevo directorio en tu máquina.</li> + <li>Échale un vistazo a los archivos. Verás que el HTML es bastante simple: un sitio web con encabezado y pie de página, así como un área de contenido principal que contiene un lugar para mostrar notas y un formulario para ingresar nuevas notas en la base de datos. El CSS proporciona un estilo simple para aclarar lo que está sucediendo. El archivo JavaScript contiene cinco constantes declaradas que contienen referencias al elemento {{htmlelement("ul")}} en el que se mostrarán las notas, el título y el cuerpo de elementos {{htmlelement("input")}}, el {{htmlelement("form")}} en sí mismo, y el {{htmlelement("button")}}.</li> + <li>Cambia el nombre de tu archivo JavaScript a <code>index.js</code>. Ahora estás listo para comenzar a agregarle código.</li> +</ol> + +<h3 id="Configuración_inicial_de_la_base_de_datos">Configuración inicial de la base de datos</h3> + +<p>Ahora veamos lo que tenemos que hacer en primer lugar, para configurar una base de datos.</p> + +<ol> + <li> + <p>Debajo de las declaraciones constantes, agrega las siguientes líneas:</p> + + <pre class="brush: js notranslate">// Crea una instancia de un objeto db para que almacenemos la base de datos abierta +let db;</pre> + + <p>Aquí estamos declarando una variable llamada <code>db</code>, que luego se usará para almacenar un objeto que representa nuestra base de datos. Usaremos esto en algunos lugares, por lo que hemos declarado globalmente aquí para facilitar las cosas.</p> + </li> + <li> + <p>A continuación, agrega lo siguiente al final de tu código:</p> + + <pre class="brush: js notranslate">window.onload = function() { + +};</pre> + + <p>Escribiremos todo nuestro subsiguiente código dentro de esta función controladora de eventos <code>window.onload</code>, llamada cuando se activa el evento {{event("load")}} de la ventana, para asegurarnos de que no intentemos usar la funcionalidad <code>IndexedDB</code> antes de que la aplicación haya terminado de cargarse por completo (podría fallar si no lo hacemos).</p> + </li> + <li> + <p>Dentro del controlador <code>window.onload</code>, agrega lo siguiente:</p> + + <pre class="brush: js notranslate">// Abre nuestra base de datos; se crea si aún no existe +// (ve onupgradeneeded a continuación) +let request = window.indexedDB.open('notes_db', 1);</pre> + + <p>Esta línea crea una <code>solicitud</code> para abrir la versión <code>1</code> de una base de datos llamada <code>notes_db</code>. Si esta aún no existe, se creará para ti mediante un código posterior. Verás que este patrón de solicitud se usa con mucha frecuencia en <code>IndexedDB</code>. Las operaciones de la base de datos llevan tiempo. No deseas colgar el navegador mientras esperas los resultados, por lo que las operaciones de la base de datos son {{Glossary("asíncronas")}}, lo que significa que en lugar de ocurrir de inmediato, sucederán en algún momento en el futuro, y recibirás una notificación cuando haya terminado.</p> + + <p>Para manejar esto en IndexedDB, crea un objeto de solicitud (que se puede llamar como desees; lo llamamos <code>request</code>, por lo que es obvio para qué sirve). Luego, usa controladores de eventos para ejecutar código cuando la solicitud se completa, falla, etc., que verás en uso a continuación.</p> + + <div class="note"> + <p><strong>Nota</strong>: El número de versión es importante. Si deseas actualizar tu base de datos (por ejemplo, cambiando la estructura de la tabla), debes ejecutar tu código nuevamente con un número de versión aumentado, un esquema diferente especificado dentro del controlador <code>onupgradeneeded</code> (ve más abajo), etc. No cubriremos la actualización de bases de datos en este sencillo tutorial.</p> + </div> + </li> + <li> + <p>Ahora agrega los siguientes controladores de eventos justo debajo de tu adición anterior, nuevamente dentro del controlador <code>window.onload</code>:</p> + + <pre class="brush: js notranslate">// un controlador de error significa que la base de datos no se abrió correctamente +request.onerror = function() { + console.log('No se pudo abrir la base de datos'); +}; + +// controlador onsuccess significa que la base de datos se abrió correctamente +request.onsuccess = function() { + console.log('Base de datos abierta con éxito'); + + // Almacena el objeto de base de datos abierto en la variable db. Esto se usa mucho a continuación + db = request.result; + + // Ejecute la función displayData() para mostrar las notas que ya están en la IDB + displayData(); +};</pre> + + <p>El controlador {{domxref("IDBRequest.onerror", "request.onerror")}} se ejecutará si el sistema dice que la solicitud falló. Esto te permite responder a este problema. En nuestro sencillo ejemplo, simplemente imprimimos un mensaje en la consola de JavaScript.</p> + + <p>El controlador {{domxref("IDBRequest.onsuccess", "request.onsuccess")}} por otro lado se ejecutará si la solicitud regresa con éxito, lo que significa que la base de datos se abrió correctamente. Si este es el caso, un objeto que representa la base de datos abierta pasa a estar disponible en la propiedad {{domxref("IDBRequest.result", "request.result")}}, lo que nos permite manipular la base de datos. Almacenamos esto en la variable <code>db</code> que creamos anteriormente para su uso posterior. También ejecutamos una función personalizada llamada <code>displayData()</code>, que muestra los datos en la base de datos dentro de {{HTMLElement("ul")}}. Lo ejecutamos ahora para que las notas que ya están en la base de datos se muestren tan pronto como se cargue la página. Verás esto definido más adelante.</p> + </li> + <li> + <p>Finalmente, en esta sección, agregaremos probablemente el controlador de eventos más importante para configurar la base de datos: {{domxref("IDBOpenDBRequest.onupgradeneeded", "request.onupgradeneeded")}}. Este controlador se ejecuta si la base de datos aún no se ha configurado, o si la base de datos se abre con un número de versión mayor que la base de datos almacenada existente (al realizar una actualización). Agrega el siguiente código, debajo de tu controlador anterior:</p> + + <pre class="brush: js notranslate">// Configura las tablas de la base de datos si esto aún no se ha hecho +request.onupgradeneeded = function(e) { + // Toma una referencia a la base de datos abierta + let db = e.target.result; + + // Crea un objectStore para almacenar nuestras notas (básicamente como una sola tabla) + // incluyendo una clave de incremento automático + let objectStore = db.createObjectStore('notes_os', {keyPath: 'id', autoIncrement: true}); + + // Define qué elementos de datos contendrá el objectStore + objectStore.createIndex('title', 'title', { unique: false }); + objectStore.createIndex('body', 'body', { unique: false }); + + console.log('Configuración de la base de datos completa'); +};</pre> + + <p>Aquí es donde definimos el esquema (estructura) de nuestra base de datos; es decir, el conjunto de columnas (o campos) que contiene. Aquí primero tomamos una referencia a la base de datos existente de la propiedad <code>result</code> del objetivo del evento (<code>e.target.result</code>), que es el objeto <code>request</code>. Esto es equivalente a la línea <code>db = request.result;</code> dentro del controlador <code>onsuccess</code>, pero aquí, debemos hacer esto por separado porque el controlador <code>onupgradeneeded</code> (si es necesario) se ejecutará antes que el controlador <code>onsuccess</code>, lo que significa que el valor <code>db</code> no estaría disponible si no hiciéramos esto.</p> + + <p>Luego usamos {{domxref("IDBDatabase.createObjectStore()")}} para crear un nuevo almacén de objetos dentro de nuestra base de datos abierta llamada <code>notes_os</code>. Esto es equivalente a una sola tabla en un sistema de base de datos convencional. Le hemos dado el nombre <em>notas</em>, y también hemos especificado un campo clave <code>autoIncrement</code> llamado <code>id</code> — en cada nuevo registro se le dará automáticamente un valor incrementado — el desarrollador no lo hace No es necesario establecer esto explícitamente. Al ser la clave, el campo <code>id</code> se utilizará para identificar registros de forma única, como cuando se elimina o muestra un registro.</p> + + <p>También creamos otros dos índices (campos) usando el método {{domxref("IDBObjectStore.createIndex()")}}: <code>title</code> (que contendrá un título para cada nota) y <code>body</code> (que contendrá el texto del cuerpo de la nota).</p> + </li> +</ol> + +<p>Entonces, con este esquema de base de datos simple configurado, cuando comenzamos a agregar registros a la base de datos; cada uno se representará como un objeto siguiendo estas líneas:</p> + +<pre class="brush: js notranslate">{ + title: "Compra leche", + body: "Necesita leche de vaca y soja", + id: 8 +}</pre> + +<h3 id="Agregar_datos_a_la_base_de_datos">Agregar datos a la base de datos</h3> + +<p>Ahora veamos cómo podemos agregar registros a la base de datos. Esto se hará mediante el formulario de nuestra página.</p> + +<p>Debajo de tu controlador de eventos anterior (pero aún dentro del controlador <code>window.onload</code>), agrega la siguiente línea, que configura un controlador <code>onsubmit</code> que ejecuta una función llamada <code>addData()</code> cuando se envía el formulario (cuando se presiona el {{htmlelement("button")}} de enviar, lo que lleva a un envío exitoso del formulario):</p> + +<pre class="brush: js notranslate">// Crea un controlador onsubmit para que cuando se envíe el formulario se ejecute la función addData() +form.onsubmit = addData;</pre> + +<p>Ahora definamos la función <code>addData()</code>. Agrega esto debajo de tu línea anterior:</p> + +<pre class="brush: js notranslate">// Define la función addData() +function addData(e) { + // evitar el predeterminado: no queremos que el formulario se envíe de la forma convencional + e.preventDefault(); + + // toma los valores ingresados en los campos del formulario y los almacenar en un objeto listo para ser insertado en la base de datos + let newItem = { title: titleInput.value, body: bodyInput.value }; + + // abre una transacción de base de datos de lectura/escritura, lista para agregar los datos + let transaction = db.transaction(['notes_os'], 'readwrite'); + + // llama a un almacén de objetos que ya se ha agregado a la base de datos + let objectStore = transaction.objectStore('notes_os'); + + // Hacer una solicitud para agregar nuestro objeto newItem al almacén de objetos + let request = objectStore.add(newItem); + request.onsuccess = function() { + // Limpiar el formulario, listo para agregar la siguiente entrada + titleInput.value = ''; + bodyInput.value = ''; + }; + + // Informa sobre el éxito de la transacción completada, cuando todo esté hecho + transaction.oncomplete = function() { + console.log('Transacción completada: modificación de la base de datos finalizada.'); + + // actualiza la visualización de datos para mostrar el elemento recién agregado, ejecutando displayData() nuevamente. + displayData(); + }; + + transaction.onerror = function() { + console.log('Transacción no abierta debido a error'); + }; +}</pre> + +<p>Esto es bastante complejo; desglosándolo, podemos:</p> + +<ul> + <li>Ejecuta {{domxref("Event.preventDefault()")}} en el objeto de evento para detener el envío del formulario de la manera convencional (esto provocaría una actualización de la página y estropearía la experiencia).</li> + <li>Crea un objeto que represente un registro para ingresar a la base de datos, llenándolo con valores de las entradas del formulario. ten en cuenta que no tenemos que incluir explícitamente un valor de <code>id</code>; como explicamos anteriormente, esto se completa automáticamente.</li> + <li>Abre una transacción <code>readwrite</code> contra el almacén de objetos <code>notes_os</code> utilizando el método {{domxref("IDBDatabase.transaction()")}}. Este objeto de transacción nos permite acceder al almacén de objetos para que podamos hacerle algo, p. ej. agregar un nuevo registro.</li> + <li>Accede a la tienda de objetos utilizando el método {{domxref("IDBTransaction.objectStore()")}}, guardando el resultado en la variable <code>objectStore</code>.</li> + <li>Agrega el nuevo registro a la base de datos usando {{domxref("IDBObjectStore.add()")}}. Esto crea un objeto <code>request</code>, de la misma manera que hemos visto antes.</li> + <li>Agrega un grupo de controladores de eventos a <code> request</code> y a <code>transaction</code> para ejecutar código en puntos críticos del ciclo de vida. Una vez que la solicitud ha tenido éxito, borramos las entradas del formulario y estamos listos para ingresar la siguiente nota. Una vez que la transacción se ha completado, ejecutamos la función <code>displayData()</code> nuevamente para actualizar la visualización de notas en la página.</li> +</ul> + +<h3 id="Visualización_de_los_datos">Visualización de los datos</h3> + +<p>Ya hemos hecho referencia a <code>displayData()</code> dos veces en nuestro código, por lo que probablemente sea mejor definirla. Agrega esto a tu código, debajo de la definición de función anterior:</p> + +<pre class="brush: js notranslate">// Define la función displayData() +function displayData() { + // Aquí vaciamos el contenido del elemento de la lista cada vez que se actualiza la pantalla + // Si no hiciste esto, obtendrás duplicados en la lista cada vez que se agregue una nueva nota + while (list.firstChild) { + list.removeChild(list.firstChild); + } + + // Abre el almacén de objetos y luego obtiene un cursor, que recorre todos los + // diferentes elementos de datos en el almacén + let objectStore = db.transaction('notes_os').objectStore('notes_os'); + objectStore.openCursor().onsuccess = function(e) { + // Obtiene una referencia al cursor + let cursor = e.target.result; + + // Si todavía hay otro elemento de datos para iterar, sigue ejecutando este código + if(cursor) { + // Crea un elemento de lista, h3 y p para poner cada elemento de datos dentro al mostrarlo + // estructura el fragmento HTML y lo anexa dentro de la lista + const listItem = document.createElement('li'); + const h3 = document.createElement('h3'); + const para = document.createElement('p'); + + listItem.appendChild(h3); + listItem.appendChild(para); + list.appendChild(listItem); + + // Coloca los datos del cursor dentro de h3 y para + h3.textContent = cursor.value.title; + para.textContent = cursor.value.body; + + // Almacena el ID del elemento de datos dentro de un atributo en listItem, para que sepamos + // a qué elemento corresponde. Esto será útil más adelante cuando queramos eliminar elementos. + listItem.setAttribute('data-note-id', cursor.value.id); + + // Crea un botón y lo coloca dentro de cada listItem + const deleteBtn = document.createElement('button'); + listItem.appendChild(deleteBtn); + deleteBtn.textContent = 'Delete'; + + // Establece un controlador de eventos para que cuando se hace clic en el botón, el elemento deleteItem() + // se ejecuta la función + deleteBtn.onclick = deleteItem; + + // Iterar al siguiente elemento del cursor + cursor.continue(); + } else { + // Nuevamente, si el elemento de la lista está vacío, muestra el mensaje 'No hay notas almacenadas' + if(!list.firstChild) { + const listItem = document.createElement('li'); + listItem.textContent = 'No hay notas almacenadas.'; + list.appendChild(listItem); + } + // si no hay más elementos de cursor para iterar, dilo + console.log('Se muestran todas las notas'); + } + }; +}</pre> + +<p>De nuevo, analicemos esto:</p> + +<ul> + <li>Primero vaciamos el contenido del elemento {{htmlelement("ul")}}, antes de llenarlo con el contenido actualizado. Si no hiciera esto, terminarías con una enorme lista de contenido duplicado que se agrega con cada actualización.</li> + <li>A continuación, obtenemos una referencia al almacén de objetos <code>notes_os</code> usando {{domxref("IDBDatabase.transaction()")}} y {{domxref("IDBTransaction.objectStore()")}} como hicimos en <code>addData()</code>, excepto que aquí los estamos encadenando juntos en una línea.</li> + <li>El siguiente paso es usar el método {{domxref("IDBObjectStore.openCursor()")}} para abrir una solicitud de un cursor; esta es una construcción que se puede usar para iterar sobre los registros en un almacén de objetos. Encadenamos un controlador <code>onsuccess</code> al final de esta línea para que el código sea más conciso: cuando el cursor se devuelve correctamente, se ejecuta el controlador.</li> + <li>Obtenemos una referencia al propio cursor (un objeto {{domxref("IDBCursor")}}) usando let <code>cursor = e.target.result</code>.</li> + <li>A continuación, verificamos si el cursor contiene un registro del almacén de datos (<code>if (cursor) {...}</code>); si es así, creamos un fragmento DOM, lo llenamos con los datos del registro y lo insertamos en la página (dentro del elemento <code><ul></code>). También incluimos un botón para eliminar que, al hacer clic, eliminará esa nota ejecutando la función <code>deleteItem()</code>, que veremos en la siguiente sección.</li> + <li>Al final del bloque <code>if</code>, usamos el método {{domxref("IDBCursor.continue()")}} para hacer avanzar el cursor al siguiente registro en el almacén de datos y ejecutar el contenido de el bloque <code>if</code> nuevamente. Si hay otro registro para iterar, esto hace que se inserte en la página, y luego se ejecuta <code>continue()</code> nuevamente, y así sucesivamente.</li> + <li>Cuando no hay más registros sobre los que iterar, <code>cursor</code> devolverá <code>undefined</code> y, por lo tanto, el bloque <code>else</code> se ejecutará en lugar del bloque <code>if</code>. Este bloque comprueba si se insertaron notas en el <code><ul></code>; de lo contrario, inserta un mensaje para indicar que no se almacenó ninguna nota.</li> +</ul> + +<h3 id="Eliminar_una_nota">Eliminar una nota</h3> + +<p>Como se indicó anteriormente, cuando se presiona el botón de eliminación de una nota, la nota se elimina. Esto se logra mediante la función <code>deleteItem()</code>, que se ve así:</p> + +<pre class="brush: js notranslate">// Define la función deleteItem() +function deleteItem(e) { + // recuperamos el nombre de la tarea que queremos eliminar. Necesitamos + // convertirla en un número antes de intentarla úselo con IDB; Clave del IDB + // los valores son sensibles al tipo. + let noteId = Number(e.target.parentNode.getAttribute('data-note-id')); + + // abre una transacción de base de datos y elimina la tarea, encontrándola usando la identificación que obtuvimos arriba + let transaction = db.transaction(['notes_os'], 'readwrite'); + let objectStore = transaction.objectStore('notes_os'); + let request = objectStore.delete(noteId); + + // informa que el elemento de datos ha sido eliminado + transaction.oncomplete = function() { + // elimina el padre del botón + // que es el elemento de la lista, por lo que ya no se muestra + e.target.parentNode.parentNode.removeChild(e.target.parentNode); + console.log('Nota ' + noteId + ' eliminada.'); + + // Nuevamente, si el elemento de la lista está vacío, muestra el mensaje 'No hay notas almacenadas' + if(!list.firstChild) { + let listItem = document.createElement('li'); + listItem.textContent = 'No hay notas almacenadas.'; + list.appendChild(listItem); + } + }; +}</pre> + +<ul> + <li>La primera parte de esto podría necesitar algo de explicación: recuperamos el ID del registro que se va a eliminar usando <code>Number(e.target.parentNode.getAttribute('data-note-id'))</code> — recuerda que el ID del registro se guardó en un atributo <code>data-note-id</code> en el <code><li></code> cuando se mostró por primera vez. Sin embargo, necesitamos pasar el atributo a través del objeto <code><a href="/es/docs/Web/JavaScript/Reference/Global_Objects/Number">Number()</a></code> integrado global ya que es de tipo cadena de datos y, por lo tanto, no sería reconocido por la base de datos, que espera un número.</li> + <li>Luego obtenemos una referencia al almacén de objetos usando el mismo patrón que hemos visto anteriormente, y usamos el método {{domxref("IDBObjectStore.delete()")}} para eliminar el registro de la base de datos, pasándole el ID.</li> + <li>Cuando se completa la transacción de la base de datos, eliminamos el <code><li></code> de la nota del DOM, y nuevamente hacemos la verificación para ver si el <code><ul></code> ahora está vacío, insertando un nota según corresponda.</li> +</ul> + +<p>¡Eso es todo!; Tu ejemplo debería funcionar ahora.</p> + +<p>Si tienes problemas con él, no dudes en <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/indexeddb/notes/">compararlo con nuestro ejemplo en vivo</a> (consulta el <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/indexeddb/notes/index.js">código fuente</a> también).</p> + +<h3 id="Almacenamiento_de_datos_complejos_a_través_de_IndexedDB">Almacenamiento de datos complejos a través de <code>IndexedDB</code></h3> + +<p>Como mencionamos anteriormente, <code>IndexedDB</code> se puede usar para almacenar más que simples cadenas de texto. Puedes almacenar casi cualquier cosa que desees, incluidos objetos complejos como blobs de imágenes o vídeos. Y no es mucho más difícil de conseguir que cualquier otro tipo de dato.</p> + +<p>Para demostrar cómo hacerlo, hemos escrito otro ejemplo llamado <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/client-side-storage/indexeddb/video-store">almacenaje de videos con IndexedDB</a> (verlo <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/indexeddb/video-store/">en vivo aquí también</a>). Cuando ejecutas el ejemplo por primera vez, descarga todos los videos de la red, los almacena en una base de datos <code>IndexedDB</code> y luego muestra los videos en la IU dentro de los elementos {{htmlelement("video")}}. La segunda vez que lo ejecutas, encuentra los videos en la base de datos y los obtiene de allí antes de mostrarlos; esto hace que las cargas posteriores sean mucho más rápidas y menos necesitadas de ancho de banda.</p> + +<p>Repasemos las partes más interesantes del ejemplo. No lo veremos todo; gran parte es similar al ejemplo anterior y el código está bien comentado.</p> + +<ol> + <li> + <p>Para este ejemplo simple, hemos almacenado los nombres de los videos para buscarlos en un arreglo de objetos:</p> + + <pre class="brush: js notranslate">const videos = [ + { 'name' : 'crystal' }, + { 'name' : 'elf' }, + { 'name' : 'frog' }, + { 'name' : 'monster' }, + { 'name' : 'pig' }, + { 'name' : 'rabbit' } +];</pre> + </li> + <li> + <p>Para empezar, una vez que la base de datos se abre con éxito, ejecutamos una función <code>init()</code>. Esto recorre los diferentes nombres de video, tratando de cargar un registro identificado por cada nombre de la base de datos de <code>videos</code>.</p> + + <p>Si cada video se encuentra en la base de datos (se verifica fácilmente al ver si <code>request.result</code> se evalúa como <code>true</code>; si el registro no está presente, será <code>undefined</code>), sus archivos de video (almacenados como blobs) y el nombre del video se pasan directamente a la función <code>displayVideo()</code> para colocarlos en la interfaz de usuario. De lo contrario, el nombre del video se pasa a la función <code>fetchVideoFromNetwork()</code> para ... ¡adivinaste!: recupera el video de la red.</p> + + <pre class="brush: js notranslate">function init() { + // Recorre los nombres de los videos uno por uno + for(let i = 0; i < videos.length; i++) { + // Abre la transacción, obtiene objetos del almacén y get() cada video por nombre + let objectStore = db.transaction('videos_os').objectStore('videos_os'); + let request = objectStore.get(videos[i].name); + request.onsuccess = function() { + // Si el resultado existe en la base de datos (no está indefinido) + if(request.result) { + // Toma los videos del IDB y los muestra usando displayVideo() + console.log('tomando videos del IDB'); + displayVideo(request.result.mp4, request.result.webm, request.result.name); + } else { + // Recuperar los videos de la red + fetchVideoFromNetwork(videos[i]); + } + }; + } +}</pre> + </li> + <li> + <p>El siguiente fragmento se tomó del interior de <code>fetchVideoFromNetwork()</code> — aquí obtenemos las versiones MP4 y WebM del video usando dos peticiones {{domxref("fetch()", "WindowOrWorkerGlobalScope.fetch()")}}. Luego usamos el método {{domxref("blob()", "Body.blob()")}} para extraer el cuerpo de cada respuesta como un blob, dándonos una representación de objeto de los videos que se pueden almacenar y mostrar más adelante.</p> + + <p>Sin embargo, tenemos un problema aquí: estas dos solicitudes son asíncronas, pero solo queremos intentar mostrar o almacenar el video cuando ambas promesas se hayan cumplido. Afortunadamente, hay un método incorporado que maneja este problema: {{jsxref("Promise.all()")}}. Este toma un argumento, referencias a todas las promesas individuales que deseas verificar para su cumplimiento colocadas en un arreglo, y en sí mismo se basa en promesas.</p> + + <p>Cuando todas esas promesas se han cumplido, la promesa <code>all()</code> se cumple con un arreglo que contiene todos los valores de cumplimiento individuales. Dentro del bloque <code>all()</code>, puedes ver que luego llamamos a la función <code>displayVideo()</code> como lo hicimos antes para mostrar los videos en la interfaz de usuario, luego también llamamos a la función <code>storeVideo()</code> para almacenar esos videos dentro de la base de datos.</p> + + <pre class="brush: js notranslate">let mp4Blob = fetch('videos/' + video.name + '.mp4').then(response => + response.blob() +); +let webmBlob = fetch('videos/' + video.name + '.webm').then(response => + response.blob() +); + +// Ejecuta el siguiente código solo cuando se hayan cumplido ambas promesas +Promise.all([mp4Blob, webmBlob]).then(function(values) { + // muestra el video obtenido de la red con displayVideo() + displayVideo(values[0], values[1], video.name); + // lo almacena en el IDB usando storeVideo() + storeVideo(values[0], values[1], video.name); +});</pre> + </li> + <li> + <p>Veamos primero <code>storeVideo()</code>. Esto es muy similar al patrón que viste en el ejemplo anterior para agregar datos a la base de datos: abrimos una transacción <code>readwrite</code> y obtenemos una referencia a nuestro almacén de objetos <code>videos_os</code>, creamos un objeto que representa el registro para agregar a la base de datos, luego simplemente lo agrega usando {{domxref("IDBObjectStore.add()")}}.</p> + + <pre class="brush: js notranslate">función storeVideo(mp4Blob, webmBlob, nombre) { + // Abre transacción, obtiene el almacén de objetos; lo convierte en lectura y escritura para que podamos escribir en el IDB + let objectStore = db.transaction(['videos_os'], 'readwrite').objectStore('videos_os'); + // Crea un registro para agregar al IDB + let record = { + mp4 : mp4Blob, + webm : webmBlob, + name : name + } + + // Agrega el registro al IDB usando add() + let request = objectStore.add(record); + + ... + +};</pre> + </li> + <li> + <p>Por último, pero no menos importante, tenemos <code>displayVideo()</code>, que crea los elementos DOM necesarios para insertar el video en la interfaz de usuario y luego los agrega a la página. Las partes más interesantes de esto son las que se muestran a continuación: para mostrar realmente nuestros blobs de video en un elemento <code><video></code>, necesitamos crear URL de objeto (URL internas que apuntan a los blobs de video almacenados en la memoria) utilizando el método {{domxref("URL.createObjectURL()")}}. Una vez hecho esto, podemos configurar las URL del objeto para que sean los valores de los atributos <code>src</code> de nuestro elemento {{htmlelement("source")}}, y funciona bien.</p> + + <pre class="brush: js notranslate">function displayVideo(mp4Blob, webmBlob, title) { + // Crea URL del objeto a partir de blobs + let mp4URL = URL.createObjectURL(mp4Blob); + let webmURL = URL.createObjectURL(webmBlob); + + ... + + const video = document.createElement('video'); + video.controls = true; + const source1 = document.createElement('source'); + source1.src = mp4URL; + source1.type = 'video/mp4'; + const source2 = document.createElement('source'); + source2.src = webmURL; + source2.type = 'video/webm'; + + ... +}</pre> + </li> +</ol> + +<h2 id="Almacenamiento_de_activos_sin_conexión">Almacenamiento de activos sin conexión</h2> + +<p>El ejemplo anterior ya muestra cómo crear una aplicación que almacenará grandes activos en una base de datos <code>IndexedDB</code>, evitando la necesidad de descargarlos más de una vez. Esto ya es una gran mejora para la experiencia del usuario, pero todavía falta una cosa: los archivos HTML, CSS y JavaScript principales aún se deben descargar cada vez que se accede al sitio, lo cual significa que no funcionará cuando no haya conexión de red.</p> + +<p><img alt="Fuera de línea" src="https://mdn.mozillademos.org/files/15759/ff-offline.png" style="border-style: solid; border-width: 1px; display: block; height: 307px; margin: 0px auto; width: 765px;"></p> + +<p>Aquí es donde entran el {{web.link("/es/docs/Web/API/Service_Worker_API", "servicio workers")}} y la {{web.link("/es/docs/Web/API/Cache", "API de caché")}}.</p> + +<p>Un servicio <em>worker</em> es un archivo JavaScript que, en pocas palabras, se registra con un origen en particular (sitio web o parte de un sitio web en un determinado dominio) cuando se accede a él mediante un navegador. Cuando se registra, puede controlar las páginas disponibles en ese origen. Para ello, se sienta entre una página cargada y la red e intercepta las solicitudes de red dirigidas a ese origen.</p> + +<p>Cuando intercepta una solicitud, puede hacer lo que desees (consulta {{web.link("/es/docs/Web/API/Service_Worker_API#Other_use_case_ideas", "ideas de casos de uso")}}), pero el ejemplo clásico es guardar las respuestas de la red fuera de línea y luego proporcionarlas en respuesta a una solicitud en lugar de las respuestas de la red. De hecho, te permite hacer que un sitio web funcione completamente fuera de línea.</p> + +<p>La API de caché es otro mecanismo de almacenamiento del lado del cliente, con una pequeña diferencia: está diseñada para guardar respuestas HTTP y, por lo tanto, funciona muy bien con el servicio <em>workers</em>.</p> + +<div class="note"> +<p><strong>Nota</strong>: El servicio <em>workers</em> y la memoria caché ahora son compatibles con la mayoría de los navegadores modernos. Al momento de escribir este artículo, Safari todavía estaba ocupado implementándolo, pero debería estar allí pronto.</p> +</div> + +<h3 id="Un_ejemplo_del_servicio_worker">Un ejemplo del servicio <em>worker</em></h3> + +<p>Veamos un ejemplo para darte una idea de cómo se vería esto. Hemos creado otra versión del ejemplo del almacén de videos que vimos en la sección anterior; este funciona de manera idéntica, excepto que también guarda HTML, CSS y JavaScript en la API de caché a través de un servicio <em>worker</em>, lo que permite que el ejemplo se ejecute sin conexión.</p> + +<p>Ve <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/">almacén de videos IndexedDB con servicio worker funcionando en vivo</a> y también <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/client-side-storage/cache-sw/video-store-offline">ve el código fuente</a>.</p> + +<h4 id="Registrar_el_servicio_worker">Registrar el servicio <em>worker</em></h4> + +<p>Lo primero que hay que tener en cuenta es que hay un fragmento adicional de código colocado en el archivo JavaScript principal (consulta <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/cache-sw/video-store-offline/index.js">index.js</a>). Primero hacemos una prueba de detección de características para ver si el miembro <code>serviceWorker</code> está disponible en el objeto {{domxref("Navigator")}}. Si esto devuelve <code>true</code>, entonces sabemos que al menos se respaldan los conceptos básicos del servicio <em>workers</em>. Aquí adentro usamos el método {{domxref("ServiceWorkerContainer.register )")}} para registrar un servicio <em>worker</em> contenido en el archivo <code>sw.js</code> contra el origen en el que reside, para que pueda controlar páginas en el mismo directorio que él, o subdirectorios. Cuando se cumple su promesa, el trabajador del servicio se considera registrado.</p> + +<pre class="brush: js notranslate"> // Registrar el servicio workers para controlar que el sitio funcione sin conexión + + if('serviceWorker' in navigator) { + navigator.serviceWorker + .register('/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js') + .then(function() { console.log('Servicio Worker Registrado'); }); + }</pre> + +<div class="note"> +<p><strong>Nota</strong>: La ruta proporcionada al archivo <code>sw.js</code> es relativa al origen del sitio, no al archivo JavaScript que contiene el código. El servicio <em>worker</em> está en <code>https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js</code>. El origen es <code>https://mdn.github.io</code> y, por lo tanto, la ruta dada debe ser <code>/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js</code>. Si quisieras alojar este ejemplo en tu propio servidor, tendrías que cambiarlo consecuentemente. Esto es bastante confuso, pero tiene que funcionar de esta manera por razones de seguridad.</p> +</div> + +<h4 id="Instalación_del_servicio_worker">Instalación del servicio <em>worker</em></h4> + +<p>La próxima vez que se accede a cualquier página bajo el control del servicio <em>worker</em> (por ejemplo, cuando se vuelve a cargar el ejemplo), el servicio <em>worker</em> se instala en esa página, lo cual significa que comenzará a controlarla. Cuando esto ocurre, se dispara un evento <code>install</code> contra el servicio <em>worker</em>; puedes escribir código dentro del propio servicio <em>worker</em> que responderá a la instalación.</p> + +<p>Veamos un ejemplo, en el archivo <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/client-side-storage/cache-sw/video-store-offline/sw.js">sw.js</a> (el servicio <em>worker</em>). Verás que el detector de instalación está registrado en <code>self</code>. Esta palabra clave <code>self</code> es una forma de hacer referencia al alcance global del servicio <em>worker</em> desde el interior del archivo del servicio <em>worker</em>.</p> + +<p>Dentro del controlador <code>install</code> usamos el método {{domxref("ExtendableEvent.waitUntil()")}}, disponible en el objeto <code>event</code>, para indicar que el navegador no debe completar la instalación del servicio <em>worker</em> hasta que la promesa interior se haya cumplido con éxito.</p> + +<p>Aquí es donde vemos en acción la API de <code>Cache</code>. Usamos el método {{domxref("CacheStorage.open()")}} para abrir un nuevo objeto <code>Cache</code> en el que se pueden almacenar las respuestas (similar a un almacén de objetos <code>IndexedDB</code>). Esta promesa se cumple con un objeto {{domxref("Cache")}} que representa la caché de <code>video-store</code>. Luego usamos el método {{domxref("Cache.addAll()")}} para obtener una serie de activos y agregar sus respuestas a la caché.</p> + +<pre class="brush: js notranslate">self.addEventListener('install', function(e) { + e.waitUntil( + caches.open('video-store').then(function(cache) { + return cache.addAll([ + '/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/', + '/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/index.html', + '/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/index.js', + '/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/style.css' + ]); + }) + ); +});</pre> + +<p>Eso es todo por ahora, instalación terminada.</p> + +<h4 id="Responder_a_más_solicitudes">Responder a más solicitudes</h4> + +<p>Con el servicio <em>worker</em> registrado e instalado en nuestra página HTML, y todos los activos relevantes agregados a nuestra caché, estamos casi listos para comenzar. Solo queda una cosa más por hacer, escribir código para responder a más solicitudes de red.</p> + +<p>Esto es lo que hace el segundo bit de código en <code>sw.js</code>. Agregamos otro escucha al ámbito global del servicio <em>worker</em>, que ejecuta la función del controlador cuando se genera el evento <code>fetch</code>. Esto sucede cada vez que el navegador solicita un activo en el directorio en el que está registrado el servicio <em>worker</em>.</p> + +<p>Dentro del controlador, primero registramos la URL del activo solicitado. Luego proporcionamos una respuesta personalizada a la solicitud, utilizando el método {{domxref("FetchEvent.respondWith()")}}.</p> + +<p>Dentro de este bloque usamos {{domxref("CacheStorage.match()")}} para verificar si una solicitud coincidente (es decir, coincide con la URL) se puede encontrar en cualquier caché. Esta promesa se cumple con la respuesta coincidente si se encuentra una coincidencia, o <code>undefined</code> si no lo es.</p> + +<p>Si se encuentra una coincidencia, simplemente la devolvemos como la respuesta personalizada. De lo contrario, {{web.link("/es/docs/Web/API/WindowOrWorkerGlobalScope/fetch", "fetch()")}} la respuesta de la red y la devolvemos en su lugar.</p> + +<pre class="brush: js notranslate">self.addEventListener('fetch', function(e) { + console.log(e.request.url); + e.respondWith( + caches.match(e.request).then(function(response) { + return response || fetch(e.request); + }) + ); +});</pre> + +<p>Y eso es todo para nuestro sencillo servicio <em>worker</em>. Hay muchas más cosas que puedes hacer con ellos; para obtener más detalles, consulta el <a href="https://serviceworke.rs/">libro de recetas para el servicio <em>worker</em></a>. Y gracias a Paul Kinlan por su artículo <a href="https://developers.google.com/web/fundamentals/codelabs/offline/">Agregar un servicio <em>worker</em> y sin conexión a tu aplicación web</a>, que inspiró este sencillo ejemplo.</p> + +<h4 id="Probando_el_ejemplo_sin_conexión">Probando el ejemplo sin conexión</h4> + +<p>Para probar nuestro <a href="https://mdn.github.io/learning-area/javascript/apis/client-side-storage/cache-sw/video-store-offline/">ejemplo de servicio <em>worker</em></a>, deberás cargarlo un par de veces para asegurarte de que esté instalado. Una vez hecho esto, puedes:</p> + +<ul> + <li>Intenta desconectar tu red/apagar tu <em>Wifi</em>.</li> + <li>Selecciona <em>Archivo → Trabajar sin conexión</em> si estás usando Firefox.</li> + <li>Ve a <em>devtools</em>, luego elige <em>Aplicación → Servicio worker</em>, luego marca la casilla de verificación <em>Sin conexión</em> si estás usando Chrome.</li> +</ul> + +<p>Si actualizas tu página de ejemplo nuevamente, deberías ver que se carga bien. Todo se almacena sin conexión: los activos de la página en una caché y los videos en una base de datos <code>IndexedDB</code>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Eso es todo por ahora. Esperamos que hayas encontrado útil nuestro resumen de las tecnologías de almacenamiento de lado del cliente.</p> + +<h2 id="Ve_también">Ve también</h2> + +<ul> + <li>{{web.link("/es/docs/Web/API/Web_Storage_API", "API de almacenamiento Web")}}</li> + <li>{{web.link("/es/docs/Web/API/IndexedDB_API", "API IndexedDB")}}</li> + <li>{{web.link("/es/docs/Web/HTTP/Cookies", "Cookies")}}</li> + <li>{{web.link("/es/docs/Web/API/Service_Worker_API", "API del servicio worker")}}</li> +</ul> + +<p>{{PreviousMenu("Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Introduction", "Introducción a las APIs web")}}</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Manipulación de documentos")}}</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data", "Obtener datos del servidor")}}</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "API de terceros")}}</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics", "Dibujar gráficos")}}</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs", "APIs de video y audio")}}</li> + <li>{{web.link("/es/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage", "Almacenamiento de lado del cliente")}}</li> +</ul> diff --git a/files/es/learn/javascript/client-side_web_apis/fetching_data/index.html b/files/es/learn/javascript/client-side_web_apis/fetching_data/index.html new file mode 100644 index 0000000000..ab34b8c319 --- /dev/null +++ b/files/es/learn/javascript/client-side_web_apis/fetching_data/index.html @@ -0,0 +1,373 @@ +--- +title: Fetching data from the server +slug: Learn/JavaScript/Client-side_web_APIs/Fetching_data +translation_of: Learn/JavaScript/Client-side_web_APIs/Fetching_data +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div> + +<p class="summary">Otra tarea muy común en páginas web y en aplicaciones es tomar elementos individuales de datos desde el servidor para actualizar secciones de la página web sin tener que cargar toda una nueva página. Este aparentemente pequeño detalle tiene un gran impacto en el desempeño y comportamiento de los sitios, por eso en este artículo, explicaremos el concepto y veremos las tecnologías que hacen esto posible, como ser XHLHttpRequest y FetchAPI. </p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>JavaScript básico (ver <a href="/en-US/docs/Learn/JavaScript/First_steps">first steps</a>, <a href="/en-US/docs/Learn/JavaScript/Building_blocks">building blocks</a>, <a href="/en-US/docs/Learn/JavaScript/Objects">JavaScript objects</a>), <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction">basics of Client-side APIs</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender como extraer datos desde el servidor y usarlo para cargar contenido en la página web. </td> + </tr> + </tbody> +</table> + +<h2 id="Cúal_es_el_problema_aquí">Cúal es el problema aquí?</h2> + +<p>Originalmente cargar páginas en la web era simple — tu enviabas una solicitud de la página web al servidor, y si no había ningún problema, los servicios encargados de la página web la descargaban y mostraban en tu computadora.</p> + +<p><img alt="A basic representation of a web site architecture" src="https://mdn.mozillademos.org/files/6475/web-site-architechture@2x.png" style="display: block; height: 134px; margin: 0px auto; width: 484px;"></p> + +<p>El problema con este modelo es que si tu quieres actualizar cualquier parte de la página, por ejemplo, mostrar el nuevo set de productos o cargar una nueva página, tu tenías que cargar toda la página de nuevo. Esto es extremadamente un desperdicio y resultaba ser una experiencia pobre al usuario, especialmente cuando la página es más grande y más compleja. </p> + +<h3 id="Introduciendo_Ajax">Introduciendo Ajax</h3> + +<p>This led to the creation of technologies that allow web pages to request small chunks of data (such as <a href="/en-US/docs/Web/HTML">HTML</a>, {{glossary("XML")}}, <a href="/en-US/docs/Learn/JavaScript/Objects/JSON">JSON</a>, or plain text) and display them only when needed, helping to solve the problem described above.</p> + +<p>This is achieved by using APIs like {{domxref("XMLHttpRequest")}} or — more recently — the <a href="/en-US/docs/Web/API/Fetch_API">Fetch API</a>. These technologies allow web pages to directly handle making <a href="/en-US/docs/Web/HTTP">HTTP</a> requests for specific resources available on a server and formatting the resulting data as needed before it is displayed.</p> + +<div class="note"> +<p><strong>Note</strong>: In the early days, this general technique was known as <a href="https://developer.mozilla.org/en-US/docs/Glossary/Asynchronous">Asynchronous</a> JavaScript and XML (<a href="https://developer.mozilla.org/en-US/docs/Glossary/Ajax">Ajax</a>), because it tended to use {{domxref("XMLHttpRequest")}} to request XML data. This is normally not the case these days (you'd be more likely to use <code>XMLHttpRequest</code> or Fetch to request JSON), but the result is still the same, and the term "Ajax" is still often used to describe the technique.</p> +</div> + +<p><img alt="A simple modern architecture for web sites" src="https://mdn.mozillademos.org/files/6477/moderne-web-site-architechture@2x.png" style="display: block; height: 235px; margin: 0px auto; width: 559px;"></p> + +<p>The Ajax model involves using a web API as a proxy to more intelligently request data rather than just having the browser reload the entire page. Let's think about the significance of this:</p> + +<ol> + <li>Go to one of your favorite information-rich sites, like Amazon, YouTube, CNN, etc., and load it.</li> + <li>Now search for something, like a new product. The main content will change, but most of the surrounding information, like the header, footer, navigation menu, etc., will stay the same.</li> +</ol> + +<p>This is a really good thing because:</p> + +<ul> + <li>Page updates are a lot quicker and you don't have to wait for the page to refresh, meaning that the site feels faster and more responsive.</li> + <li>Less data is downloaded on each update, meaning less wasted bandwidth. This may not be such a big issue on a desktop on a broadband connection, but it's a major issue on mobile devices and in developing countries that don't have ubiquitous fast Internet service.</li> +</ul> + +<p>To speed things up even further, some sites also store assets and data on the user's computer when they are first requested, meaning that on subsequent visits they use the local versions instead of downloading fresh copies when the page is first loaded. The content is only reloaded from the server when it has been updated.</p> + +<p><img alt="A basic web app data flow architecture" src="https://mdn.mozillademos.org/files/6479/web-app-architecture@2x.png" style="display: block; height: 383px; margin: 0px auto; width: 562px;"></p> + +<h2 id="A_basic_Ajax_request">A basic Ajax request</h2> + +<p>Let's look at how such a request is handled, using both {{domxref("XMLHttpRequest")}} and <a href="/en-US/docs/Web/API/Fetch_API">Fetch</a>. For these examples, we'll request data out of a few different text files and use them to populate a content area.</p> + +<p>This series of files will act as our fake database; in a real application, we'd be more likely to use a server-side language like PHP, Python, or Node to request our data from a database. Here, however, we want to keep it simple and concentrate on the client-side part of this.</p> + +<h3 id="XMLHttpRequest">XMLHttpRequest</h3> + +<p><code>XMLHttpRequest</code> (which is frequently abbreviated to XHR) is a fairly old technology now — it was invented by Microsoft in the late '90s, and has been standardized across browsers for quite a long time.</p> + +<ol> + <li> + <p>To begin this example, make a local copy of <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/ajax-start.html">ajax-start.html</a> and the four text files — <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse1.txt">verse1.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse2.txt">verse2.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse3.txt">verse3.txt</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse4.txt">verse4.txt</a> — in a new directory on your computer. In this example, we will load a different verse of the poem (which you may well recognize) via XHR when it's selected in the drop-down menu.</p> + </li> + <li> + <p>Just inside the {{htmlelement("script")}} element, add the following code. This stores a reference to the {{htmlelement("select")}} and {{htmlelement("pre")}} elements in variables and defines an {{domxref("GlobalEventHandlers.onchange","onchange")}} event handler function so that when the select's value is changed, its value is passed to an invoked function <code>updateDisplay()</code> as a parameter.</p> + + <pre class="brush: js">var verseChoose = document.querySelector('select'); +var poemDisplay = document.querySelector('pre'); + +verseChoose.onchange = function() { + var verse = verseChoose.value; + updateDisplay(verse); +};</pre> + </li> + <li> + <p>Let's define our <code>updateDisplay()</code> function. First of all, put the following beneath your previous code block — this is the empty shell of the function:</p> + + <pre class="brush: js">function updateDisplay(verse) { + +};</pre> + </li> + <li> + <p>We'll start our function by constructing a relative URL pointing to the text file we want to load, as we'll need it later. The value of the {{htmlelement("select")}} element at any time is the same as the text inside the selected {{htmlelement("option")}} (unless you specify a different value in a value attribute) — so for example "Verse 1". The corresponding verse text file is "verse1.txt", and is in the same directory as the HTML file, therefore just the file name will do.</p> + + <p>However, web servers tend to be case sensitive, and the file name doesn't have a space in it. To convert "Verse 1" to "verse1.txt" we need to convert the V to lower case, remove the space, and add .txt on the end. This can be done with {{jsxref("String.replace", "replace()")}}, {{jsxref("String.toLowerCase", "toLowerCase()")}}, and simple <a href="/en-US/docs/Learn/JavaScript/First_steps/Strings#Concatenating_strings">string concatenation</a>. Add the following lines inside your <code>updateDisplay()</code> function:</p> + + <pre class="brush: js">verse = verse.replace(" ", ""); +verse = verse.toLowerCase(); +var url = verse + '.txt';</pre> + </li> + <li> + <p>To begin creating an XHR request, you need to create a new request object using the {{domxref("XMLHttpRequest.XMLHttpRequest", "XMLHttpRequest()")}} constructor. You can call this object anything you like, but we'll call it <code>request</code> to keep things simple. Add the following below your previous lines:</p> + + <pre class="brush: js">var request = new XMLHttpRequest();</pre> + </li> + <li> + <p>Next, you need to use the {{domxref("XMLHttpRequest.open","open()")}} method to specify what <a href="/en-US/docs/Web/HTTP/Methods">HTTP request method</a> to use to request the resource from the network, and what its URL is. We'll just use the <code><a href="/en-US/docs/Web/HTTP/Methods/GET">GET</a></code> method here and set the URL as our <code>url</code> variable. Add this below your previous line:</p> + + <pre class="brush: js">request.open('GET', url);</pre> + </li> + <li> + <p>Next, we'll set the type of response we are expecting — which is defined by the request's {{domxref("XMLHttpRequest.responseType", "responseType")}} property — as <code>text</code>. This isn't strictly necessary here — XHR returns text by default — but it is a good idea to get into the habit of setting this in case you want to fetch other types of data in the future. Add this next:</p> + + <pre class="brush: js">request.responseType = 'text';</pre> + </li> + <li> + <p>Fetching a resource from the network is an {{glossary("asynchronous")}} operation, meaning that you have to wait for that operation to complete (e.g., the resource is returned from the network) before you can do anything with that response, otherwise, an error will be thrown. XHR allows you to handle this using its {{domxref("XMLHttpRequest.onload", "onload")}} event handler — this is run when the {{event("load")}} event fires (when the response has returned). When this has occurred, the response data will be available in the <code>response</code> property of the XHR request object.</p> + + <p>Add the following below your last addition. You'll see that inside the <code>onload</code> event handler we are setting the <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> of the <code>poemDisplay</code> (the {{htmlelement("pre")}} element) to the value of the {{domxref("XMLHttpRequest.response", "request.response")}} property.</p> + + <pre class="brush: js">request.onload = function() { + poemDisplay.textContent = request.response; +};</pre> + </li> + <li> + <p>The above is all set up for the XHR request — it won't actually run until we tell it to, which is done using the {{domxref("XMLHttpRequest.send","send()")}} method. Add the following below your previous addition to complete the function:</p> + + <pre class="brush: js">request.send();</pre> + </li> + <li> + <p>One problem with the example as it stands is that it won't show any of the poem when it first loads. To fix this, add the following two lines at the bottom of your code (just above the closing <code></script></code> tag) to load verse 1 by default, and make sure the {{htmlelement("select")}} element always shows the correct value:</p> + + <pre class="brush: js">updateDisplay('Verse 1'); +verseChoose.value = 'Verse 1';</pre> + </li> +</ol> + +<h3 id="Serving_your_example_from_a_server">Serving your example from a server</h3> + +<p>Some browsers (including Chrome) will not run XHR requests if you just run the example from a local file. This is because of security restrictions (for more on web security, read <a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">Website security</a>).</p> + +<p>To get around this, we need to test the example by running it through a local web server. To find out how to do this, read <a href="/en-US/docs/Learn/Common_questions/set_up_a_local_testing_server">How do you set up a local testing server?</a></p> + +<h3 id="Fetch">Fetch</h3> + +<p>The Fetch API is basically a modern replacement for XHR; it was introduced in browsers recently to make asynchronous HTTP requests easier to do in JavaScript, both for developers and other APIs that build on top of Fetch.</p> + +<p>Let's convert the last example to use Fetch instead.</p> + +<ol> + <li> + <p>Make a copy of your previous finished example directory. (If you didn't work through the previous exercise, create a new directory and inside it make copies of <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/xhr-basic.html">xhr-basic.html</a> and the four text files — <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse1.txt">verse1.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse2.txt">verse2.txt</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse3.txt">verse3.txt</a>, and <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/verse4.txt">verse4.txt</a>.)</p> + </li> + <li> + <p>Inside the <code>updateDisplay()</code> function, find the XHR code:</p> + + <pre class="brush: js">var request = new XMLHttpRequest(); +request.open('GET', url); +request.responseType = 'text'; + +request.onload = function() { + poemDisplay.textContent = request.response; +}; + +request.send();</pre> + </li> + <li> + <p>Replace all the XHR code with this:</p> + + <pre class="brush: js">fetch(url).then(function(response) { + response.text().then(function(text) { + poemDisplay.textContent = text; + }); +});</pre> + </li> + <li> + <p>Load the example in your browser (running it through a web server) and it should work just the same as the XHR version, provided you are running a modern browser.</p> + </li> +</ol> + +<h4 id="So_what_is_going_on_in_the_Fetch_code">So what is going on in the Fetch code?</h4> + +<p>First of all, we invoke the {{domxref("WorkerOrWindowGlobalScope.fetch()","fetch()")}} method, passing it the URL of the resource we want to fetch. This is the modern equivalent of {{domxref("XMLHttpRequest.open","request.open()")}} in XHR, plus you don't need any equivalent to <code>.send()</code>.</p> + +<p>After that, you can see the {{jsxref("Promise.then",".then()")}} method chained onto the end of <code>fetch()</code> — this method is a part of {{jsxref("Promise","Promises")}}, a modern JavaScript feature for performing asynchronous operations. <code>fetch()</code> returns a <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promise</a>, which resolves to the response sent back from the server — we use <code>.then()</code> to run some follow-up code after the promise resolves, which is the function we've defined inside it. This is the equivalent of the <code>onload</code> event handler in the XHR version.</p> + +<p>This function is automatically given the response from the server as a parameter when the <code>fetch()</code> promise resolves. Inside the function we grab the response and run its {{domxref("Body.text","text()")}} method, which basically returns the response as raw text. This is the equivalent of <code>request.responseType = 'text'</code> in the XHR version.</p> + +<p>You'll see that <code>text()</code> also returns a promise, so we chain another <code>.then()</code> onto it, inside of which we define a function to receive the raw text that the <code>text()</code> promise resolves to.</p> + +<p>Inside the inner promise's function, we do much the same as we did in the XHR version — set the {{htmlelement("pre")}} element's text content to the text value.</p> + +<h3 id="Aside_on_promises">Aside on promises</h3> + +<p>Promises are a bit confusing the first time you meet them, but don't worry too much about this for now. You'll get used to them after a while, especially as you learn more about modern JavaScript APIs — most of the newer ones are heavily based on promises.</p> + +<p>Let's look at the promise structure from above again to see if we can make some more sense of it:</p> + +<pre class="brush: js">fetch(url).then(function(response) { + response.text().then(function(text) { + poemDisplay.textContent = text; + }); +});</pre> + +<p>The first line is saying "fetch the resource located at URL" (<code>fetch(url)</code>) and "then run the specified function when the promise resolves" (<code>.then(function() { ... })</code>). "Resolve" means "finish performing the specified operation at some point in the future". The specified operation, in this case, is to fetch a resource from a specified URL (using an HTTP request), and return the response for us to do something with.</p> + +<p>Effectively, the function passed into <code>then()</code> is a chunk of code that won't run immediately. Instead, it will run at some point in the future when the response has been returned. Note that you could also choose to store your promise in a variable and chain {{jsxref("Promise.then",".then()")}} onto that instead. The code below would do the same thing:</p> + +<pre class="brush: js">var myFetch = fetch(url); + +myFetch.then(function(response) { + response.text().then(function(text) { + poemDisplay.textContent = text; + }); +});</pre> + +<p>Because the <code>fetch()</code> method returns a promise that resolves to the HTTP response, any function you define inside a <code>.then()</code> chained onto the end of it will automatically be given the response as a parameter. You can call the parameter anything you like — the below example would still work:</p> + +<pre class="brush: js">fetch(url).then(function(dogBiscuits) { + dogBiscuits.text().then(function(text) { + poemDisplay.textContent = text; + }); +});</pre> + +<p>But it makes more sense to call the parameter something that describes its contents.</p> + +<p>Now let's focus just on the function:</p> + +<pre class="brush: js">function(response) { + response.text().then(function(text) { + poemDisplay.textContent = text; + }); +}</pre> + +<p>The response object has a method {{domxref("Body.text","text()")}} that takes the raw data contained in the response body and turns it into plain text — the format we want it in. It also returns a promise (which resolves to the resulting text string), so here we use another {{jsxref("Promise.then",".then()")}}, inside of which we define another function that dictates what we want to do with that text string. We are just setting the <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> property of our poem's {{htmlelement("pre")}} element to equal the text string, so this works out pretty simple.</p> + +<p>It is also worth noting that you can directly chain multiple promise blocks (<code>.then()</code> blocks, but there are other types too) onto the end of one another, passing the result of each block to the next block as you travel down the chain. This makes promises very powerful.</p> + +<p>The following block does the same thing as our original example, but is written in a different style:</p> + +<pre class="brush: js">fetch(url).then(function(response) { + return response.text() +}).then(function(text) { + poemDisplay.textContent = text; +});</pre> + +<p>Many developers like this style better, as it is flatter and arguably easier to read for longer promise chains — each subsequent promise comes after the previous one, rather than being inside the previous one (which can get unwieldy). The only other difference is that we've had to include a <code><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">return</a></code> statement in front of <code>response.text()</code>, to get it to pass its result on to the next link in the chain.</p> + +<h3 id="Which_mechanism_should_you_use">Which mechanism should you use?</h3> + +<p>This really depends on what project you are working on. XHR has been around for a long time now and has very good cross-browser support. Fetch and Promises, on the other hand, are a more recent addition to the web platform, although they're supported well across the browser landscape, with the exception of Internet Explorer.</p> + +<p>If you need to support older browsers, then an XHR solution might be preferable. If however you are working on a more progressive project and aren't as worried about older browsers, then Fetch could be a good choice.</p> + +<p>You should really learn both — Fetch will become more popular as Internet Explorer declines in usage (IE is no longer being developed, in favor of Microsoft's new Edge browser), but you might need XHR for a while yet.</p> + +<h2 id="A_more_complex_example">A more complex example</h2> + +<p>To round off the article, we'll look at a slightly more complex example that shows some more interesting uses of Fetch. We have created a sample site called The Can Store — it's a fictional supermarket that only sells canned goods. You can find this <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store/">example live on GitHub</a>, and <a href="https://github.com/mdn/learning-area/tree/master/javascript/apis/fetching-data/can-store">see the source code</a>.</p> + +<p><img alt="A fake ecommerce site showing search options in the left hand column, and product search results in the right hand column." src="https://mdn.mozillademos.org/files/14779/can-store.png" style="display: block; margin: 0 auto;"></p> + +<p>By default, the site displays all the products, but you can use the form controls in the left hand column to filter them by category, or search term, or both.</p> + +<p>There is quite a lot of complex code that deals with filtering the products by category and search terms, manipulating strings so the data displays correctly in the UI, etc. We won't discuss all of it in the article, but you can find extensive comments in the code (see <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-script.js">can-script.js</a>).</p> + +<p>We will however explain the Fetch code.</p> + +<p>The first block that uses Fetch can be found at the start of the JavaScript:</p> + +<pre class="brush: js">fetch('products.json').then(function(response) { + return response.json(); +}).then(function(json) { + products = json; + initialize(); +}).catch(function(err) { + console.log('Fetch problem: ' + err.message); +});</pre> + +<p>The <code>fetch()</code> function returns a <code>promise</code>. If this completes successfully, the function inside the first <code>.then()</code> block contains the <code>response</code> returned from the network.</p> + +<p>Inside this function we run {{domxref("Body.json","json()")}} on the response, not {{domxref("Body.text","text()")}}, as we want to return our response as structured JSON data, not plain text.</p> + +<p>Next, we chain another <code>.then()</code> onto the end of our first one, the success function that contains the <code>json</code> returned from the <code>response.json()</code> promise. We set this to be the value of the products global object, then run <code>initialize()</code>, which starts the process of displaying all the products in the user interface.</p> + +<p>To handle errors, we chain a <code>.catch()</code> block onto the end of the chain. This runs if the promise fails for some reason. Inside it, we include a function that is passed as a parameter, an <code>error</code> object. This <code>error</code> object can be used to report the nature of the error that has occurred, in this case we do it with a simple <code>console.log()</code>.</p> + +<p>However, a complete website would handle this error more gracefully by displaying a message on the user's screen and perhaps offering options to remedy the situation, but we don't need anything more than a simple <code>console.log()</code>.</p> + +<p>You can test the fail case yourself:</p> + +<ol> + <li>Make a local copy of the example files (download and unpack <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-store.zip?raw=true">the can-store ZIP file</a>).</li> + <li>Run the code through a web server (as described above, in {{anch("Serving your example from a server")}}).</li> + <li>Modify the path to the file being fetched, to something like 'produc.json' (make sure it is misspelled).</li> + <li>Now load the index file in your browser (via <code>localhost:8000</code>) and look in your browser developer console. You'll see a message similar to "Network request for products.json failed with response 404: File not found".</li> +</ol> + +<p>The second Fetch block can be found inside the <code>fetchBlob()</code> function:</p> + +<pre class="brush: js">fetch(url).then(function(response) { + return response.blob(); +}).then(function(blob) { + // Convert the blob to an object URL — this is basically an temporary internal URL + // that points to an object stored inside the browser + var objectURL = URL.createObjectURL(blob); + // invoke showProduct + showProduct(objectURL, product); +});</pre> + +<p>This works in much the same way as the previous one, except that instead of using {{domxref("Body.json","json()")}}, we use {{domxref("Body.blob","blob()")}}. In this case we want to return our response as an image file, and the data format we use for that is <a href="/en-US/docs/Web/API/Blob">Blob</a> (the term is an abbreviation of "Binary Large Object" and can basically be used to represent large file-like objects, such as images or video files).</p> + +<p>Once we've successfully received our blob, we create an object URL out of it using {{domxref("URL.createObjectURL()", "createObjectURL()")}}. This returns a temporary internal URL that points to an object referenced inside the browser. These are not very readable, but you can see what one looks like by opening up the Can Store app, Ctrl-/Right-clicking on an image, and selecting the "View image" option (which might vary slightly depending on what browser you are using). The object URL will be visible inside the address bar, and should be something like this:</p> + +<pre>blob:http://localhost:7800/9b75250e-5279-e249-884f-d03eb1fd84f4</pre> + +<h3 id="Challenge_An_XHR_version_of_the_Can_Store">Challenge: An XHR version of the Can Store</h3> + +<p>We'd like you to try converting the Fetch version of the app to use XHR as a useful bit of practice. Take a <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store/can-store.zip?raw=true">copy of the ZIP file</a>, and try modifying the JavaScript as appropriate.</p> + +<p>Some helpful hints:</p> + +<ul> + <li>You might find the {{domxref("XMLHttpRequest")}} reference material useful.</li> + <li>You will basically need to use the same pattern as you saw earlier in the <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/xhr-basic.html">XHR-basic.html</a> example.</li> + <li>You will, however, need to add the error handling we showed you in the Fetch version of the Can Store: + <ul> + <li>The response is found in <code>request.response</code> after the <code>load</code> event has fired, not in a promise <code>then()</code>.</li> + <li>About the best equivalent to Fetch's <code>response.ok</code> in XHR is to check whether {{domxref("XMLHttpRequest.status","request.status")}} is equal to 200, or if {{domxref("XMLHttpRequest.readyState","request.readyState")}} is equal to 4.</li> + <li>The properties for getting the status and status message are the same, but they are found on the <code>request</code> (XHR) object, not the <code>response</code> object.</li> + </ul> + </li> +</ul> + +<div class="note"> +<p><strong>Note</strong>: If you have trouble with this, feel free to check your code against the finished version on GitHub (<a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/fetching-data/can-store-xhr/can-script.js">see the source here</a>, and also <a href="https://mdn.github.io/learning-area/javascript/apis/fetching-data/can-store-xhr/">see it running live</a>).</p> +</div> + +<h2 id="Summary">Summary</h2> + +<p>This article shows how to start working with both XHR and Fetch to fetch data from the server.</p> + +<h2 id="See_also">See also</h2> + +<p>There are however a lot of different subjects discussed in this article, which has only really scratched the surface. For a lot more detail on these subjects, try the following articles:</p> + +<ul> + <li><a href="/en-US/docs/AJAX/Getting_Started">Ajax — Getting started</a></li> + <li><a href="/en-US/docs/Web/API/Fetch_API/Using_Fetch">Using Fetch</a></li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">Promises</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Web/HTTP/Overview">An overview of HTTP</a></li> + <li><a href="/en-US/docs/Learn/Server-side">Server-side website programming</a></li> +</ul> + +<div>{{PreviousMenuNext("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs/Third_party_APIs", "Learn/JavaScript/Client-side_web_APIs")}}</div> + +<div> +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction">Introduction to web APIs</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipulating documents</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Fetching data from the server</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs">Third party APIs</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Drawing graphics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">Video and audio APIs</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">Client-side storage</a></li> +</ul> +</div> diff --git a/files/es/learn/javascript/client-side_web_apis/index.html b/files/es/learn/javascript/client-side_web_apis/index.html new file mode 100644 index 0000000000..731edea2a3 --- /dev/null +++ b/files/es/learn/javascript/client-side_web_apis/index.html @@ -0,0 +1,53 @@ +--- +title: Client-side web APIs +slug: Learn/JavaScript/Client-side_web_APIs +tags: + - API + - Articles + - Beginner + - CodingScripting + - DOM + - Graphics + - JavaScript + - Landing + - Learn + - Media + - Module + - NeedsTranslation + - TopicStub + - WebAPI + - data +translation_of: Learn/JavaScript/Client-side_web_APIs +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Cuando se escribe JavaScript para sitios web o aplicaciones del lado del cliente, no pasará mucho tiempo antes de que comience a usar APIs ("Application Programming Interfaces"). Estas son interfaces para manipular diferentes aspectos del navegador y el sistema operativo sobre el cuál se esta ejecutando, o incluso datos de otros sitios web o servicios. En este módulo, vamos a aprender que son las APIs y cómo utilizar algunas de las API más comunes que encuentran al momento de desarrollar. </p> + +<h2 id="Requisitos">Requisitos</h2> + +<p>Para aprovechar al máximo este módulo, debería haber trabajado con los módulos anteriores de JavaScript (<a href="/en-US/docs/Learn/JavaScript/First_steps">Primeros Pasos</a>, <a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/Building_blocks">Bloques de construcción</a>, y <a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/Objects">Objetos en JavaScript</a>). De todos modos, esos módulos involucran el uso de varias APIs simples, ya que es dificil escribir ejemplos en Javascript del lado del cliente sin dar uso de ellos! Para este tutorial, asumiremos que se tiene conocimiento basico sobre JavaScript y exploraremos las API web mas comunes con un poco más de detalle.</p> + +<p>Conocimiento basico de <a href="/en-US/docs/Learn/HTML">HTML</a> y <a href="/en-US/docs/Learn/CSS">CSS</a> tambien seria util.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si está trabajando en un dispositivo en el que no tiene la capacidad de crear sus propios archivos, puede probar (la mayoría de) los ejemplos de código en un programa de codificación en línea como <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction">Introducción a web APIs</a></dt> + <dd>En primer lugar, comenzaremos observando las API de alto nivel: ¿qué son, cómo funcionan, cómo las utilizan en su código y cómo están estructuradas? También veremos cuáles son las diferentes principales clases de APIs y qué tipo de usos tienen.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipulacion de documentos</a></dt> + <dd>Al escribir páginas web y aplicaciones, una de las cosas más comunes que querrás hacer es manipular los documentos web de alguna manera. Esto generalmente se hace usando el Document Object Model (DOM), un conjunto de APIs para controlar el HTML y la información de sus estilos que hace un uso intensivo del objeto {{domxref("Document")}} . En este artículo, veremos cómo usar el DOM en detalle, junto con algunas otras API que pueden alterar su entorno de maneras interesantes.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Obteniendo data desde el servidor</a></dt> + <dd>Otra tarea frecuente en las en las aplicaciones y los sitios web modernos, es recuperar los datos individuales de un elemento del seridor para actualizar solo una seccion de la pagina sin tener que cargar una pagina web completamente nueva. Este detalle, aparentemente pequeño, ha tenido un gran impacto en el rendimiento y el comportamiento de los sitios, En este artículo, explicaremos el concepto y veremos las tecnologías que hacen esto posible, como {{domxref("XMLHttpRequest")}} y el <a href="/en-US/docs/Web/API/Fetch_API">Fetch API</a>.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs de terceros</a></dt> + <dd>Las APIs que hemos cubierto hasta ahora están integradas en el navegador, pero no todas las APIs lo estan. Muchos grandes sitios web y servicios tales como Google Maps, Twitter, Facebook, PayPal, etc. proporcionan APIs que permiten a los desarrolladores hacer uso de sus datos (p.ej. mostrando tu actividad en twitter dentro de tu blog) o sus servicios (p.ej. mostrar una ubicacion personalizada porGoogle Maps en tu sitio, o usar el inicio de sesión de Facebook para que inicien sesión tus usuarios). Este artículo analiza la diferencia entre las API del navegador y las API de terceros y muestra algunos usos típicos de este último.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Dibujar gráficos</a></dt> + <dd>El navegador contiene algunas herramientas de programación poderosas para gráficos, desde el lenguaje de Gráficos de Vectores Escalables (<a href="/en-US/docs/Web/SVG">SVG</a>), hasta APIs para dibujar elementos HTML {{htmlelement("canvas")}}, (ver <a href="/en-US/docs/Web/API/Canvas_API">El API Canvas</a> y <a href="/en-US/docs/Web/API/WebGL_API">WebGL</a>). Este articulo provee una introducción al Canvas API, y además recursos que te van a permirir aprender más.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs de audio y video</a></dt> + <dd>HTML5 for embedding rich media in documents — {{htmlelement("video")}} and {{htmlelement("audio")}} — which in turn come with their own APIs for controlling playback, seeking, etc. This article shows you how to do common tasks such as creating custom playback controls.</dd> + <dt><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">Almacenamiento del lado del Cliente</a></dt> + <dd>Modernos navegadores web implementan un número de diferente de tecnologías que te permiten almacenar datos relacionados a sitios y recuperarlos cuando sea necesario permitiendote almacenarlos por mucho tiempo, almacenar sitios fuera de linea, y más. Este articulo explica aspectos los principios de como trabaja.</dd> +</dl> diff --git a/files/es/learn/javascript/client-side_web_apis/introducción/index.html b/files/es/learn/javascript/client-side_web_apis/introducción/index.html new file mode 100644 index 0000000000..fc73d4ebc9 --- /dev/null +++ b/files/es/learn/javascript/client-side_web_apis/introducción/index.html @@ -0,0 +1,274 @@ +--- +title: Introducción a las APIs web +slug: Learn/JavaScript/Client-side_web_APIs/Introducción +translation_of: Learn/JavaScript/Client-side_web_APIs/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs")}}</div> + +<p class="summary">En primer lugar empezaremos echando un vistazo a las APIS desde un nivel superior — ¿qué son, cómo funcionan, cómo usarlas en el código, y cómo están estructuradas?. También echaremos un vistazo a cuáles son los principales tipos de APIs, y para qué se usan.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre requisitos:</th> + <td>Conocimientos básicos de informática, principios básicos de <a href="/es/docs/Learn/HTML">HTML</a>, <a href="/es/docs/Learn/CSS">CSS</a> y JavaScript (ver <a href="/es/docs/Learn/JavaScript/First_steps">primeros pasos</a>, <a href="/es/docs/Learn/JavaScript/Building_blocks">bloques de construcción</a>, <a href="/es/docs/Learn/JavaScript/Objects">objetos JavaScript</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarse con las APIs, saber qué pueden hacer y cómo usarlas en tu código.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_son_las_APIs">¿Qué son las APIs?</h2> + +<p>Las Interfaces de Programacion de Aplicaciones (APIs por sus siglas en inglés) son construcciones disponibles en los lenguajes de programación que permiten a los desarrolladores crear funcionalidades complejas de una manera simple. Estas abstraen el código más complejo para proveer una sintaxis más fácil de usar en su lugar.</p> + +<p>Como ejemplo, piensa en el suministro de electricidad de tu casa, apartamento, o cualquier otro edificio. Si quieres usar un electrodoméstico, simplemente lo conectas en un enchufe y funciona. No intentas conectarlo directamente a la fuente de alimentación — hacerlo sería muy ineficiente y, si no eres electricista, dificil y peligroso.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14317/plug-socket.png" style="display: block; height: 472px; margin: 0px auto; width: 700px;"></p> + +<p><em>Fuente de la imagen: <a href="https://www.flickr.com/photos/easy-pics/9518184890/in/photostream/lightbox/">Overloaded plug socket</a> por <a href="https://www.flickr.com/photos/easy-pics/">The Clear Communication People</a>, en Flickr.</em></p> + +<p>De la misma manera, si quisieras programar gráficos 3D, sería mucho más facil hacerlo usando una API escrita en un lenguaje de alto nivel como JavaScript o Python, en lugar de intentar escribir código de bajo nivel (por ejemplo: C o C++) que controle directamente la GPU del equipo u otras funciones gráficas.</p> + +<div class="note"> +<p><strong>Nota</strong>: Consulta también la <a href="/es/docs/Glossary/API">entrada API en el glosario</a> para una descripción más detallada.</p> +</div> + +<h3 id="APIs_en_JavaScript_del_lado_cliente">APIs en JavaScript del lado cliente</h3> + +<p>JavaScript del lado cliente, particularmente, tiene muchas APIs disponibles — estas <span id="result_box" lang="es"><span>no son parte del lenguaje en sí, sino que están construidas sobre el núcleo de este lenguaje de programación, proporcionándote superpoderes adicionales para usar en tu código.</span> <span>Por lo general, se dividen en dos categorías:</span></span></p> + +<ul> + <li><span id="result_box" lang="es"><span><strong>Las APIs de navegador</strong> están integradas en tu navegador web y pueden exponer datos del navegador y del entorno informático circundante y hacer cosas complejas y útiles con él.</span> <span>Por ejemplo, la API de Geolocalización proporciona algunas construcciones simples de JavaScript para obtener datos de ubicación con los que, por ejemplo, trazar tu ubicación en un mapa de Google.</span> Realmente, el navegador está haciendo uso<span> de códigos de bajo nivel complejos en segundo plano (por ejemplo, C++) para comunicarse con el hardware GPS del dispositivo (o lo que esté disponible para determinar los datos de posición), recuperar datos de posición y devolverlos al entorno del navegador para su uso</span> <span>en tu código.</span> <span>Pero una vez más, la API se encarga de abstraer esta complejidad.</span></span></li> + <li><strong>Las APIs de terceros </strong>no están incluídas por defecto en el navegador, y por lo general es necesario obtener el código e información desde algún lugar de la Web. Por ejemplo, <a href="https://dev.twitter.com/overview/documentation">la API de Twitter</a> permite hacer cosas como mostrar tus últimos tweets en un sitio web. Proporciona un conjunto especial de construcciones que puedes usar para consultar el servicio de Twitter y devolver información específica.</li> +</ul> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13508/browser.png" style="display: block; height: 511px; margin: 0px auto; width: 815px;"></p> + +<h3 id="Relacion_entre_JavaScript_APIs_y_otras_herramientas_de_JavaScript">Relacion entre JavaScript, APIs, y otras herramientas de JavaScript</h3> + +<p><span id="result_box" lang="es"><span>Anteriormente hablamos sobre qué son las APIs de JavaScript del lado cliente y cómo se relacionan con este lenguaje.</span> <span>Recapitulemos ahora para dejarlo claro, y veamos también dónde encajan otras herramientas de JavaScript:</span></span></p> + +<ul> + <li>JavaScript — Un lenguaje de scripts de alto nivel incorporado en los navegadores que permite implementar interactividad en páginas web / apps. <span id="result_box" lang="es"><span>Ten en cuenta que JavaScript también está disponible en otros entornos de programación, como <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Node</a>.</span></span></li> + <li>APIs de navegador — Construcciones integradas en el navegador creadas con el lenguaje JavaScript y que permiten implementar funcionalidad mucho más fácilmente.</li> + <li>APIs de terceros — <span id="result_box" lang="es"><span>Construcciones integradas en plataformas de terceros (por ejemplo Twitter, Facebook) que permiten usar algunas de las funcionalidades de esa plataforma en tus páginas web (como por ejemplo mostrar tus últimos Tweets en tu página web).</span></span></li> + <li>Librerías JavaScript — Por lo general uno o más archivos JavaScript que contienen <a href="/es/docs/Learn/JavaScript/Building_blocks/Functions#Custom_functions">funciones personalizadas</a> que puedes añadir a tu página web para acelerar o habilitar la escritura de funcionalidades comunes. Por ejemplo jQuery, Mootools y React.</li> + <li>Frameworks JavaScript — <span id="result_box" lang="es"><span>El siguiente paso a las librerías, los frameworks JavaScript (como Angular y Ember) suelen ser paquetes de HTML, CSS, JavaScript y otras tecnologías que se instalan y luego se usan para escribir una aplicación web completa desde cero.</span> <span>La diferencia clave entre una librería y un framework es la "Inversión del control".</span> <span>Cuando se llama a un método desde una librería, el desarrollador tiene el control.</span> <span>Con un framework el control se invierte: el framework llama al código del desarrollador.</span></span></li> +</ul> + +<h2 id="¿Qué_pueden_hacer_las_APIs"><span class="short_text" id="result_box" lang="es"><span>¿Qué pueden hacer las APIs?</span></span></h2> + +<p><span id="result_box" lang="es"><span>Hay una gran cantidad de APIs disponibles en los navegadores modernos que te permiten hacer una gran variedad de cosas en tu código.</span> <span>Puedes verlo echando un vistazo al</span></span> <a href="https://developer.mozilla.org/es/docs/Web/API">índice de APIs de MDN</a>.</p> + +<h3 id="APIs_de_navegador_más_comunes">APIs de navegador más comunes</h3> + +<p><span id="result_box" lang="es"><span>En particular, las categorías más comunes de APIs de navegador más usadas (y que trataremos con mayor detalle en este módulo) son:</span></span></p> + +<ul> + <li><strong>APIs para manipular documentos</strong> cargados en el navegador. El ejemplo más obvio es la <a href="https://developer.mozilla.org/es/docs/Web/API/Document_Object_Model">API DOM (Document Object Model)</a>, que permite manipular HTML y CSS — crear, eliminar y modificar HTML, aplicar estilos dinámicos a una página, etc. Cada vez que se muestra una ventana emergente en una página, o un nuevo contenido, por ejemplo, es el DOM en acción. Más información sobre este tipo de APIs en <a href="/es/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipulando documentos</a>.</li> + <li><strong>APIs que obtienen datos del servidor,</strong> comunmente usadas para actualizar pequeñas secciones de una página web. Este aparente pequeño detalle tiene un gran impacto en el performance y en el comportamiento de los sitios. — Sí solo necesitas actualizar un Stock de artículos o una lista de tiendas disponibles, al utilizar APIs para obtener datos desde el servidor lo lograrás sin tener que volver a cargar toda la página o aplicación logrando que estas tengan una sensación de rapidez y agilidad. Las APIs hacen esto posible gracias a que incluyen <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest" title="XMLHttpRequest is an API that provides client functionality for transferring data between a client and a server. It provides an easy way to retrieve data from a URL without having to do a full page refresh. This enables a Web page to update just a part of the page without disrupting what the user is doing."><code>XMLHttpRequest</code></a> y la <a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API">Fetch API</a>. Tambièn puede encontrar el termino Ajax que describe esta técnica. Más información sobre este tipo de APIs en <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Fetching data from the server</a>.</li> + <li><strong>Las APIs para dibujar y manipular graficos</strong> ya son soportadas por la mayoría de navegadores. Las más populares son <a href="/en-US/docs/Web/API/Canvas_API">Canvas</a> y <a href="/en-US/docs/Web/API/WebGL_API">WebGL</a>, que permiten actualizar la información de cada uno de los píxeles contenidos en un {{htmlelement("canvas")}} HTML, para crear escenas 2D y 3D. Por ejemplo, se pueden dibujar formas como rectángulos o círculos, importar una imagen en el canvas y aplicarle filtros como sepia o escala de grises usando la API de Canvas, o crear una escena compleja 3D con iluminación y texturas usando WebGL. Estas APIs, a menudo se combinan con apis para crear bucles de animación (como {{domxref("window.requestAnimationFrame()")}}) y otras veces para hacer que se actualicen constantemente escenas de dibujos animados o videojuegos.</li> + <li><strong><a href="https://developer.mozilla.org/en-US/Apps/Fundamentals/Audio_and_video_delivery">APIS de audio y vídeo</a></strong> como {{domxref("HTMLMediaElement")}}, la <a href="/en-US/docs/Web/API/Web_Audio_API">Web Audio API</a>, y <a href="/en-US/docs/Web/API/WebRTC_API">WebRTC</a> te permitirán hacer cosas realmente interesantes con elementos multimedia: crear una interfaz personalizada para los controles de reproducción de audio y vídeo, mostrar pistas de texto con subtítulos junto con el vídeo, capturar vídeo de la cámara web para ser manipulado en un canvas (ver más arriba) o mostrado en el ordenador de otra persona en una videoconferencia, añadir efectos a las pistas de audio (como ganancia, distorsión, retardo, etc).</li> + <li><strong>Las APIs de dispositivos</strong> son básicamente APIs para manipular y recuperar información de dispositivos modernos de hardware de forma que sean útiles para aplicaciones web. Ya hemos hablado de la API de geolocalización, que accede a la información de ubicación del dispositivo, de forma que te pueda localizar en un mapa. Otros ejemplos incluyen indicar al usuario de que una actulización útil está disponible en una aplicación web mediante notificaciones de sistema (ver <a href="/en-US/docs/Web/API/Notifications_API">Notifications API</a>) o la vibración de hardware (ver <a href="/en-US/docs/Web/API/Vibration_API">Vibration API</a>).</li> + <li>Las <strong>APIS de almacenamiento en el lado del cliente</strong> se están popularizando en los navegadores. La habilidad de almacenar información en el lado del cliente es muy útil para hacer aplicaciones que salven su estado entre carga de páginas, e incluso trabajar cuando el dispositivo está fuera de línea. Hay varias opciones disponibles, por ejemplo el almacenamiento en pares de clave/valor con <a href="/en-US/docs/Web/API/Web_Storage_API" style="font-size: 1rem; letter-spacing: -0.00278rem;">Web Storage API</a><span style="font-size: 1rem; letter-spacing: -0.00278rem;">, y una forma más compleja de almacenar datos tabulados mediante la </span><a href="/en-US/docs/Web/API/IndexedDB_API" style="font-size: 1rem; letter-spacing: -0.00278rem;">IndexedDB API</a><span style="font-size: 1rem; letter-spacing: -0.00278rem;">.</span></li> +</ul> + +<h3 id="APIs_populares_de_terceros">APIs populares de terceros</h3> + +<p>Existe una gran variedad de APIs de terceros, algunas de las más populares de las que querrás hacer uso en algún momento son:</p> + +<ul> + <li>La <a href="https://dev.twitter.com/overview/documentation">API de Twitter</a>, que te permite hacer cosas como mostrar tus ultimos tweets en tu sitio web.</li> + <li>La <a href="https://developers.google.com/maps/">API de Google Maps</a> permite hacer todo tipo de cosas con mapas en tus páginas web (incluso hace funcionar Google Maps). Actualmente, existe todo un conjunto de apis que te permiten realizar una gran variedad de tareas, como se puede ver en <a href="https://developers.google.com/maps/documentation/api-picker">Google Maps API Picker</a>.</li> + <li>El <a href="https://developers.facebook.com/docs/">conjunto de APIs de Facebook</a> te permite usar partes del ecosistema de facebook para mejorar tu aplicación, por ejemplo aportando la posiblidad de identificación mediante el login de Facebook, aceptar pagos en la aplicación, desplegar campañas de anuncios para un target concreto, etc.</li> + <li>La <a href="https://developers.google.com/youtube/">YouTube API</a>, te permite integrar videos de Youtube en tu sitio, buscar en Youtube, construir listas de reproducción y más.</li> + <li>La <a href="https://www.twilio.com/">Twilio API</a>, provee de un framework para crear la funcionalidad de llamadas y videollamadas en tus aplicaciones, enviar SMS o MMS y más.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: puedes encontrar información de una gran cantidad de APIs de terceros en el <a href="http://www.programmableweb.com/category/all/apis">Programmable Web API directory</a>.</p> +</div> + +<h2 id="¿Cómo_funcionan_las_APIs">¿Cómo funcionan las APIs?</h2> + +<p>Las distintas APIs de JavaScript funcionan de forma ligeramente diferente, pero generalmente tienen características similares y una forma parecida en cómo trabajan.</p> + +<h3 id="Están_basadas_en_objetos">Están basadas en objetos</h3> + +<p>Las APIs interactúan con tu código usando uno o más <a href="/en-US/docs/Learn/JavaScript/Objects">Objetos JavaScript,</a> que sirven como contenedores para los datos que usa la API (contenidos en las propiedades del objeto), y la funcionalidad que la API provee (contenida en los métodos del objeto).</p> + +<div class="note"> +<p><strong>Nota</strong>: si no estás familiarizado en cómo trabajar con objetos, deberías volver atrás y revisar el módulo de <a href="/en-US/docs/Learn/JavaScript/Objects">objetos JavaScript </a>antes de seguir.</p> +</div> + +<p>Volvamos al ejemplo de la API de Geolocalización, que es una API muy simple que consiste en unos pocos objetos sencillos:</p> + +<ul> + <li>{{domxref("Geolocation")}}, que contiene tres métodos para controlar la recuperación de los datos geográficos.</li> + <li>{{domxref("Position")}}, que representa la posición de un dispositivo en un momento dado — esto contiene un objeto {{domxref("Coordinates")}} que contiene la información de la posición actual, además de una marca de tiempo con el momento exacto.</li> + <li>{{domxref("Coordinates")}}, que contiene una gran cantidad de datos útiles sobre la posición del dispositivo, incluyendo latitud y longitud, altitud, velocidad, dirección de movimiento y más.</li> +</ul> + +<p>¿Cómo interactúan estos objetos? Si miras a nuestro ejemplo <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/maps-example.html">maps-example.html</a> (<a href="http://mdn.github.io/learning-area/javascript/apis/introduction/maps-example.html">ver también en vivo</a>), encontrarás el siguiente código:</p> + +<pre class="brush: js">navigator.geolocation.getCurrentPosition(function(position) { + var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude); + var myOptions = { + zoom: 8, + center: latlng, + mapTypeId: google.maps.MapTypeId.TERRAIN, + disableDefaultUI: true + } + var map = new google.maps.Map(document.querySelector("#map_canvas"), myOptions); +});</pre> + +<div class="note"> +<p><strong>Nota</strong>: cuando cargues por primera vez el ejemplo de arriba, se te mostrará un mensaje preguntando si deseas compartir tu localización con esta aplicación (ver la sección {{anch("They have additional security mechanisms where appropriate")}} que se encuentra más adelante en este artículo). Deberás estar de acuerdo con esto para poder ver tu localización en el mapa. Si aún así sigues sin ver tu localización, tal vez debas establecer los permisos manualmente; lo puedes hacer de varias formas dependiendo del navegador que estés usando; por ejemplo en Firefox debes ir a > <em>Tools</em> > <em>Page Info</em> > <em>Permissions</em>, y cambiar la configuración para <em>Share Location</em>; en Chrome ve a <em>Settings</em> > <em>Privacy</em> > <em>Show advanced settings</em> > <em>Content settings</em> y cambia las opciones para <em>Location</em>.</p> +</div> + +<p>Primero queremos usar el método {{domxref("Geolocation.getCurrentPosition()")}} para retornar la posición actuali de nuestro dispositivo. El objeto {{domxref("Geolocation")}} del navegador es accedido llamando a la propiedad {{domxref("Navigator.geolocation")}}, así que comenzaremos haciendo:</p> + +<pre class="brush: js">navigator.geolocation.getCurrentPosition(function(position) { ... });</pre> + +<p>Lo que es equivalente a hacer algo como:</p> + +<pre class="brush: js">var myGeo = navigator.geolocation; +myGeo.getCurrentPosition(function(position) { ... });</pre> + +<p>Pero podemos usar la sintaxis con punto para concatener nuestros accesos a propiedades/métodos reduciendo el número de líneas que tenemos que escribir.</p> + +<p>El método {{domxref("Geolocation.getCurrentPosition()")}} solamente tiene un parámetroobligatorio, que es una función anónima que se ejecutará cuando se recupere correctamente la ubicación del dispositivo. Esta función tiene un parámetro, que contiene un objeto<span style="font-size: 1rem; letter-spacing: -0.00278rem;"> {{domxref("Position")}} con la representación de los datos de la posición actual.</span></p> + +<div class="note"> +<p><strong>Nota</strong>: una función que es tomada por otra función como argumento es conocida con el nombre de <a href="/en-US/docs/Glossary/Callback_function">callback function</a>.</p> +</div> + +<p>Este patrón de invocar una función solamente cuando una operación ha sido completada es muy común en las APIs de Javascript — asegurando que una operación ha sido completada antes de intentar usar los datos que retorna en otra operación. Estas operaciones se llaman <strong><a href="/en-US/docs/Glossary/Asynchronous">operaciones asíncronas</a></strong>. Puesto que obtener la posición actual del dispositivo recae en un componente externo (el GPS del dispositivo u otro hardware de geolocalización), no podemos asegurar que se haga a tiempo para usar inmediatamente los datos. Por tanto, algo así no funcionará:</p> + +<pre class="brush: js example-bad">var position = navigator.geolocation.getCurrentPosition(); +var myLatitude = position.coords.latitude;</pre> + +<p>Si la primera línea no ha retornado todavía su resultado, la segunda línea lanzará un error puesto que los datos de posición no estarán disponibles. Por esa razón, las APIs que tienen operaciones asíncronas se diseñan para usar<span style="font-size: 1rem; letter-spacing: -0.00278rem;"> {{glossary("callback function")}}s, o el sistema más moderno de </span><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" style="font-size: 1rem; letter-spacing: -0.00278rem;">Promises</a><span style="font-size: 1rem; letter-spacing: -0.00278rem;">, que se ha introducido en ECMAScript 6 y se está usando mucho en las APIs más nuevas.</span></p> + +<p>Vamos a combinar la API de geolocalización con una API de terceros — la API de Google Maps — que se usa para dibujar la localización retornada por <code>getCurrentPosition()</code> en un mapa de Google. Haremos disponible esta API en nuestra página vinculándonos a ella — encontrarás esta línea en el HTML:</p> + +<pre class="brush: html"><script type="text/javascript" src="https://maps.google.com/maps/api/js?key=AIzaSyDDuGt0E5IEGkcE6ZfrKfUtE9Ko_de66pA"></script></pre> + +<p>Para usar la API, primero creamos una instancia del objeto <code>LatLng</code> usando el constructor <code>google.maps.LatLng()</code>, que toma los valores de nuestra {{domxref("Coordinates.latitude")}} y {{domxref("Coordinates.longitude")}} geolocalizada como parámetros:</p> + +<pre class="brush: js">var latlng = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);</pre> + +<p>Este objeto quedará establecido como el valor de la propiedad<span style="font-size: 1rem; letter-spacing: -0.00278rem;"> </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;">center</code><span style="font-size: 1rem; letter-spacing: -0.00278rem;"> de un objeto de opciones que hemos llamado </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;">myOptions</code><span style="font-size: 1rem; letter-spacing: -0.00278rem;">. Entonces crearemos una instancia de objeto para representar nuestro mapa llamando al constructor de </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;">google.maps.Map()</code><span style="font-size: 1rem; letter-spacing: -0.00278rem;">, pasándole sus dos parámetros — una referencia al elemento {{htmlelement("div")}} donde queremos presentar el mapa (con ID </span><code style="font-size: 1rem; letter-spacing: -0.00278rem;">map_canvas</code><span style="font-size: 1rem; letter-spacing: -0.00278rem;">), y el objeto de opciones que acabamos de definir.</span></p> + +<pre class="brush: js">var myOptions = { + zoom: 8, + center: latlng, + mapTypeId: google.maps.MapTypeId.TERRAIN, + disableDefaultUI: true +} + +var map = new google.maps.Map(document.querySelector("#map_canvas"), myOptions);</pre> + +<p>Una vez hecho, veremos dibujado nuestro mapa.</p> + +<p>Este último bloque de código muestra dos patrones habituales que veremos en muchas APIs. Primero, los objetos de las APIs habitualmente disponen de constructores, que son invocados para crear instancias de esos objetos que que habitualmente usaremos en nuestros programas. Segundo, los objetos de las APIs a menudo ofrecen múltiples opciones que pueden ser adaptadas para obtener exactamente lo que queremos en nuestro programa. Los constructores de las APIs habitualmente aceptan un objeto de opciones como parámetro, que es donde se deben establecer dichas opciones.</p> + +<div class="note"> +<p><strong>Nota</strong>: no te preocupes si no entiendes todos los detalles de este ejemplo inmediantamente. Los repasaremos usando APIs de terceros con más detalle en un artículo futuro.</p> +</div> + +<h3 id="Tienen_puntos_de_acceso_reconocibles">Tienen puntos de acceso reconocibles</h3> + +<p>Cuando uses una API, debes estar seguro que conoces dónde están los puntos de acceso para ella. En la API de Geolocalización esto es bastante sencillo — es la propiedad {{domxref("Navigator.geolocation")}}, que retorna el objeto del navegador {{domxref("Geolocation")}} que contiene todos los métodos útiles de geolocalización disponibles en su interior.</p> + +<p>La API del Modelo de Objetos del Navegador (DOM) tiene un punto de acceso todavía más simple — sus características las podemos encontrar colgando del objeto {{domxref("Document")}}, o una instancia de un elemento HTML que queremos modificar de alguna forma, por ejemplo:</p> + +<pre class="brush: js">var em = document.createElement('em'); // crear un nuevo elemento em +var para = document.querySelector('p'); // referencia a un elemento p existente +em.textContent = 'Hello there!'; // dar al em algo de contenido textual +para.appendChild(em); // ubicar el em dentro del párrafo</pre> + +<p>Otras APIs tienen puntos de acceso ligeramente más complejos, que a menudo implican crear un contexto específico para escribir el código de la API. Por ejemplo, el objeto de contexto de la API Canvas se crea obteniendo una referencia al elemento<span style="font-size: 1rem; letter-spacing: -0.00278rem;"> {{htmlelement("canvas")}} en el que quieres dibujar, y a continuación invocando su método {{domxref("HTMLCanvasElement.getContext()")}}:</span></p> + +<pre class="brush: js">var canvas = document.querySelector('canvas'); +var ctx = canvas.getContext('2d');</pre> + +<p>Cualquier cosa que queramos hacerle al canvas, se conseguirá llamando a las propiedades y métodos del objeto de contexto (que es una instancia de {{domxref("CanvasRenderingContext2D")}}), por ejemplo:</p> + +<pre class="brush: js">Ball.prototype.draw = function() { + ctx.beginPath(); + ctx.fillStyle = this.color; + ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); + ctx.fill(); +};</pre> + +<div class="note"> +<p><strong>Nota</strong>: puedes ver este código en acción en nuetro <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/bouncing-balls.html">bouncing balls demo</a> (y también verlo <a href="http://mdn.github.io/learning-area/javascript/apis/introduction/bouncing-balls.html">funcionando</a>).</p> +</div> + +<h3 id="Usan_eventos_para_manejar_cambios_en_su_estado">Usan eventos para manejar cambios en su estado</h3> + +<p>Ya hemos discutido anteriormente los eventos en este curso, en nuestro artículo de <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">Introducción a los eventos</a> — este artículo detalla qué son los eventos del lado del cliente y cómo se usan en el código. Si no estás familiarizado en cómo se trabaja con la API de eventos del lado del cliente, deberías ir a consultar este artículo antes de continuar.</p> + +<p>Algunas APIs web no contienen eventos, pero algunas otras sí contienen un buen número de ellos. Las propiedades para manejarlos, que nos permiten ejecutar funciones cuando los eventos se producen, generalmente se listan en nuestro material de referencia en secciones de "Manejadores de Eventos" separadas. Como ejemplo simple, instancias del objeto <code><a href="/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest</a></code> (cada uno representa una petición HTTP al servidor para recuperar un nuevo recurso de algún tipo) tienen un número de eventos disponibles, por ejemplo el evento <code>load</code> que es disparado cuando una respuesta ha sido retornada satisfactoriamente conteniendo el recurso solicitado, y ahora está disponible.</p> + +<p>El siguiente código aporta un ejemplo simple de cómo se debe usar esto:</p> + + + +<pre class="brush: js">var requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json'; +var request = new XMLHttpRequest(); +request.open('GET', requestURL); +request.responseType = 'json'; +request.send(); + +request.onload = function() { + var superHeroes = request.response; + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + +<div class="note"> +<p><strong>Nota</strong>: puedes ver este código en acción en nuestro ejemplo <a href="https://github.com/mdn/learning-area/blob/master/javascript/apis/introduction/ajax.html">ajax.html</a> (<a href="http://mdn.github.io/learning-area/javascript/apis/introduction/ajax.html">verlo en vivo</a>).</p> +</div> + +<p>Las primeras cinco líneas especifican la licalización del recurso que queremos recuperar, se crea una nueva instancia del objeto con la petición usando el constructor <code>XMLHttpRequest()</code>, se abre una petición HTTP <code>GET</code> para recuperar el recurso especificado, se indica que la respuesta debería ser enviada en formato JSON, y finalmente se envía la petición.</p> + +<p>El manejador <code>onload</code> especifica entonces qué hacer con la respuesta. Ya sabemos que la respuesta será retornada satisfactoriamente y estará disponible tras producirse el evento load (a menos que haya sucedido un error), así que salvamos la respuesta que contiene el código JSON retornado en la variable <code style="font-size: 1rem; letter-spacing: -0.00278rem;">superHeroes</code><span style="font-size: 1rem; letter-spacing: -0.00278rem;">, luego lo pasamos a dos funciones diferentes para un procesado posterior.</span></p> + +<h3 id="Tienen_mecanismos_adicionales_de_seguridad_donde_sea_necesario">Tienen mecanismos adicionales de seguridad donde sea necesario</h3> + +<p>Las características de las WebAPI están sujetas a las mismas consideraciones de seguridad que JavaScript y otras tecnologías web (por ejemplo <a href="/en-US/docs/Web/Security/Same-origin_policy">same-origin policy</a>), pero a veces tienen mecanismos adicionales de seguridad. Por ejemplo, algunas de las WebAPIs más modernas solamente funcionan en páginas servidas mediante HTTPS debido a que transmiten información potencialmente sensible (algunos ejemplos son <a href="/en-US/docs/Web/API/Service_Worker_API">Service Workers</a> y <a href="/en-US/docs/Web/API/Push_API">Push</a>).</p> + +<p>Además, algunas WebAPIs solicitarán permiso al usuario para ser activadas cuando se produzcan las llamadas desde el código. Como ejemplo, habrás observado un cuadro de diálogo como éste al probar nuestro ejemplo anterior de <a href="/en-US/docs/Web/API/Geolocation">Geolocalización</a>:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14313/location-permission.png" style="border-style: solid; border-width: 1px; display: block; height: 188px; margin: 0px auto; width: 413px;"></p> + +<p>La <a href="/en-US/docs/Web/API/Notifications_API">Notifications API</a> solicita los permisos de una forma parecida:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14315/notification-permission.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Estos diálogos solicitando permiso se muestran al usuario por motivos de seguridad — si no estuvieran, los sitios podrían rastrear la localización sin que el usuario lo supiera o bombardearlo con un montón de notificaciones molestas.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En este punto, deberías tener ya una buena idea de los que son las APIs, cómo trabajan y qué puedes hacer con ellas en tu código JavaScript. Seguramente estarás con ganas de comenzar a hacer cosas divertidas con algunas APIs específicas, así que ¡vamos allá! A continuación veremos cómo manipular documentos con el Modelo de Objetos del Documento (DOM).</p> + +<p>{{NextMenu("Learn/JavaScript/Client-side_web_APIs/Manipulating_documents", "Learn/JavaScript/Client-side_web_APIs")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction">Introducción a las APIs web</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents">Manipulando documentos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Fetching_data">Recuperando información del servidor</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Third_party_APIs">APIs de terceros</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Dibujando gráficos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Video_and_audio_APIs">APIs de vídeo y audio</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Client-side_storage">Almacenamiento en el lado del cliente</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/a_first_splash/index.html b/files/es/learn/javascript/first_steps/a_first_splash/index.html new file mode 100644 index 0000000000..1d2f5e2be0 --- /dev/null +++ b/files/es/learn/javascript/first_steps/a_first_splash/index.html @@ -0,0 +1,613 @@ +--- +title: Un primer acercamiento a JavaScript +slug: Learn/JavaScript/First_steps/A_first_splash +tags: + - Aprender + - Artículo + - CodingScripting + - Condicionales + - Funciones + - JavaScript + - Novato + - Objetos + - Operadores + - Variables + - eventos + - 'l10n:priority' +translation_of: Learn/JavaScript/First_steps/A_first_splash +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Ahora que has aprendido algo sobre la teoría de JavaScript y lo que puedes hacer con ella, te daremos un curso intensivo sobre las características básicas de JavaScript a través de un tutorial completamente práctico. Aquí crearás un sencillo juego de "Adivina el número", paso a paso.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, comprensión básica de HTML y CSS, comprensión de lo que es JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Tener un poco de experiencia escribiendo algo de JavaScript, y conseguir al menos una comprensión básica de lo que implica escribir un programa JavaScript.</td> + </tr> + </tbody> +</table> + +<p>No esperes entender todo el código inmediatamente — por ahora sólo queremos presentarte los conceptos de alto nivel, y darte una idea de como funciona JavaScript (y otros lenguajes de programación). ¡Más adelante vas a volver a ver estas características con mucho más detalle!</p> + +<div class="note"> +<p><strong>Nota</strong>: Muchas de las características que vas a ver en JavaScript son las mismas que en otros lenguajes de programación — funciones, bucles, etc. La sintaxis del código es diferente, pero los conceptos siguen siendo básicamente los mismos. La sintaxis del código es diferente, pero los conceptos siguen siendo básicamente los mismos.</p> +</div> + +<h2 id="Pensando_como_un_programador">Pensando como un programador</h2> + +<p>Una de las cosas más difíciles de aprender en programación no es la sintaxis que necesita aprender, sino cómo aplicarla para resolver problemas del mundo real. Debes comenzar a pensar como un programador — esto generalmente implica mirar descripciones de lo que necesita hacer tu programa, determinar qué características de código necesitas para alcanzar esas cosas y cómo hacer que funcionen juntas.</p> + +<p>Esto implica una combinación de trabajo duro, experiencia con la sintaxis de programación y práctica — más un poquito de creatividad. Mientras más programes, más habilidoso serás haciéndolo. No te podemos prometer que vas a desarrollar un "cerebro de programador" en cinco minutos, pero, a lo largo de este curso, te vamos a dar muchas oportunidades de practicar el pensar como un programador.</p> + +<p>Teniendo esto en mente, veamos el ejemplo que vamos a construir en este artículo, y revisemos el proceso general de seccionarlo y dividirlo en tareas tangibles.</p> + +<h2 id="Ejemplo_—_Juego_adivina_el_número">Ejemplo — Juego adivina el número</h2> + +<p>En este artículo vamos a mostrarte cómo construir el juego que puedes ver abajo:</p> + +<div class="hidden"> +<h6 id="Top_hidden_code">Top hidden code</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + +<head> + <meta charset="utf-8"> + <title>Juego adivina el número</title> + <style> + html { + font-family: sans-serif; + } + + body { + width: 50%; + max-width: 800px; + min-width: 480px; + margin: 0 auto; + } + + .lastResult { + color: white; + padding: 3px; + } + </style> +</head> + +<body> + <h1>Juego adivina el número</h1> + <p>Hemos seleccionado un número aleatorio entre 1 y 100. Fíjate si lo puedes adivinar en 10 turnos o menos. Vamos a decirte si tu número es más alto o más bajo.</p> + <div class="form"> <label for="guessField">Adivina el numero: </label><input type="text" id="guessField" class="guessField"> <input type="submit" value="Enviar respuesta" class="guessSubmit"> </div> + <div class="resultParas"> + <p class="guesses"></p> + <p class="lastResult"></p> + <p class="lowOrHi"></p> + </div> +<script> + // Tu código JavaScript va aquí + let randomNumber = Math.floor(Math.random() * 100) + 1; + const guesses = document.querySelector('.guesses'); + const lastResult = document.querySelector('.lastResult'); + const lowOrHi = document.querySelector('.lowOrHi'); + const guessSubmit = document.querySelector('.guessSubmit'); + const guessField = document.querySelector('.guessField'); + let guessCount = 1; + let resetButton; + + function checkGuess() { + let userGuess = Number(guessField.value); + if (guessCount === 1) { + guesses.textContent = 'Intentos anteriores: '; + } + + guesses.textContent += userGuess + ' '; + + if (userGuess === randomNumber) { + lastResult.textContent = '¡Felicidades! ¡Lo adivinaste!'; + lastResult.style.backgroundColor = 'green'; + lowOrHi.textContent = ''; + setGameOver(); + } else if (guessCount === 10) { + lastResult.textContent = '!!!Fin del juego!!!'; + lowOrHi.textContent = ''; + setGameOver(); + } else { + lastResult.textContent = '¡Incorrecto!'; + lastResult.style.backgroundColor = 'red'; + if(userGuess < randomNumber) { + lowOrHi.textContent = '¡El número es muy bajo!' ; + } else if(userGuess > randomNumber) { + lowOrHi.textContent = '¡El número es muy grande!'; + } + } + + guessCount++; + guessField.value = ''; + } + + guessSubmit.addEventListener('click', checkGuess); + + function setGameOver() { + guessField.disabled = true; + guessSubmit.disabled = true; + resetButton = document.createElement('button'); + resetButton.textContent = 'Iniciar nuevo juego'; + document.body.append(resetButton); + resetButton.addEventListener('click', resetGame); + } + + function resetGame() { + guessCount = 1; + const resetParas = document.querySelectorAll('.resultParas p'); + for(let i = 0 ; i < resetParas.length ; i++) { + resetParas[i].textContent = ''; + } + + resetButton.parentNode.removeChild(resetButton); + guessField.disabled = false; + guessSubmit.disabled = false; + guessField.value = ''; + guessField.focus(); + lastResult.style.backgroundColor = 'white'; + randomNumber = Math.floor(Math.random() * 100) + 1; + } +</script> + +</body> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Top_hidden_code', '100%', 320, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Juega un poco — familiarízate con el juego antes de continuar.</p> + +<p>Imaginemos que tu jefe te ha dado el siguiente resumen para crear este juego:</p> + +<blockquote> +<p>Quiero que crees un sencillo juego del tipo "adivina el número". Se debe elegir un número aleatorio entre 1 y 100, luego desafiar al jugador a adivinar el número en 10 intentos. Después de cada intento, debería decirle al jugador si ha acertado o no — y si está equivocado, debería decirle si se ha quedado corto o se ha pasado. También debería decir los números que ya se probaron anteriormente. El juego terminará una vez que el jugador acierte o cuando se acaben los intentos. Cuando el juego termina, se le debe dar al jugador la opción de volver a jugar.</p> +</blockquote> + +<p>Al observar este resumen, lo primero que podemos hacer es comenzar a desglosar el proyecto en tareas simples y realizables, con la mayor mentalidad de programador posible:</p> + +<ol> + <li>Generar un número aleatorio entre 1 y 100.</li> + <li>Registrar el número del intento en el que el jugador se encuentre. Empezando en 1.</li> + <li>Darle al jugador una forma de adivinar cuál es el número.</li> + <li>Una vez que se ha introducido en número, registrarlo en alguna parte para que el jugador pueda ver sus intentos previos.</li> + <li>A continuación, comprobar si el número es correcto.</li> + <li>Si es correcto: + <ol> + <li>Mostrar un mensaje de felicitaciones.</li> + <li>Hacer que el jugador no pueda introducir más intentos (esto arruinaría el juego).</li> + <li>Mostrar un control que permita al jugador volver a empezar el juego.</li> + </ol> + </li> + <li>Si es incorrecto y al jugador todavía le quedan intentos: + <ol> + <li>Decirle al jugador que ha fallado.</li> + <li>Dejar que el jugador lo intente de nuevo.</li> + <li>Incrementa el número de intentos en 1.</li> + </ol> + </li> + <li>Si el jugador falla y no le quedan turnos: + <ol> + <li>Decirle al jugador que el juego se ha terminado.</li> + <li>Hacer que el jugador no pueda introducir más intentos (esto arruinaría el juego).</li> + <li>Mostrar un control que permita al jugador volver a empezar el juego.</li> + </ol> + </li> + <li>Una vez que el juego se reinicia, asegúrate de que la lógica del juego y la IU (interfaz de usuario) se restablezcan por completo, luego vuelve al paso 1.</li> +</ol> + +<p>Veamos cómo podemos trasformar estos pasos en código, construyendo el ejemplo y explorando las características de JavaScript a medida que avanzamos.</p> + +<h3 id="Configuración_inicial">Configuración inicial</h3> + +<p>Para empezar este tutorial, quisiéramos que hicieras una copia local del archivo <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game-start.html">number-guess-guess-game-start.html</a> (<a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/first-splash/number-guessing-game-start.html">en vivo aquí</a>). Ábrelo en tu editor de texto y en tu navegador web. De momento, puedes ver un sencillo encabezado, un párrafo de instrucciones y un espacio para introducir un intento de número, pero no hará nada por ahora.</p> + +<p>El lugar donde agregaremos todo nuestro código es dentro del elemento {{htmlelement("script")}} en la parte inferior del HTML:</p> + +<pre class="brush: html notranslate"><script> + + // Tu JavaScript va aquí + +</script> +</pre> + +<h3 id="Añadiendo_variables_para_guardar_los_datos">Añadiendo variables para guardar los datos</h3> + +<p>Empecemos. En primer lugar, agrega las siguientes líneas dentro de tu elemento {{htmlelement("script")}}:</p> + +<pre class="brush: js notranslate">let randomNumber = Math.floor(Math.random() * 100) + 1; + +const guesses = document.querySelector('.guesses'); +const lastResult = document.querySelector('.lastResult'); +const lowOrHi = document.querySelector('.lowOrHi'); + +const guessSubmit = document.querySelector('.guessSubmit'); +const guessField = document.querySelector('.guessField'); + +let guessCount = 1; +let resetButton;</pre> + +<p>Esta sección del código establece las variables y constantes que necesitamos para almacenar los datos que nuestro programa utilizará. Las variables básicamente son contenedores de valores (como números o cadenas de texto). Creas una variable con la palabra clave <code>let</code> (o <code>var</code>) seguida de un nombre para tu variable (leerás más sobre la diferencia entre las palabras clave en el <a href="/es/docs/Learn/JavaScript/First_steps/Variables#The_difference_between_var_and_let">siguiente artículo</a>). Las constantes se utilizan para almacenar valores que no deseas modificar y se crean con la palabra clave <code>const</code>. En este caso, estamos usando constantes para almacenar referencias a partes de nuestra interfaz de usuario; el texto dentro de algunas de ellas puede cambiar, pero los elementos HTML a los que se hace referencia permanecer iguales.</p> + +<p>Puedes asignar un valor a tu variable o constante con un signo igual (<code>=</code>) seguido del valor que deseas darle.</p> + +<p>En nuestro ejemplo:</p> + +<ul> + <li>A la primera variable — <code>randomNumber</code> — se le asigna un número al azar entre 1 y 100, calculado usando un algoritmo matemático.</li> + <li>Las primeras tres constantes sirven cada una para almacenar una referencia a los párrafos de resultados en nuestro HTML, y se usarán para insertar valores en los párrafos más adelante en el código (observa cómo están dentro de un elemento <code><div></code>, el cual se utiliza para seleccionar los tres más adelante para restablecerlos a sus valores originales, cuando reiniciamos el juego): + <pre class="brush: html notranslate"><div class="resultParas"> + <p class="guesses"></p> + <p class="lastResult"></p> + <p class="lowOrHi"></p> +</div> +</pre> + </li> + <li>Las siguientes dos constantes almacenan referencias a la entrada de texto y al botón "Enviar" del formulario, y se utilizan para controlar las respuestas del jugador más adelante. + <pre class="brush: html notranslate"><label for="guessField">Adivina el número: </label><input type="text" id="guessField" class="guessField"> +<input type="submit" value="Enviar respuesta" class="guessSubmit"></pre> + </li> + <li>Nuestras dos variables finales almacenan un conteo de intentos desde 1 (que se usa para tener un registro de cuántos intentos ha hecho el jugador), y una referencia al botón de reinicio que aún no existe (pero que lo hará más adelante).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Aprenderás mucho más sobre las variables/constantes más adelante en el curso, comenzando con el <a href="https://developer.mozilla.org/en-US/docs/user:chrisdavidmills/variables">artículo siguiente</a>.</p> +</div> + +<h3 id="Funciones">Funciones</h3> + +<p>A continuación, agrega lo siguiente debajo de tu código JavaScript anterior:</p> + +<pre class="brush: js notranslate">function checkGuess() { + alert('Soy un marcador de posición'); +}</pre> + +<p>Las funciones son bloques de código reutilizable que puedes escribir una vez y ejecutar una y otra vez, ahorrando la necesidad de repetir el código todo el tiempo. Son realmente útiles. Hay varias maneras de definir funciones, pero por ahora nos concentraremos en un tipo simple. Aquí hemos definido una función usando la palabra clave <code>function</code>, seguida de un nombre, con paréntesis después de él. Después de eso ponemos dos llaves (<code>{ }</code>). Dentro de las llaves se encuentra todo el código que queremos ejecutar cuando llamamos a la función.</p> + +<p>Cuando queramos ejecutar el código, escribimos el nombre de la función seguido de los paréntesis.</p> + +<p>Probémoslo ahora. Guarda tu código y actualiza la página en tu navegador. Luego, ingresa a la <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">consola JavaScript de las herramientas para desarrolladores</a> e ingresa la siguiente línea:</p> + +<pre class="brush: js notranslate">checkGuess();</pre> + +<p>Después de presionar<kbd>Retorno</kbd>/<kbd>Intro</kbd>, debería aparecer una alerta que dice "<samp>Soy un marcador de posición</samp>"; hemos definido una función en nuestro código que crea una alerta cada vez que la llamamos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Aprenderás mucho más sobre las <a href="/es/docs/Learn/JavaScript/Building_blocks/Functions">funciones más adelante</a> en el curso.</p> +</div> + +<h3 id="Operadores">Operadores</h3> + +<p>Los operadores de JavaScript nos permiten realizar pruebas, hacer cálculos matemáticos, unir cadenas y otras cosas similares.</p> + +<p>Si aún no lo has hecho, guarda tu código, actualiza la página en tu navegador y abre la <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">consola JavaScript de las herramientas para desarrolladores</a>. Luego, podemos intentar escribir los ejemplos que se muestran a continuación — escribe cada una de las columnas de "Ejemplo" exactamente como se muestra, presionando <kbd>Retorno</kbd>/<kbd>Intro</kbd> después de cada una, y ve los resultados que devuelven.</p> + +<p>Primero veamos los operadores aritméticos, por ejemplo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Descripción</th> + <th scope="col">Ejemplo</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+</code></td> + <td>Suma</td> + <td><code>6 + 9</code></td> + </tr> + <tr> + <td><code>-</code></td> + <td>Resta</td> + <td><code>20 - 15</code></td> + </tr> + <tr> + <td><code>*</code></td> + <td>Multiplicación</td> + <td><code>3 * 7</code></td> + </tr> + <tr> + <td><code>/</code></td> + <td>División</td> + <td><code>10 / 5</code></td> + </tr> + </tbody> +</table> + +<p>También puedes usar el operador <code>+</code> para unir cadenas de texto (en programación, esto se llama <em>concatenación</em>). Intenta ingresar las siguientes líneas, una por una:</p> + +<pre class="brush: js notranslate">let name = 'Bingo'; +name; +let hello = ' dice hola!'; +hello; +let greeting = '¡' + name + hello; +greeting;</pre> + +<p>También disponemos de algunos atajos de operadores, llamados <a href="/es/docs/Web/JavaScript/Reference/Operators/Assignment_Operators">operadores de asignación</a> mejorada. Por ejemplo, si quieres simplemente agregar una nueva cadena de texto a una existente y devolver el resultado, puedes hacer esto:</p> + +<pre class="brush: js notranslate">name += ' dice hola!';</pre> + +<p>Esto es equivalente a</p> + +<pre class="brush: js notranslate">name = name + ' dice hola!';</pre> + +<p>Cuando ejecutamos pruebas de verdadero/falso (por ejemplo, dentro de condicionales — consulta {{anch("Conditionals", "abajo")}}) usamos <a href="/es/docs/Web/JavaScript/Reference/Operators/Comparison_Operators">operadores de comparación</a>. Por ejemplo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Descripción</th> + <th scope="col">Ejemplo</th> + </tr> + <tr> + <td><code>===</code></td> + <td>Igualdad estricta (¿es exactamente lo mismo?)</td> + <td> + <pre class="brush: js notranslate"> +5 === 2 + 4 // false +'Chris' === 'Bob' // false +5 === 2 + 3 // true +2 === '2' // false; número versus cadena +</pre> + </td> + </tr> + <tr> + <td><code>!==</code></td> + <td>No igual (¿no es lo mismo?)</td> + <td> + <pre class="brush: js notranslate"> +5 !== 2 + 4 // true +'Chris' !== 'Bob' // true +5 !== 2 + 3 // false +2 !== '2' // true; número versus cadena +</pre> + </td> + </tr> + <tr> + <td><code><</code></td> + <td>Menor que</td> + <td> + <pre class="brush: js notranslate"> +6 < 10 // true +20 < 10 // false</pre> + </td> + </tr> + <tr> + <td><code>></code></td> + <td>Mayor que</td> + <td> + <pre class="brush: js notranslate"> +6 > 10 // false +20 > 10 // true</pre> + </td> + </tr> + </thead> +</table> + +<h3 id="Condicionales">Condicionales</h3> + +<p>Volviendo a nuestra función <code>checkGuess()</code>, creo que es seguro decir que no queremos que simplemente muestre un mensaje de marcador de posición. Queremos que compruebe si la respuesta del jugador es correcta o no, y que responda de manera apropiada.</p> + +<p>En este punto, reemplaza su función <code>checkGuess()</code> actual con esta versión:</p> + +<pre class="brush: js notranslate">function checkGuess() { + let userGuess = Number(guessField.value); + if (guessCount === 1) { + guesses.textContent = 'Intentos anteriores: '; + } + guesses.textContent += userGuess + ' '; + + if (userGuess === randomNumber) { + lastResult.textContent = '¡Felicidades! ¡Lo adivinaste!'; + lastResult.style.backgroundColor = 'green'; + lowOrHi.textContent = ''; + setGameOver(); + } else if (guessCount === 10) { + lastResult.textContent = '!!!Fin del juego!!!'; + setGameOver(); + } else { + lastResult.textContent = '¡Incorrecto!'; + lastResult.style.backgroundColor = 'red'; + if(userGuess < randomNumber) { + lowOrHi.textContent = '¡El número es muy bajo!'; + } else if(userGuess > randomNumber) { + lowOrHi.textContent = '¡El número es muy grande!'; + } + } + + guessCount++; + guessField.value = ''; + guessField.focus(); +}</pre> + +<p>Esto es un montón de código — ¡uf! Repasemos cada sección y expliquemos lo qué hace.</p> + +<ul> + <li>La primera línea (línea 2 arriba) declara una variable llamada <code>userGuess</code> y establece su valor al valor actual ingresado dentro del campo de texto. También ejecutamos este valor a través del constructor <code>Number()</code> integrado, solo para asegurarnos de que el valor definitivamente sea un número.</li> + <li>A continuación, encontramos nuestro primer bloque de código condicional (líneas 3-5 arriba). Un bloque de código condicional te permite ejecutar código de manera selectiva, dependiendo de si una determinada condición es verdadera o no. Se parece un poco a una función, pero no lo es. La forma más simple de bloque condicional comienza con la palabra clave <code>if</code>, luego algunos paréntesis, luego unas llaves. Dentro del paréntesis incluimos una prueba. Si la prueba devuelve <code>true</code>, ejecutamos el código dentro de las llaves. Si no, no lo hacemos y pasamos al siguiente segmento del código. En este caso, la prueba está verificando si la variable <code>guessCount</code> es igual a <code>1</code> (es decir, si este es el primer intento del jugador o no): + <pre class="brush: js notranslate">guessCount === 1</pre> + Si es así, hacemos que el contenido del texto del párrafo de intentos sea igual a "<samp>Intentos previos: </samp>". Si no, no lo hacemos.</li> + <li>La línea 6 agrega el valor actual de <code>userGuess</code> al final del párrafo <code>guesses</code>, más un espacio en blanco para que haya un espacio entre cada intento mostrado.</li> + <li>El siguiente bloque (líneas 8-24 arriba) realiza algunas comprobaciones: + <ul> + <li>El primer <code>if(){ }</code> verifica si la respuesta del jugador es igual al <code>randomNumber</code> establecido al comienzo de nuestro JavaScript. Si es así, el jugador ha adivinado correctamente y ha ganado el juego, por lo tanto mostramos al jugador un mensaje de felicitación con un bonito color verde, borramos el contenido del cuadro de información de intentos <em>Low/High</em> y ejecutamos una función llamada <code>setGameOver()</code>, que examinaremos más adelante.</li> + <li>Ahora hemos encadenado otra prueba al final de la última usando una estructura <code>else if(){ }</code>. Esta comprueba si este intento es el último turno del jugador. Si es así, el programa hace lo mismo que en el bloque anterior, salvo por un mensaje de fin de juego en lugar de un mensaje de felicitación.</li> + <li>El bloque final encadenado al final de este código (el <code>else { }</code>) contiene código que solo se ejecuta si ninguna de las otras dos pruebas devuelve <code>true</code> (es decir, el jugador no acertó, pero todavía le quedan intentos). En este caso le decimos que es incorrecto, luego realizamos otra prueba condicional para verificar si el intento fue más alto o más bajo que la respuesta, mostrando un mensaje adicional según corresponda para decirle si tiene que ir más alto o bajo.</li> + </ul> + </li> + <li>Las últimas tres líneas de la función (líneas 26 a 28 arriba) nos preparan para el siguiente intento. Agregamos 1 a la variable <code>guessCount</code> para que el jugador use su turno (<code>++</code> es una operación de incremento — incrementar en 1), y vaciamos el valor del campo de texto. y enfocándolo de nuevo, listo para ingresar el próximo intento.</li> +</ul> + +<h3 id="Eventos">Eventos</h3> + +<p>A estas alturas, hemos implementado correctamente la función <code>checkGuess()</code>, pero no hará nada porque aún no la hemos llamado. Lo ideal, sería llamarla cuando se presiona el botón "Enviar respuesta", y para hacerlo necesitamos usar un <strong>evento</strong>. Los eventos son cosas que suceden en el navegador — se hace clic en un botón, se carga una página, se reproduce un video, etc. — en respuesta a lo cual podemos ejecutar bloques de código. Las construcciones que escuchan el evento que ocurre se denominan <strong>escuchas de eventos</strong>, y los bloques de código que se ejecutan en respuesta a la activación del evento se denominan <strong>controladores de eventos</strong>.</p> + +<p>Agrega la siguiente línea debajo de tu función <code>checkGuess()</code>:</p> + +<pre class="brush: js notranslate">guessSubmit.addEventListener('click', checkGuess);</pre> + +<p>Aquí estamos agregando un escucha de eventos al botón <code>guessSubmit</code>. Este es un método toma dos valores de entrada (llamados <em>argumentos</em>) — el tipo de evento que queremos escuchar (en este caso, <code>click</code>) como una cadena, y el código que queremos ejecutar cuando ocurra el evento (en este caso la función <code>checkGuess()</code>). Ten en cuenta que no es necesario especificar los paréntesis al escribirlo dentro de {{domxref("EventTarget.addEventListener", "addEventListener()")}}.</p> + +<p>Intenta guardar y actualizar tu código ahora, y tu ejemplo debería funcionar — hasta cierto punto. El único problema ahora es que si adivinas la respuesta correcta o agotas los intentos, el juego se interrumpirá porque aún no hemos definido la función <code>setGameOver()</code> que se supone se debe ejecutar una vez que el juego se acabó. Ahora, agreguemos nuestro código faltante y completemos la funcionalidad de ejemplo.</p> + +<h3 id="Finalizando_la_funcionalidad_del_juego">Finalizando la funcionalidad del juego</h3> + +<p>Agreguemos la función <code>setGameOver()</code> al final de nuestro código y luego repasémoslo. Agrega esto ahora, debajo del resto de su JavaScript:</p> + +<pre class="brush: js notranslate">function setGameOver() { + guessField.disabled = true; + guessSubmit.disabled = true; + resetButton = document.createElement('button'); + resetButton.textContent = 'Iniciar nuevo juego'; + document.body.append(resetButton); + resetButton.addEventListener('click', resetGame); +}</pre> + +<ul> + <li>Las dos primeras líneas deshabilitan el campo de texto y el botón fijando sus propiedades <code>disabled</code> en <code>true</code>. Esto es necesario, porque si no lo hiciéramos, el jugador podría seguir enviando más intentos aunque el juego hubiera terminado, lo cual estropearía las cosas.</li> + <li>Las siguientes tres líneas generan un nuevo elemento {{htmlelement("button")}}, establecen su etiqueta de texto en "Iniciar nuevo juego" y lo añaden al final de nuestro HTML existente.</li> + <li>La última línea establece un escucha de eventos en nuestro nuevo botón para que cuando se haga clic en él, se ejecute una función llamada <code>resetGame()</code>.</li> +</ul> + +<p>¡Ahora también necesitamos definir esta función! Agrega el siguiente código, nuevamente al final de tu JavaScript:</p> + +<pre class="brush: js notranslate">function resetGame() { + guessCount = 1; + + const resetParas = document.querySelectorAll('.resultParas p'); + for (let i = 0 ; i < resetParas.length ; i++) { + resetParas[i].textContent = ''; + } + + resetButton.parentNode.removeChild(resetButton); + + guessField.disabled = false; + guessSubmit.disabled = false; + guessField.value = ''; + guessField.focus(); + + lastResult.style.backgroundColor = 'white'; + + randomNumber = Math.floor(Math.random() * 100) + 1; +}</pre> + +<p>Este bloque de código bastante largo restablece completamente todo a cómo estaba al comienzo del juego, para que el jugador pueda intentarlo de nuevo. Eso:</p> + +<ul> + <li>Vuelve a poner <code>guessCount</code> en 1.</li> + <li>Vacía todo el texto de los párrafos de información. Seleccionamos todos los párrafos dentro de <code><div class="resultParas"></div></code>, luego recorremos cada uno, configurando su <code>textContent</code> en <code>''</code> (una cadena vacía).</li> + <li>Elimina de nuestro código el botón de reinicio.</li> + <li>Habilita los elementos del formulario, vacía y enfoca el campo de texto, listo para ingresar un nuevo intento.</li> + <li>Elimina el color de fondo del párrafo <code>lastResult</code>.</li> + <li>Genera un nuevo número al azar ¡para que no vuelvas a adivinar el mismo número!.</li> +</ul> + +<p><strong>En este punto, deberías tener un juego completamente funcional (simple) — ¡Felicidades!</strong></p> + +<p>Todo lo que resta por hacer en este artículo es hablar sobre algunas otras importantes características del código que ya has visto, aunque es posible que no te hayas dado cuenta.</p> + +<h3 id="Bucles">Bucles</h3> + +<p>Una parte del código anterior que debemos examinar detalladamente es el bucle <a href="/es/docs/Web/JavaScript/Reference/Statements/for">for</a>. Los bucles son un muy importante concepto en programación, estos te permiten seguir ejecutando un fragmento de código una y otra vez, hasta que se cumpla una determinada condición.</p> + +<p>Para empezar, de nuevo ve a tu <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">consola JavaScript de las herramientas para desarrolladores del navegador</a> e introduce lo siguiente:</p> + +<pre class="brush: js notranslate">for (let i = 1 ; i < 21 ; i++) { console.log(i) }</pre> + +<p>¿Que sucedió? Los números <samp>1</samp> a <samp>20</samp> se imprimieron en tu consola. Esto se debió al bucle. Un bucle <code>for</code> toma tres valores (argumentos) de entrada:</p> + +<ol> + <li><strong>Un valor inicial</strong>: En este caso, comenzamos a contar en 1, pero este podría ser cualquier número que desees. También puedes reemplazar la letra <code>i</code> con cualquier nombre que desees, pero por convención se usa <code>i</code> porque es corto y fácil de recordar.</li> + <li><strong>Una condición de salida</strong>: Aquí hemos especificado <code>i < 21</code> — el ciclo continuará hasta que <code>i</code> no sea menor que 21. Cuando <code>i</code> llegue a 21, el bucle ya no se ejecutará.</li> + <li><strong>Un incremento</strong>: Hemos especificado <code>i++</code>, que significa "agrega 1 a i". El ciclo se ejecutará una vez por cada valor de <code>i</code>, hasta que <code>i</code> alcance un valor de 21 (como se explicó anteriormente). En este caso, simplemente imprimimos el valor de <code>i</code> en la consola en cada iteración usando {{domxref("console.log", "console.log()")}}.</li> +</ol> + +<p>Ahora veamos el ciclo en nuestro juego de adivinan el número — lo siguiente está dentro de la función <code>resetGame()</code>:</p> + +<pre class="brush: js notranslate">const resetParas = document.querySelectorAll('.resultParas p'); +for (let i = 0 ; i < resetParas.length ; i++) { + resetParas[i].textContent = ''; +}</pre> + +<p>Este código crea una variable que contiene una lista de todos los párrafos dentro de <code><div class="resultParas"></code> usando el método {{domxref("document.querySelectorAll", "querySelectorAll()")}}, luego recorre cada uno de ellos, eliminando el texto contenido a su paso.</p> + +<h3 id="Una_pequeña_explicación_sobre_objetos.">Una pequeña explicación sobre objetos.</h3> + +<p>Agreguemos una mejora final más antes de entrar en esta explicación. Agrega la siguiente línea justo debajo de la línea <code>let resetButton;</code> cerca de la parte superior de tu JavaScript, luego guarda tu archivo:</p> + +<pre class="brush: js notranslate">guessField.focus();</pre> + +<p>Esta línea usa el método {{domxref("HTMLElement.focus", "focus()")}} para colocar automáticamente el cursor en el campo de texto {{htmlelement("input")}} tan pronto como se cargue la página, lo cual significa que el jugador puede comenzar a escribir su primer intento inmediatamente, sin tener que hacer clic primero en el campo del formulario. Es solo una pequeña adición, pero mejora la experiencia del jugador — brindando al usuario una buena pista visual de lo que tiene que hacer para jugar.</p> + +<p>Analicemos lo que está sucediendo aquí con un poco más de detalle. En JavaScript, todo es un objeto. Un objeto es una colección de funciones relacionadas almacenadas en un solo grupo. Puedes crear tus propios objetos, pero eso es bastante avanzado y no lo cubriremos hasta mucho más adelante en el curso. Por ahora, analizaremos brevemente los objetos integrados que contiene tu navegador, los cuales te permiten hacer muchas cosas útiles.</p> + +<p>En este caso particular, primero creamos una constante <code>guessField</code> que almacena una referencia al campo de texto del formulario en nuestro HTML — la siguiente línea se puede encontrar entre nuestras declaraciones cerca de la parte superior del código:</p> + +<pre class="brush: js notranslate">const guessField = document.querySelector('.guessField');</pre> + +<p>Para obtener esta referencia, usamos el método {{domxref("document.querySelector", "querySelector()")}} del objeto {{domxref("document")}}. <code>querySelector()</code> toma un parámetro — un <a href="/es/docs/Learn/CSS/Introduction_to_CSS/Selectors">selector CSS</a> que selecciona el elemento del que deseas una referencia.</p> + +<p>Debido a que <code>guessField</code> ahora contiene una referencia a un elemento {{htmlelement("input")}}, ahora tiene acceso a varias propiedades (básicamente variables almacenadas dentro de los objetos, algunas de las cuales no les puedes cambiar sus valores) y métodos (básicamente funciones almacenadas dentro de objetos). Un método disponible para elementos <code>input</code> es <code>focus()</code>, por lo que ahora podemos usar esta línea para enfocar el campo de texto:</p> + +<pre class="brush: js notranslate">guessField.focus();</pre> + +<p>Las variables que no contienen referencias a elementos de formulario no dispondrán de método <code>focus()</code>. Por ejemplo, la constante <code>guessCount</code> contiene una referencia a un elemento {{htmlelement("p")}} y la variable <code>guessCount</code> contiene un número.</p> + +<h3 id="Jugando_con_los_objetos_del_navegador">Jugando con los objetos del navegador</h3> + +<p>Juguemos un poco con algunos objetos del navegador.</p> + +<ol> + <li>En primer lugar, abre tu programa en un navegador.</li> + <li>A continuación, abre las <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">herramientas de desarrollo del navegador</a> y asegúrate de que la pestaña de la consola JavaScript esté abierta.</li> + <li>Escribe <code>guessField</code> y la consola te mostrará que la variable contiene un elemento {{htmlelement("input")}}. También notarás que la consola te ayuda completando automáticamente los nombres de los objetos que existen dentro del entorno de ejecución, ¡incluidas tus variables!</li> + <li>Ahora escribe lo siguiente: + <pre class="brush: js notranslate">guessField.value = 'Hola';</pre> + La propiedad <code>value</code> representa el valor actual ingresado en el campo de texto. Verás que al ingresar este comando, ¡hemos cambiado este valor!</li> + <li>Ahora intenta escribir <code>guesses</code> en la consola y presiona Intro. La consola te muestra que la variable contiene un elemento {{htmlelement("p")}}.</li> + <li>Ahora intenta ingresar la siguiente línea: + <pre class="brush: js notranslate">guesses.value</pre> + El navegador devuelve <code>undefined</code>, porque los párrafos no tienen la propiedad <code>value</code>.</li> + <li>Para cambiar el texto dentro de un párrafo, necesitas la propiedad {{domxref("Node.textContent", "textContent")}} en su lugar. Prueba esto: + <pre class="brush: js notranslate">guesses.textContent = '¿Dónde está mi párrafo?';</pre> + </li> + <li>Ahora, solo por diversión. Intenta ingresar las siguientes líneas, una por una: + <pre class="brush: js notranslate">guesses.style.backgroundColor = 'yellow'; +guesses.style.fontSize = '200%'; +guesses.style.padding = '10px'; +guesses.style.boxShadow = '3px 3px 6px black';</pre> + Cada elemento de una página tiene una propiedad <code>style</code>, que a su vez contiene un objeto cuyas propiedades contienen todos los estilos CSS en línea aplicados a ese elemento. Esto nos permite establecer dinámicamente nuevos estilos CSS en elementos utilizando JavaScript.</li> +</ol> + +<h2 id="Terminamos_por_ahora...">Terminamos por ahora...</h2> + +<p>Así que eso es todo para construir el ejemplo. Llegaste al final, ¡bien hecho! Prueba tu código final, o <a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/first-splash/number-guessing-game.html">juega con nuestra versión final aquí</a>. Si no puedes hacer que el ejemplo funcione, compáralo con el <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game.html">código fuente</a>.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_is_JavaScript", "Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_is_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/A_first_splash">Primer contacto con JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_went_wrong">¿Qué salió mal? Solución de problemas de JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Variables">Almacenamiento de la información que necesita — Variables</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Math">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos de cadena útiles</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Arrays">Arreglos</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Silly_story_generator">Evaluación: Generador de historias tontas</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/arrays/index.html b/files/es/learn/javascript/first_steps/arrays/index.html new file mode 100644 index 0000000000..cea00871a7 --- /dev/null +++ b/files/es/learn/javascript/first_steps/arrays/index.html @@ -0,0 +1,665 @@ +--- +title: Arrays +slug: Learn/JavaScript/First_steps/Arrays +translation_of: Learn/JavaScript/First_steps/Arrays +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}</div> + +<h2 id="Arreglos_o_Matrices">Arreglos o Matrices</h2> + +<p class="summary">En este último artículo de este módulo, veremos las matrices — una manera ordenada de almacenar una lista de elementos de datos bajo un solo nombre de variable. Aquí vemos por qué esto es útil, luego exploramos cómo crear una matriz, recuperar, agregar y eliminar elementos almacenados en una matriz, y más.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, una comprensión básica de HTML y CSS, una idea de lo que es JavaScript.</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Para entender qué son las matrices y cómo manipularlas en JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_una_matriz">¿Qué es una matriz?</h2> + +<p>Las matrices se describen como "objetos tipo lista"; básicamente son objetos individuales que contienen múltiples valores almacenados en una lista. Los objetos de matriz pueden almacenarse en variables y tratarse de la misma manera que cualquier otro tipo de valor, la diferencia es que podemos acceder individualmente a cada valor dentro de la lista y hacer cosas útiles y eficientes con la lista, como recorrerlo con un bucle y hacer una misma cosa a cada valor. Tal vez tenemos una serie de productos y sus precios almacenados en una matriz, y queremos recorrerlos e imprimirlos en una factura, sumando todos los precios e imprimiendo el total en la parte inferior.</p> + +<p>Si no tuvieramos matrices, tendríamos que almacenar cada elemento en una variable separada, luego llamar al código que hace la impresión y agregarlo por separado para cada artículo. Esto sería mucho más largo de escribir, menos eficiente y más propenso a errores. si tuviéramos 10 elementos para agregar a la factura, ya sería suficientemente malo, pero ¿ qué pasa con 100 o 1000 artículos? Volveremos a este ejemplo más adelante en el artículo.</p> + +<p>Como en artículos anteriores, aprendamos sobre los aspectos básicos reales de las matrices ingresando algunos ejemplos en una consola de JavaScript. A continuación proporcionamos uno (también puedes <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir en consola</a> en una pestaña o ventana separadas, o usar la <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">consola de desarrollador de navegador</a>, si lo prefieres).</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class','input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + if(document.querySelectorAll('div').length > 1) { + inputForm.focus(); + } + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Creando_una_matriz">Creando una matriz</h3> + +<p>Las matrices se construyen con corchetes, que contiene una lista de elementos separdos por comas.</p> + +<ol> + <li>Digamos que queríamos almacenar una lista de compras en una matriz — haríamos algo como lo siguiente. Ingresa las siguientes líneas en la consola: + <pre class="brush: js">let shopping = ['bread', 'milk', 'cheese', 'hummus', 'noodles']; +shopping;</pre> + </li> + <li>En este caso, cada elemento de la matriz es una cadena, pero ten en cuenta que puedes almacenar cualquier elemento en una matriz — cadena, número, objeto, otra variable, incluso otra matriz. También puedes mezclar y combinar tipos de elementos — no todos tienen que ser números, cadenas, etc. Prueba estos: + <pre class="brush: js">let sequence = [1, 1, 2, 3, 5, 8, 13]; +let random = ['tree', 795, [0, 1, 2]];</pre> + </li> + <li>Intenta creando un par de matrices por tu cuenta, antes de continuar.</li> +</ol> + +<h3 id="Accediendo_y_modificando_elementos_de_la_matriz">Accediendo y modificando elementos de la matriz</h3> + +<p>Puedes entonces acceder a elementos individuales en la matriz mediante la notación de corchetes, del mismo modo que <a href="/en-US/Learn/JavaScript/First_steps/Useful_string_methods#Retrieving_a_specific_string_character">accediste a las letras de una cadena</a>.</p> + +<ol> + <li>Ingresa lo siguiente en tu consola: + <pre class="brush: js">shopping[0]; +// returns "bread"</pre> + </li> + <li>también puedes modificar un elemento en una matriz simplemente dando a un item de la matriz un nuevo valor. Prueba esto: + <pre class="brush: js">shopping[0] = 'tahini'; +shopping; +// shopping will now return [ "tahini", "milk", "cheese", "hummus", "noodles" ]</pre> + + <div class="note"><strong>Nota</strong>: Lo dijimos antes, pero solo como recordatorio — ¡ las computadoras comienzan a contar desde 0!</div> + </li> + <li>Ten en cuenta que una matriz dentro de otra matriz se llama matriz multidimensional. Puedes acceder a los elementos de una matriz que estén dentro de otra, encadenando dos pares de corchetes. Por ejemplo, para acceder a uno de los elementos dentro de la matriz, que a su vez, es el tercer elemento dentro de la matriz <code>random</code> (ver sección anterior), podríamos hacer algo como esto: + <pre class="brush: js">random[2][2];</pre> + </li> + <li>Intenta seguir jugando y haciendo algunas modificaciones más a tus ejemplos de matriz antes de continuar.</li> +</ol> + +<h3 id="Encontrar_la_longitud_de_una_matriz">Encontrar la longitud de una matriz</h3> + +<p>Puedes averiguar la longitud de una matriz (cuántos elementos contiene) exactamente de la misma manera que determinas la longitud (en caracteres) de una cadena— utilizando la propiedad {{jsxref("Array.prototype.length","length")}}. Prueba lo siguiente:</p> + +<pre class="brush: js">sequence.length; +// should return 7</pre> + +<p>Esto tiene otros usos, pero se usa más comunmente para indicarle a un ciclo que continúe hasta que haya recorrido todos los elementos de la matriz. Así por ejemplo:</p> + +<pre class="brush: js">let sequence = [1, 1, 2, 3, 5, 8, 13]; +for (var i = 0; i < sequence.length; i++) { + console.log(sequence[i]); +}</pre> + +<p>Aprenderás acerca de bucles correctamente en un artículo futuro, pero brevemente, éste código dice:</p> + +<ol> + <li>Comienza el bucle en el elemento de la posición 0 en la matriz.</li> + <li>Detén el bucle en el número de item igual a la longitud de la matriz. Esto funcionará para una matriz de cualquier longitid, pero en este caso el ciclo se detendrá en el elemento número 7 (esto es bueno, ya que el último elemento — que queremos que recorra el bucle — es 6.</li> + <li>Para cada elemento, imprime en la consola del navegador con <code><a href="/en-US/docs/Web/API/Console/log">console.log()</a></code>.</li> +</ol> + +<h2 id="Alguno_métodos_de_matriz_útiles">Alguno métodos de matriz útiles</h2> + +<p>En esta sección veremos algunos métodos bastante útiles relacionados con matrices que nos permiten dividir cadenas en elementos de matriz y viceversa, y agregar nuevos elementos en matrices.</p> + +<h3 id="Conversión_entre_matrices_y_cadenas">Conversión entre matrices y cadenas</h3> + +<p>A menudo se te presentarán algunos datos brutos contenidos en una cadena larga y grande, y es posible que desees separar los elementos útiles de una forma más conveniente y luego hacerle cosas, como mostrarlos en una tabla de datos. Para hacer esto, podemos usar el método {{jsxref("String.prototype.split()","split()")}}. En su forma más simple, esto toma un único parámetro, el caracter que quieres separar de la cadena, y devuelve las subcadenas entre el separador como elementos en una matriz.</p> + +<div class="note"> +<p><strong>Nota</strong>: Bien, esto es técnicamente un método de cadena, no un método de matriz, pero lo hemos incluido con las matrices, ya que va bien aquí.</p> +</div> + +<ol> + <li>Vamos a jugar con esto, para ver como funciona. Primero, crea una cadena en tu consola: + <pre class="brush: js">let myData = 'Manchester,London,Liverpool,Birmingham,Leeds,Carlisle';</pre> + </li> + <li>Ahora dividámoslo en cada coma: + <pre class="brush: js">let myArray = myData.split(','); +myArray;</pre> + </li> + <li>Finalmente, intenta encontrar la longitud de tu nueva matriz y recuperar algunos elementos de ella: + <pre class="brush: js">myArray.length; +myArray[0]; // the first item in the array +myArray[1]; // the second item in the array +myArray[myArray.length-1]; // the last item in the array</pre> + </li> + <li>También puedes ir en la dirección opuesta usando el método {{jsxref("Array.prototype.join()","join()")}}. Prueba lo siguiente: + <pre class="brush: js">let myNewString = myArray.join(','); +myNewString;</pre> + </li> + <li>Otra forma de convertir una matriz en cadena es usar el método {{jsxref("Array.prototype.toString()","toString()")}}. <code>toString()</code> es posiblemente más simple que <code>join()</code> ya que no toma un parámetro, pero es más limitado. Con <code>join()</code> puedes especificar diferentes separadores (intenta ejecutar el Paso 4 con un caracter diferente a la coma). + <pre class="brush: js">let dogNames = ['Rocket','Flash','Bella','Slugger']; +dogNames.toString(); //Rocket,Flash,Bella,Slugger</pre> + </li> +</ol> + +<h3 id="Agregar_y_eliminar_elementos_de_la_matriz">Agregar y eliminar elementos de la matriz</h3> + +<p>Todavia no hemos cubierto la posibilidad de agregar y eliminar elementos de la matriz — echemos un vistazo a esto ahora. Usaremos la matriz <code>myArray</code> con la que terminamos en la última sección. Si todavía no has seguido esa sección, primero crea la matriz en tu consola:</p> + +<pre class="brush: js">let myArray = ['Manchester', 'London', 'Liverpool', 'Birmingham', 'Leeds', 'Carlisle'];</pre> + +<p>Antes que nada, para añdir o eliminar un elemento al final de una matriz podemos usar {{jsxref("Array.prototype.push()","push()")}} y {{jsxref("Array.prototype.pop()","pop()")}} respectivamente.</p> + +<ol> + <li>primero usemos <code>push()</code> — nota que necesitas incluir uno o más elementos que desees agregas al final de tu matriz. Prueba esto: + + <pre class="brush: js">myArray.push('Cardiff'); +myArray; +myArray.push('Bradford', 'Brighton'); +myArray; +</pre> + </li> + <li>La nueva longitud de la matriz se devuelve cuando finaliza la llamada al método. Si quisieras almacenar la nueva longitud de matriz en una variable, podrías hacer algo como esto: + <pre class="brush: js">let newLength = myArray.push('Bristol'); +myArray; +newLength;</pre> + </li> + <li>Eliminar el último elemento de una matriz es tan simple como ejecutar <code>pop()</code> en ella. Prueba esto: + <pre class="brush: js">myArray.pop();</pre> + </li> + <li>El elemento que sé eliminó se devuelve cuando se completa la llamada al método. Para guardar este elemento en una variable, puedes hacer lo siguiente: + <pre class="brush: js">let removedItem = myArray.pop(); +myArray; +removedItem;</pre> + </li> +</ol> + +<p>{{jsxref("Array.prototype.unshift()","unshift()")}} y {{jsxref("Array.prototype.shift()","shift()")}} funcionan exactamente igual de <code>push()</code> y <code>pop()</code>, respectivamente, excepto que funcionan al principio de la matriz, no al final.</p> + +<ol> + <li>Primero <code>unshift()</code> — prueba el siguiente comando: + + <pre class="brush: js">myArray.unshift('Edinburgh'); +myArray;</pre> + </li> + <li>Ahora <code>shift()</code>; prueba estos! + <pre class="brush: js">let removedItem = myArray.shift(); +myArray; +removedItem;</pre> + </li> +</ol> + +<h2 id="Aprendizaje_activo_¡Imprimiendo_esos_productos!">Aprendizaje activo: ¡Imprimiendo esos productos!</h2> + +<p>Volvamos al ejemplo que describimos anteriormente — imprima los nombres de los productos y los precios en una factura, luego, sume los precios e imprímelos en la parte inferior. En el ejemplo editable a continuación, hay comentarios que contienen números — cada uno de estos marca un lugar donde debe agregar algo al código. Ellos son los siguientes:</p> + +<ol> + <li>Debajo de <code>// number 1</code> hay un número de cadena, cada una de las cuales contiene un nombre de producto y un precio separados por dos puntos. Nos gustaría que conviertas esto en una matriz y lo almacenamos en una matriz llamda <code>products</code>.</li> + <li>En la misma línea que el comentario <code>// number 2</code> es el comienzo de un ciclo for. En esta línea, actualmente tenemos <code>i <= 0</code>, que es una prueba condicional que hace que el bucle que el <a href="/en-US/Learn/JavaScript/First_steps/A_first_splash#Loops">bucle for</a> se detenga inmediatamente, porque dice "detener cuando <code>i</code> es menor o igual 0", y <code>i</code> comienza en 0. Nos gustaría que reemplazaras esto con una prueba condicional que detenga el ciclo cuando <code>i</code> no sea inferior a la longitud la matriz <code>products</code> .</li> + <li>justo debajo del comentario <code>// number 3</code> queremos que escriba una línea de código que divide el elemento actual de la matriz (<code>nombre:precio</code>) en dos elementos separados, uno que contiene solo el nombre y otros que contienen solo el precio. Si no está seguro de cómo hacerlo, consulte el artículo <a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos de cadenas útiles</a> para obtener ayuda o, mejor aún, consulte la sección {{anch("Converting between strings and arrays")}} de este artículo.</li> + <li>Como parte de la línea de código anterior, también querras convertir el precio de una cadena a un número. Si no pudes recordar como hacerlo, consulta el <a href="/en-US/Learn/JavaScript/First_steps/Strings#Numbers_versus_strings">primer artículo de cadenas</a>.</li> + <li>Hay una variable llamada <code>total</code> que se crea y se le da un valor de 0 en la parte superior del código. Dentro del ciclo (debajo de <code>// number 4</code>) queremos que agregues una línea que añade el precio actual del artículo a ese total en cada iteración del ciclo, de modo que al final del código el total correcto se imprima en la factura. Es posible que necesites un <a href="/en-US/Learn/JavaScript/First_steps/Math#Assignment_operators">operador de asignación</a> para hacer esto.</li> + <li>Queremos que cambies la línea justo de bajo <code>// number 5</code> para que la variable <code>itemText</code> se iguale a "nombre de elemnto actual — $precio de elemento actual", por ejemplo "Zapatos — $23.99" en cada caso, por lo que la ionformación correcta artículo está impreso en la factura. Esto es simplemente una concatenación de cadenas, lo que debería ser familiar para ti.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html"><h2>Live output</h2> + +<div class="output" style="min-height: 150px;"> + +<ul> + +</ul> + +<p></p> + +</div> + +<h2>Editable code</h2> + +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 410px;width: 95%"> +var list = document.querySelector('.output ul'); +var totalBox = document.querySelector('.output p'); +var total = 0; +list.innerHTML = ''; +totalBox.textContent = ''; +// number 1 + 'Underpants:6.99' + 'Socks:5.99' + 'T-shirt:14.99' + 'Trousers:31.99' + 'Shoes:23.99'; + +for (var i = 0; i <= 0; i++) { // number 2 + // number 3 + + // number 4 + + // number 5 + itemText = 0; + + var listItem = document.createElement('li'); + listItem.textContent = itemText; + list.appendChild(listItem); +} + +totalBox.textContent = 'Total: $' + total.toFixed(2); +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar totalBox = document.querySelector(\'.output p\');\nvar total = 0;\nlist.innerHTML = \'\';\ntotalBox.textContent = \'\';\n\nvar products = [\'Underpants:6.99\',\n \'Socks:5.99\',\n \'T-shirt:14.99\',\n \'Trousers:31.99\',\n \'Shoes:23.99\'];\n\nfor(var i = 0; i < products.length; i++) {\n var subArray = products[i].split(\':\');\n var name = subArray[0];\n var price = Number(subArray[1]);\n total += price;\n itemText = name + \' — $\' + price;\n\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n}\n\ntotalBox.textContent = \'Total: $\' + total.toFixed(2);'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> + +<pre class="brush: css">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background-color: #f5f9fa; +}</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', '100%', 730, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Aprendizaje_Activo_Top_5_búsquedas">Aprendizaje Activo: Top 5 búsquedas</h2> + +<p>Un buen uso para los métodos de matriz como {{jsxref("Array.prototype.push()","push()")}} y {{jsxref("Array.prototype.pop()","pop()")}} es cuando estás manteniendo un registro de elementos actualmente activos en una aplicación web. En una escena animada por ejemplo, es posible que tengas una matriz de objetos que representan los gráficos de fondo que se muestran actualmente, y es posible que sólo desees que se muestren 50 a la vez, por razones de rendimiento o desorden. A medida que se crean y agregan nuevos objetos a la matriz, se puede eliminar los más antiguos de la matriz para mantener el número deseado.</p> + +<p>En este ejemplo vamos a mostrar un uso mucho más simple — aquí te daremos un sitio de búsqueda falso, con un cuadro de búsqueda. La idea es que cuando los términos se ingresan en un cuadro de búsqueda, se muetren el top 5 de términos de búsqueda previos en la lista. Cuando el número de términos supera el 5, el último término comienza a borrarse cada vez que agregas un nuevo término a la parte superior, por lo que siempre se muestran los 5 términos anteriores.</p> + +<div class="note"> +<p><strong>Nota</strong>: En una aplicación de búsqueda real, probablemente puedas hacer clic en los términos de búsqueda anteriores para volver a los términos de búsqueda anteriores y ¡se motrarán los resultados de búsqueda reales! Solamente lo mantendremos simple por ahora.</p> +</div> + +<p>Para completar la aplicación necesitamos:</p> + +<ol> + <li>Agregar una línea debajo del comentario <code>// number 1</code> que agrega el valor actual ingresado en la entrada de la búsqueda al inicio de la matriz. Esto se puede recuperar usando <code>searchInput.value</code>.</li> + <li>Agrega una línea debajo del comentario <code>// number 2</code> que elimina el valor actualmente al final de la matriz.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html"><h2>Live output</h2> +<div class="output" style="min-height: 150px;"> + +<input type="text"><button>Search</button> + +<ul> + +</ul> + +</div> + +<h2>Editable code</h2> + +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + + +<textarea id="code" class="playable-code" style="height: 370px; width: 95%"> +var list = document.querySelector('.output ul'); +var searchInput = document.querySelector('.output input'); +var searchBtn = document.querySelector('.output button'); + +list.innerHTML = ''; + +var myHistory = []; + +searchBtn.onclick = function() { + // we will only allow a term to be entered if the search input isn't empty + if (searchInput.value !== '') { + // number 1 + + // empty the list so that we don't display duplicate entries + // the display is regenerated every time a search term is entered. + list.innerHTML = ''; + + // loop through the array, and display all the search terms in the list + for (var i = 0; i < myHistory.length; i++) { + itemText = myHistory[i]; + var listItem = document.createElement('li'); + listItem.textContent = itemText; + list.appendChild(listItem); + } + + // If the array length is 5 or more, remove the oldest search term + if (myHistory.length >= 5) { + // number 2 + + } + + // empty the search input and focus it, ready for the next term to be entered + searchInput.value = ''; + searchInput.focus(); + } +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div></pre> + +<pre class="brush: css">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nvar searchInput = document.querySelector(\'.output input\');\nvar searchBtn = document.querySelector(\'.output button\');\n\nlist.innerHTML = \'\';\n\nvar myHistory= [];\n\nsearchBtn.onclick = function() {\n if(searchInput.value !== \'\') {\n myHistory.unshift(searchInput.value);\n\n list.innerHTML = \'\';\n\n for(var i = 0; i < myHistory.length; i++) {\n itemText = myHistory[i];\n var listItem = document.createElement(\'li\');\n listItem.textContent = itemText;\n list.appendChild(listItem);\n }\n\n if(myHistory.length >= 5) {\n myHistory.pop();\n }\n\n searchInput.value = \'\';\n searchInput.focus();\n }\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', '100%', 700, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Después de leer este artículo, estamos seguros de que estaras de acuerdo en que las matrices parecen bastante útiles; las verás aparecer en todas partes en JavaScript, a menudo en asociación con bucles para hacer una misma cosa con cada elemento de la matriz. Te enseñaremos todos los aspectos básicos útiles que hay que conocer sobre los bucles en el siguiente módulo, pero por ahora debes darte un aplauso y tomarte un merecido descanso; ¡has trabajado en todos los artículos de este módulo!</p> + +<p>Lo único que queda por hacer es trabajar a través de la evaluación de este módulo, que te pondrá a prueba tu comprensión de los de los artículos anteriores.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Indexed_collections">Indexed collections</a> — an advanced level guide to arrays and their cousins, typed arrays.</li> + <li>{{jsxref("Array")}} — the <code>Array</code> object reference page — for a detailed reference guide to the features discussed in this page, and many more.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps/Silly_story_generator", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Qu%C3%A9_es_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/A_first_splash">Un primer acercamiento a JavaScript</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/What_went_wrong">¿Qué salió mal? Troubleshooting JavaScript</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Variables">Guardando la información que necesitas— Variables</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Matem%C3%A1ticas">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos útiles para el manejo de cadenas</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Arrays">Arreglos</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Silly_story_generator" rel="nofollow">Evaluaciones: Generador de historias absurdas</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/generador_de_historias_absurdas/index.html b/files/es/learn/javascript/first_steps/generador_de_historias_absurdas/index.html new file mode 100644 index 0000000000..58bb8e688a --- /dev/null +++ b/files/es/learn/javascript/first_steps/generador_de_historias_absurdas/index.html @@ -0,0 +1,147 @@ +--- +title: Generador de historias absurdas +slug: Learn/JavaScript/First_steps/Generador_de_historias_absurdas +tags: + - Arreglos + - Cadenas + - JavaScript + - Numeros + - Principiante +translation_of: Learn/JavaScript/First_steps/Silly_story_generator +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary"></p> + +<p class="summary">En esta evaluación, deberás tomar parte del conocimiento que has aprendido en los artículos de este módulo y aplicarlo a la creación de una aplicación divertida que genere historias aleatorias. ¡Que te diviertas!</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Antes de intentar esta evaluación, deberías haber revisado todos los artículos de este módulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Probar la comprensión de los fundamentos de JavaScript, como variables, números, operadores, cadenas y matrices</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Para iniciar esta evaluación, debe:</p> + +<ul> + <li>Vaya y <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/index.html">tome el archivo HTML</a> para el ejemplo y guarde una copia local de este como <code>index.html</code> en un directorio nuevo en algún lugar de su computadora. Esto también tiene el CSS para estilizar el ejemplo que contiene.</li> + <li>Vaya a la <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/assessment-start/raw-text.txt">página que contiene el texto sin procesar</a> y manténgalo abierto en una pestaña separada del navegador en algún lugar. Lo necesitarás más tarde.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Alternativamente, puede usar un sitio como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> o <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> para hacer su evaluación. Puede pegar el HTML, CSS y JavaScript en uno de estos editores en línea. Si el editor en línea que está utilizando no tiene un panel de JavaScript separado, no dude en colocarlo en línea en un elemento <code><script></code> dentro de la página HTML.</p> +</div> + +<h2 id="Resumen_del_proyecto">Resumen del proyecto</h2> + +<p>Se le han proporcionado algunos HTML / CSS en bruto y algunas cadenas de texto y funciones de JavaScript; necesita escribir el JavaScript necesario para convertir esto en un programa de trabajo, que hace lo siguiente:</p> + +<ul> + <li>Genera una historia tonta cuando se presiona el botón "Generar historia aleatoria".</li> + <li>Reemplaza el nombre predeterminado "Bob" en la historia con un nombre personalizado, solo si se ingresa un nombre personalizado en el campo de texto "Ingresar nombre personalizado" antes de presionar el botón Generar.</li> + <li>Convierte las cantidades y unidades de peso y temperatura predeterminadas de los EE. UU. En la historia en equivalentes del Reino Unido del botón de opción del Reino Unido, antes de presionar el botón de generar.</li> + <li>Generará otra historia tonta al azar si presionas el botón otra vez (y otra vez ...)</li> +</ul> + +<p>La siguiente captura de pantalla muestra un ejemplo de lo que debería producir el programa terminado:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/16178/Screen_Shot_2018-09-19_at_10.01.38_AM.png" style="border-style: solid; border-width: 1px; display: block; height: 404px; margin: 0px auto; width: 500px;"></p> + +<p>Para darle más idea, eche un vistazo al ejemplo final (¡no mire el código fuente!)</p> + +<h2 id="Etapas_para_completar">Etapas para completar</h2> + +<p>En las siguientes secciones se describe lo que hay que hacer.</p> + +<p>Configuración básica:</p> + +<ol> + <li>Crear un nuevo archivo llamado <code>main.js</code>, en el mismo directorio que tu archivo <code>index.html</code>.</li> + <li>Aplicar el archivo JavaScript externo a tu HTML insertando un elemento {{htmlelement("script")}} en tu HTML haciendo referencia a <code>main.js</code>. Póngalo justo antes de la etiquette de cierra <code></body></code>.</li> +</ol> + +<p>Variables y funciones iniciales:</p> + +<ol> + <li>en el archivo de texto sin procesar, copia todo el código bajo el encabezado "1. COMPLETE VARIABLE AND FUNCTION DEFINITIONS" y pégalo en la parte superior del archivo main.js. Esto te dará tres variables que almacenan las referencias al campo de texto "Enter custom name" (<code>customName</code>), el botón "Generate random story" (<code>randomize</code>), y el elemento {{htmlelement("p")}} al fondo del cuerpo HTML en el que la historia será copiada en (<code>story</code>), respectivamente. Además, obtendrás una funcion llamada <code>randomValueFromArray()</code> que toma un array, y devuelve uno de los items guardados dentro del array al azar.</li> + <li>Ahora observa la segunda sección del archivo de texto sin procesar — "2. RAW TEXT STRINGS". Esta contiene cadenas de texto que actuarán como entrada en nuestro programa. Nos gustaría que mantengas estas variables internas dentro del archivo <code>main.js</code>: + <ol> + <li>Almacena la primera, la más larga, cadena de texto dentro de una variable llamada <code>storyText</code>.</li> + <li>Almacena el primer conjunto de tres cadenas dentro de un array llamado <code>insertX</code>.</li> + <li>Almacena el segundo conjunto de tres cadenas dentro de un array llamado <code>insertY</code>.</li> + <li>Almacena el tercer conjunto de tres cadenas dentro de un array llamado <code>insertZ</code>.</li> + </ol> + </li> +</ol> + +<p>Colocar el controlador de evento y la función incompleta:</p> + +<ol> + <li>Ahora regresa al archivo de texto sin procesar.</li> + <li>Copia el código encontrado bajo el encabezado "3. EVENT LISTENER AND PARTIAL FUNCTION DEFINITION" y pégalo al fondo de tu archivo <code>main.js</code> . Esto: + <ul> + <li>Añade un detector de eventos a la variable <code>randomize</code>, de manera que cuando al botón que esta representa se le haya dado un click, la función <code>result()</code> funcione.</li> + <li>Añade una definición de la función parcialmente completada <code>result()</code> a tu código. Por el resto de la evaluación, deberás llenar en líneas dentro de esta función para completarla y hacer que trabaje adecuadamente.</li> + </ul> + </li> +</ol> + +<p>Completando la función <code>result()</code>:</p> + +<ol> + <li>Crear una nueva variable llamada <code>newStory</code>, y establezca su valor igual a <code>storyText</code>. Esto es necesario para que podamos crear una nueva historia aleatoria cada vez que se presiona el botón y se ejecuta la función. Si hiciéramos cambios directamente en <code>storyText</code>, solo podríamos generar una nueva historia una vez.</li> + <li>Crear tres nuevas variables llamadas <code>xItem</code>, <code>yItem</code>, y <code>zItem</code>, y tienes que igualar cada variable llamando a <code>randomValueFromArray()</code> en sus tres matrices (el resultado en cada caso será un elemento aleatorio de cada matriz en la que se llama). Por ejemplo, puede llamar a la función y hacer que devuelva una cadena aleatoria de <code>insertX</code> escribiendo <code>randomValueFromArray(insertX)</code>.</li> + <li>A continuación, queremos reemplazar los tres marcadores de posición en la cadena <code>newStory</code> — <code>:insertx:</code>, <code>:inserty:</code>, y <code>:insertz:</code> — con las cadenas almacenadas en <code>xItem</code>, <code>yItem</code>, y <code>zItem</code>. Hay un método de string en particular que lo ayudará aquí: en cada caso, haga que la llamada al método sea igual a <code>newStory</code> de modo que cada vez que se llame, <code>newStory</code> se iguale a sí mismo, pero con sustituciones. Entonces, cada vez que se presiona el botón, estos marcadores de posición se reemplazan con una cadena absurda aleatoria. Como sugerencia adicional, el método en cuestión solo reemplaza la primera instancia de la subcadena que encuentra, por lo que es posible que deba realizar una de las llamadas dos veces.</li> + <li>Dentro del primer bloque <code>if</code>, agregue otra llamada al método de reemplazo de cadena para reemplazar el nombre 'Bob' que se encuentra en la cadena <code>newStory</code> con la variable de <code>name</code>. En este bloque estamos diciendo "Si se ingresó un valor en la entrada de texto <code>customName</code> reemplace a Bob en la historia con ese nombre personalizado."</li> + <li>Dentro del segundo bloque <code>if</code>, se esta verificando si se ha seleccionado el botón de opción <code>uk</code> Si es así, queremos convertir los valores de peso y temperatura en la historia de libras and Fahrenheit a stones and grados centígrados. Lo que debe hacer es lo siguiente: + <ol> + <li>Busque las fórmulas para convertir libras a stone, and Fahrenheit en grados centígrados.</li> + <li>Dentro de la línea que define la variable de <code>weight</code>, reemplace 300 con un cálculo que convierta 300 libras en stones. Concatenar <code>'stone'</code> al final del resultado de la llamada <code>Math.round()</code>.</li> + <li>Al lado de la línea que define la variable de <code>temperature</code>, reemplace 94 con un cálculo que convierta 94 Fahrenheit en centígrados. Concatenar <code>'centigrade'</code> al final del resultado de la llamada <code>Math.round()</code>.</li> + <li>Justo debajo de las dos definiciones de variables, agregue dos líneas de reemplazo de cadena más que reemplacen '94 fahrenheit 'con el contenido de la variable de <code>temperature</code>, y '300 libras' con el contenido de la variable de <code>weight</code>.</li> + </ol> + </li> + <li>Finalmente, en la penúltima línea de la función, haga que la propiedad <code>textContent</code> de la variable de la <code>story</code> (que hace referencia al párrafo) sea igual a <code>newStory</code>.</li> +</ol> + +<h2 id="Claves_y_pistas">Claves y pistas</h2> + +<ul> + <li>No necesitas modificar el HTML, salvo para incrustar el JavaScript a tu HTML.</li> + <li>Si no estás seguro si el JavaScript está siendo aplicado adecuadamente a tu HTML, intenta remover temporalmente todo el codigo del archivo JavaScript, agregar una instruccion simple que sabes que tendrá un efecto obvio, luego guarda y actualiza. El siguiente ejemplo cambia el fondo de {{htmlelement("html")}} - así la ventana se verá completamente roja si el JavaScript está siendo aplicado adecuadamente.: + <pre class="brush: js notranslate">document.querySelector('html').style.backgroundColor = 'red';</pre> + </li> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round">Math.round()</a> es un método JavaScript integrado que simplemente redondea el resultado de un cálculo al número entero más cercano.</li> + <li>Hay tres casos de cadenas que deben reemplazarse. Puede repetir el método <code>replace()</code> varias veces o puede utilizar expresiones regulares. Por ejemplo, <code>let text = 'I am the biggest lover, I love my love'; text.replace(/love/g,'like');</code> Reemplazará todas las instancias de 'love' a 'like'. Recuerde, las cuerdas son inmutables.</li> +</ul> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Si está siguiendo esta evaluación como parte de un curso organizado, debería poder entregar su trabajo a su profesor/mentor para que lo califique. Si está aprendiendo por ti mismo, puede obtener la guía de calificación con bastante facilidad preguntando en el hilo de <a href="https://discourse.mozilla.org/t/silly-story-generator-assessment/24686">discussion thread for this exercise</a>, o en el canal de IRC <a href="irc://irc.mozilla.org/mdn">#mdn</a> en <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Pruebe el ejercicio primero: ¡no se gana nada haciendo trampa!</p> + +<p>{{PreviousMenu("Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Qu%C3%A9_es_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/A_first_splash">Un primer acercamiento a JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_went_wrong">What went wrong? Corrigiendo JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Variables">Almacenando la información que necesitas - Variables</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Matem%C3%A1ticas">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Strings">Manejando el texto - cadenas en JavaScript</a></li> + <li><a href="/es/docs/Glossary/Arreglos">Métodos útiles con cadenas</a></li> + <li><a href="/es/docs/Glossary/Arreglos">Arreglos (matrices)</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Silly_story_generator">Evaluación: Generador de hisorias alocadas</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/index.html b/files/es/learn/javascript/first_steps/index.html new file mode 100644 index 0000000000..9a1211fc54 --- /dev/null +++ b/files/es/learn/javascript/first_steps/index.html @@ -0,0 +1,88 @@ +--- +title: Primeros pasos con JavaScript +slug: Learn/JavaScript/First_steps +tags: + - Arrays + - Arreglos + - Artículo + - Cadenas + - CodingScripting + - Evaluación + - Guide + - Guía + - JavaScript + - Landing + - Matemáticas + - Numeros + - Operadores + - Principiante + - Rangos + - Series + - TopicStub + - Variables + - 'l10n:priority' + - modulo +translation_of: Learn/JavaScript/First_steps +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">En nuestro primer módulo de JavaScript, primero respondemos algunas preguntas fundamentales como "¿qué es JavaScript?", "¿cómo se ve?" y "¿qué puede hacer?", antes de pasar avanzar en la guía por tu primera experiencia práctica de escribir JavaScript. Después de eso, explicaremos en detalle algunos bloques de construcción clave, tal como variables, cadenas, números y arreglos.</p> + +<div class="in-page-callout webdev"> +<h3 id="¿Quieres_transformarte_en_un_desarrollador_de_la_interfaz_de_usuario_web">¿Quieres transformarte en un desarrollador de la interfaz de usuario web?</h3> + +<p>Se elaboró un curso que incluye toda la información esencial que necesitas para alcanzar tu objetivo.</p> + +<p><a class="cta primary" href="/docs/Learn/Front-end_web_developer">Empieza aquí</a></p> +</div> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Antes de comenzar este módulo, no necesitas ningún conocimiento previo de JavaScript, pero debes estar familiarizado con HTML y CSS. Es recomendable trabajar con los siguientes módulos antes de comenzar con JavaScript:</p> + +<ul> + <li>{{web.link("/es/docs/Learn/Getting_started_with_the_web", "Introducción a la Web")}} (que incluye una {{web.link("/es/docs/Learn/Getting_started_with_the_web/JavaScript_basics", "introducción básica a JavaScript")}}).</li> + <li>{{web.link("/es/docs/Learn/HTML/Introduction_to_HTML", "Introducción a HTML")}}</li> + <li>{{web.link("/es/docs/Learn/CSS/Introduction_to_CSS", "Introducción a CSS")}}.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Si estás trabajando en una computadora, tableta u otro dispositivo en el que no puedes crear tus propios archivos, puedes probar (la mayoría de) los ejemplos de código en un programa de codificación en línea como <a href="http://jsbin.com/">JSBin</a> o <a href="https://glitch.com/">Glitch</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/Que_es_JavaScript", "¿Qué es JavaScript?")}}</dt> + <dd>¡Bienvenido al curso de JavaScript para principiantes de MDN!, En este primer artículo, analizaremos JavaScript desde un alto nivel, respondiendo preguntas como "¿qué es?", y "¿qué hace?", asegurándote de que te sientas cómodo con la intención de JavaScript.</dd> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/A_first_splash", "Una primera introducción a JavaScript")}}</dt> + <dd>Ahora que has aprendido algo sobre la teoría de JavaScript y lo que puedes hacer con él, te daremos un curso intensivo sobre las características básicas de JavaScript a través de un tutorial completamente práctico. Aquí, te llevaremos paso a paso en la creación de un sencillo juego de "Adivina el número".</dd> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/What_went_wrong", "¿Qué salió mal? — Solución de problemas de JavaScript")}}</dt> + <dd>Cuando construiste el juego "Adivina el número" en el artículo anterior, es posible que hayas descubierto que no funcionó. Tranquilo — este artículo tiene como objetivo evitar tu calvicie prematura al jalarte los pelos por este tipo de problemas proporcionándote algunos sencillos consejos sobre cómo encontrar y corregir errores en los programas JavaScript.</dd> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/Variables", "Almacenar la información que necesitas — Variables")}}</dt> + <dd>Después de leer los últimos artículos, deberías saber qué es JavaScript, qué puede hacer por ti, cómo usarlo junto con otras tecnologías web y cómo se ven sus características principales desde un alto nivel. En este artículo llegaremos a los conceptos básicos reales, y veremos cómo trabajar con los bloques de construcción más básicos de JavaScript — Variables.</dd> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/Math", "Matemáticas básicas en JavaScript — números y operadores")}}</dt> + <dd>En este punto del curso, explicaremos las matemáticas en JavaScript — cómo podemos combinar operadores y otras características para manipular con éxito los números para cumplir nuestras ofertas.</dd> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/Strings", "Manejo de texto — cadenas en JavaScript")}}</dt> + <dd>A continuación, centraremos nuestra atención en las cadenas (<code>strings</code>) — así es como se llaman los fragmentos de texto en programación. En este artículo, veremos todas las cosas comunes que realmente debes saber sobre las cadenas al aprender JavaScript, como crear cadenas, escapar las comillas en una cadena y unirlas.</dd> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/Useful_string_methods", "Útiles métodos de cadena")}}</dt> + <dd>Ahora que hemos visto los conceptos básicos de las cadenas, avancemos un poco y comencemos a pensar en las operaciones útiles que podemos hacer en las cadenas con métodos integrados, como encontrar la longitud del texto en una cadena, unir y dividir cadenas, sustituir un caracter por otro en una cadena, y más.</dd> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/Arrays", "Arreglos")}}</dt> + <dd>En el artículo final de este módulo, veremos los arreglos — una forma ordenada de almacenar una lista de elementos de datos con un solo nombre de variable. Aquí vemos por qué esto es útil, luego exploramos cómo crear un arreglo, recuperar, agregar y eliminar elementos almacenados en un arreglo, y más.</dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<p>La siguiente evaluación pondrá a prueba tu comprensión de los conceptos básicos de JavaScript cubiertos en las guías anteriores.</p> + +<dl> + <dt>{{web.link("/es/docs/Learn/JavaScript/First_steps/Silly_story_generator", "Generador de historias absurdas")}}</dt> + <dd>En esta evaluación, se te asignará la tarea de tomar algunos de los conocimientos adquiridos en los artículos de este módulo y aplicarlos para crear una divertida aplicación que genere historias absurdas al azar. ¡Que te diviertas!</dd> +</dl> + +<h2 id="Ve_también">Ve también</h2> + +<dl> + <dt><a href="https://learnjavascript.online/">Aprende JavaScript</a></dt> + <dd>Un excelente recurso para los aspirantes a desarrolladores web — aprende JavaScript en un entorno interactivo, con lecciones breves y pruebas interactivas, guiado por una evaluación automatizada. Las primeras 40 lecciones son gratuitas y el curso completo está disponible por un pequeño pago único.</dd> +</dl> diff --git a/files/es/learn/javascript/first_steps/matemáticas/index.html b/files/es/learn/javascript/first_steps/matemáticas/index.html new file mode 100644 index 0000000000..d9117ed211 --- /dev/null +++ b/files/es/learn/javascript/first_steps/matemáticas/index.html @@ -0,0 +1,443 @@ +--- +title: Matemáticas básicas en JavaScript — números y operadores +slug: Learn/JavaScript/First_steps/Matemáticas +tags: + - Aprender + - Artículo + - Guía + - JavaScript + - Matemáticas + - Math + - Novato + - Operadores + - Principiante + - incremento + - 'l10n:priority' + - modulo +translation_of: Learn/JavaScript/First_steps/Math +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">En este punto del curso, hablaremos de matemáticas en JavaScript — cómo podemos usar {{Glossary("Operator","operadores")}} y otras características para manipular con éxito números y conseguir lo que nos hayamos propuesto.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de ordenadores, comprensión básica de HTML y CSS, comprensión básica de lo que es JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarse con las matemáticas básicas de JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Todos_aman_las_matemáticas">Todos aman las matemáticas</h2> + +<p>Vale, tal vez no. A algunos nos gustan, otros las odiamos desde que aprendimos en la escuela las tablas de multipicar y las divisiones complicadas, y algunos estamos a mitad entre ambas posturas. Pero ninguno podemos negar que las matemáticas son una parte fundamental de la vida que nos afecta. Y esto es especialmente cierto cuando aprendemos JavaScript (o cualquier otro lenguaje similar) — en la medida en que ello pasa por procesar números, calcular nuevos valores, etc., no te puede sorprender comprobar que JavaScript dispone de un completo conjunto de funciones matemáticas.</p> + +<p>En este artículo se trata solo aquella parte básica que necesitas conocer por ahora.</p> + +<h3 id="Tipos_de_números">Tipos de números</h3> + +<p>En programación, incluso el simple sistema numérico decimal que todos conocemos tan bien, es más complicado de lo que podrías pensar. Usamos diferentes términos para describir diferentes tipos de números decimales, por ejemplo:</p> + +<ul> + <li><strong>Enteros son números sin parte decimal</strong>, e.g. 10, 400 o -5.</li> + <li><strong>Números con coma flotante </strong>(floats): tienen punto decimal y parte decimal, por ejemplo,12.5 y 56.7786543.</li> + <li><strong>Doubles</strong>: son un tipo específico de números de coma flotante que tienen una mayor precisión que los numeros de coma flotante comunes (lo que significa que son más precisos en cuanto a la cantidad de decimales que poseen).</li> +</ul> + +<p>¡Incluso tenemos distintos tipos de sistemas numéricos! El decimal es base 10 (quiere decir que utiliza 0-9 en cada columna), pero también tenemos cosas como:</p> + +<ul> + <li><strong>Binario</strong> — El lenguaje de computadora de nivel más bajo; 0s y 1s.</li> + <li><strong>Octal</strong> — De base 8, utiliza de 0–7 en cada columna.</li> + <li><strong>Hexadecimal</strong> — De base 16, utiliza de 0–9 y luego de a–f en cada columna. Puedes haber encontrado estos números antes, cuando colocabas <a href="/es/Learn/CSS/Introduction_to_CSS/Values_and_units#Hexadecimal_values">colores en CSS</a>.</li> +</ul> + +<p><strong>Antes de que comiences a preouparte de que tu cerebro se derrita, ¡detente un momento!</strong> Para empezar, sólo vamos a apegarnos a los números decimales durante todo este curso; pocas veces te verás en la necesidad de comenzar a pensar sobre los otros tipos, si es que lo haces.</p> + +<p>La segunda parte de las buenas noticias es que, a diferencia de otros lenguajes de programación, JavaScript sólo tiene un tipo de dato para los números, adivinaste, {{jsxref("Number")}}. Esto significa que, sin importar el tipo de número con el que estés lidiando en Javascript, los manejas siempre de la misma manera.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: En realidad, JavaScript tiene un segundo tipo de número, {{Glossary("BigInt")}}, que se utiliza para números enteros muy, muy grandes. Pero para los propósitos de este curso, solo nos preocuparemos por los valores numéricos.</p> +</div> + +<h3 id="Para_mí_todo_son_números.">Para mí, todo son números.</h3> + +<p>Juguemos un poco con algunos números para ponernos al día con la sintaxis básica que necesitamos. Coloca los comandos listados abajo en la <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">consola JavaScript de tus herramientas para desarrolladores</a>, o utiliza la sencilla consola integrada que verás abajo si lo prefieres.</p> + +<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/">Abrir en una ventana nueva</a></strong></p> + +<ol> + <li>Primero que todo, declara un par de variables e inicializalas con un entero y un flotante, respectivamente, luego escribe los nombres de esas variables para chequear que todo esté en orden: + <pre class="brush: js notranslate">var myInt = 5; +var myFloat = 6.667; +myInt; +myFloat;</pre> + </li> + <li>Los valores numéricos están escritos sin comillas - Trata de declarar e inicializar un par de variables más que contengan números antes de continuar.</li> + <li>Ahora chequea que nuestras variables originales sean del mismo tipo. Hay un operador llamado {{jsxref("Operators/typeof", "typeof")}} en JavaScript hace esto. Digita las dos lineas siguientes: + <pre class="brush: js notranslate">typeof myInt; +typeof myFloat;</pre> + Obtendrás <code>"number"</code> en ambos casos — esto hace las cosas mucho más fáciles que si diferentes números tuvieran difetentes tipos, y tuvimos que lidiar con ellos de diferentes maneras. Uf !</li> +</ol> + +<h2 id="Operadores_Aritméticos">Operadores Aritméticos</h2> + +<p>Los operadores aritméticos son operadores básicos que usamos para hacer sumas:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nombre</th> + <th scope="col">Propósito</th> + <th scope="col">Ejemplo</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+</code></td> + <td>Adición</td> + <td>Suma dos números juntos.</td> + <td><code>6 + 9</code></td> + </tr> + <tr> + <td><code>-</code></td> + <td>Resta</td> + <td>Resta el numero de la derecha del de la izquierda.</td> + <td><code>20 - 15</code></td> + </tr> + <tr> + <td><code>*</code></td> + <td>Multiplicación</td> + <td>Multiplica dos números juntos.</td> + <td><code>3 * 7</code></td> + </tr> + <tr> + <td><code>/</code></td> + <td>División</td> + <td>Divide el número de la izquierda por el de la derecha.</td> + <td><code>10 / 5</code></td> + </tr> + <tr> + <td><code>%</code></td> + <td>Sobrante (también llamado módulo)</td> + <td> + <p>Retorna el restante después de dividir el número de la izquierda en porciones enteras del de la derecha.</p> + </td> + <td><code>8 % 3</code> (retorna 2, como tres está dos veces en 8, quedando 2 restantes.)</td> + </tr> + </tbody> +</table> + +<div class="note"> +<p><strong>Nota</strong>: A veces verás números involucrados en sumas referidas como {{Glossary("Operand", "operands")}}.</p> +</div> + +<p>Probablemente no necesitemos enseñarte matemáticas básicas, pero nos gustaría probar tu entendimiento de la sintaxis involucrada. Intenta entrar los ejemplos de abajo en tu <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">consola JavaScript de tus herramientas para desarrolladores</a>, o usa la sencilla consola incorporada que se vio anteriormente, si lo prefieres, para familiarizarte con la sintaxis.</p> + +<ol> + <li>Primero, trata entrando un ejemplo simple por tu cuenta, como + <pre class="brush: js notranslate">10 + 7 +9 * 8 +60 % 3</pre> + </li> + <li>Puedes tratar declarando e inicializando algunos números en variables, y probar usándolos en la suma - Las variables se comportarán exactamente como los valores que tienen para los fines de la suma. Por ejemplo: + <pre class="brush: js notranslate">var num1 = 10; +var num2 = 50; +9 * num1; +num2 / num1;</pre> + </li> + <li>Por último, trate entrando algunas expresiones complejas, como: + <pre class="brush: js notranslate">5 + 10 * 3; +num2 % 9 * num1; +num2 + num1 / 8 + 2;</pre> + </li> +</ol> + +<p>Es posible que parte de este último conjunto de sumas no te dé el resultado que esperabas; La siguiente sección bien podría dar la respuesta del por qué.</p> + +<h3 id="Precedencia_de_Operadores">Precedencia de Operadores</h3> + +<p>Veamos el último ejemplo de arriba, asumiendo que num2 tiene el valor 50 y num1 tiene el valor 10 (como se indicó anteriormente):</p> + +<pre class="brush: js notranslate">num2 + num1 / 8 + 2;</pre> + +<p>Como un ser humano, puedes leer esto como "50 más 10 es igual a 60", luego "8 más 2 es igual a 10", y finalmente "60 dividido por 10 es igual a 6".</p> + +<p>Pero el navegador hace "10 dividido por 8 es igual a 1.25", luego "50 más 1.25 más 2 es igual a 53.25".</p> + +<p>Esto es debido a la <strong>precedencia de operadores</strong> — algunos operadores son aplicados antes de otros cuando se calcula el resultado de una suma (referida como una expresión, en programación). La precedencia de operadores en JavaScript es la misma que en las matemáticas de la escuela — La multiplicación y la división se resuelven siempre primero, luego la suma y resta (la suma siempre se evalua de izquierda a derecha).</p> + +<p>Si quieres alterar la precedencia de operación, puedes colocar paréntesis alrededor de las partes que quieras explícitamente evaluar primero. Para obtener un resultado de 6, podríamos hacer esto:</p> + +<pre class="brush: js notranslate">(num2 + num1) / (8 + 2);</pre> + +<p>Pruébalo y verás.</p> + +<div class="note"> +<p><strong>Nota</strong>: Una completa lista de todos los operadores de JavaScript y sus precedencias pueden encontrarse en <a href="/es/docs/Web/JavaScript/Guide/Expressions_and_Operators#Operator_precedence">Expresiones y operadores</a>.</p> +</div> + +<h2 id="Operadores_de_incremento_y_decremento">Operadores de incremento y decremento</h2> + +<p>Algunas veces necesitarás repetidamente sumar o restar uno de/a una variable numérica. Esto puede hacerse convenientemente usando los operadores de incremento (<code>++</code>) y decremento (<code>--</code>). Usamos <code>++</code> en nuestro juego "Adivina el número" en nuestro artículo <a href="/es/docs/Learn/JavaScript/First_steps/A_first_splash">Un primer acercamiento a JavaScrip</a><a href="/es/docs/Learn/JavaScript/Introduction_to_JavaScript_1/A_first_splash">t</a>, cuando agregamos 1 a nuestra variable <code>guessCount</code> para mantener una pista de cuantas respuestas le quedan al usuario por turno.</p> + +<pre class="brush: js notranslate">guessCount++;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Son muy comunmente usadas en <a href="/en-US/docs/Web/JavaScript/Guide/Loops_and_iteration">ciclos</a>, que aprenderás más adelante en el curso. Por ejemplo, Digamos que quieras recorrer una lista de precios, y agregar impuestos a cada uno. Usaría un ciclo para recorrer cada valor y realizar el cálculo necesario para agregar el impuesto a las ventas en cada caso. El incrementador es usado para mover al próximo valor cuando es necesario. Damos un simple ejemplo En realidad, proporcionamos un ejemplo simple que muestra cómo se hace esto: ¡pruébalo en vivo y mira el código fuente para ver si puedes detectar los incrementadores! Veremos los ciclos en detalle más adelante en el curso..</p> +</div> + +<p>Trata jugando con eso en tu consola. Para empezar, nota que no puedes aplicar esto directamente a un número, sin operar en él mismo. Lo siguiente retorna un error:</p> + +<pre class="brush: js notranslate">3++;</pre> + +<p>Asì, puedes solo incrementar una variable existente. Prueba esto:</p> + +<pre class="brush: js notranslate">var num1 = 4; +num1++;</pre> + +<p>Ok, la extrañeza número 2! Cuando hagas esto, verás que se devuelve un valor de 4; esto se debe a que el navegador devuelve el valor actual y luego incrementa la variable. Puedes ver que se ha incrementado si devuelves el valor variable nuevamente:</p> + +<pre class="brush: js notranslate">num1;</pre> + +<p>Lo mismo funciona con <code>--</code> : intenta lo siguiente:</p> + +<pre class="brush: js notranslate">var num2 = 6; +num2--; +num2;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Puedes hacer que el navegador lo haga al revés: aumentar / disminuir la variable y luego devolver el valor, colocando el operador al comienzo de la variable en lugar del final. Prueba los ejemplos anteriores otra vez, pero esta vez usa <code>++num1</code> y<code>--num2</code>.</p> +</div> + +<h2 id="Operadores_de_asignación">Operadores de asignación</h2> + +<p>Los operadores de asignación son operadores que asignan un valor a una variable. Ya usamos el más básico, <code>=</code>, muchas veces — simplemente asigna a la variable de la izquierda, el valor de la derecha:</p> + +<pre class="brush: js notranslate">var x = 3; // x contiene el valor 3 +var y = 4; // y contiene el valor 4 +x = y; // x ahora contiene el mismo valor de y... 4</pre> + +<p>Pero hay algunos tipos más complejos, que proporcionan atajos útiles para mantener tu código más ordenado y más eficiente. Los más comunes se enumeran a continuación.:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nombre</th> + <th scope="col">Propósito</th> + <th scope="col">_Ejemplo</th> + <th scope="col">__Atajo_de__</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>+=</code></td> + <td>Adición asignación</td> + <td>Suma el valor de la derecha al valor de la variable de la izquierda y returna el nuevo valor</td> + <td><code>x = 3;<br> + x += 4;</code></td> + <td><code>x = 3;<br> + x = x + 4;</code></td> + </tr> + <tr> + <td><code>-=</code></td> + <td>Resta asignación</td> + <td> + <p>Resta el valor de la derecha, del valor de la variable de la izquierda y retorna el nuevo valor.</p> + </td> + <td><code>x = 6;<br> + x -= 3;</code></td> + <td><code>x = 6;<br> + x = x - 3;</code></td> + </tr> + <tr> + <td><code>*=</code></td> + <td>Multiplicación asignación</td> + <td> + <p>Multiplica el valor de la variable en la izquierda por el valor en la derecha y retorna el nuevo valor.</p> + </td> + <td><code>x = 2;<br> + x *= 3;</code></td> + <td><code>x = 2;<br> + x = x * 3;</code></td> + </tr> + <tr> + <td><code>/=</code></td> + <td>División asignación</td> + <td> + <p>Divide el valor de la variable en la izquierda por el valor de la derecha y retorna el nuevo valor.</p> + </td> + <td><code>x = 10;<br> + x /= 5;</code></td> + <td><code>x = 10;<br> + x = x / 5;</code></td> + </tr> + </tbody> +</table> + +<p>Intenta digitar algunos de estos ejemplos en tu consola, para darte una idea de cómo funcionan. Mira si puedes preguntar los valores que tenían antes de ingresarlos en la segunda línea, en cada caso.</p> + +<p>Ten en cuenta que puedes usar otras variables en el lado derecho de cada expresión, por ejemplo:</p> + +<pre class="brush: js notranslate">var x = 3; // x contiene el valor 3 +var y = 4; // y contiene el valor 4 +x *= y; // x ahora contiene el valor 12</pre> + +<div class="note"> +<p><strong>Nota</strong>: Hay una cantidad de <a href="/es/docs/Web/JavaScript/Guide/Expressions_and_Operators#Assignment_operators">otros operadores de asignación disponibles</a>, pero estos son los básicos que debes aprender por ahora.</p> +</div> + +<h2 id="Aprendizaje_activo_dimensionando_una_caja_canvas">Aprendizaje activo: dimensionando una caja canvas</h2> + +<p>En este ejercicio vamos a hacer que completes algunos números y operadores para manipular el tamaño de una caja. El cuadro se dibuja utilizando una API de navegador llamada {{domxref("Canvas API", "", "", "true")}}. No hay necesidad de preocuparse por cómo funciona esto, solo concentrarse en las matemáticas por ahora. El ancho y el alto del cuadro (en píxeles) están definidos por las variables x e y, a las que inicialmente se les asigna un valor de 50.</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html", '100%', 520)}}</p> + +<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/editable_canvas.html">Abrir en una nueva ventana</a></strong></p> + +<p>En el cuadro de código editable anterior, hay dos líneas marcadas claramente con un comentario que nos gustaría que actualices para hacer que el cuadro crezca/se reduzca a ciertos tamaños, utilizando ciertos operadores y/o valores en cada caso. Intenta lo siguiente:</p> + +<ul> + <li>Cambia la línea que calcula x, para que el recuadro tenga un ancho de 50px, y que el 50 se calcule utilizando los números 43 y 7, y un operador aritmético.</li> + <li>Cambia la línea que calcula y, para que la casilla tenga 75px de altura y que el 75 se calcule utilizando los números 25 y 3, y un operador aritmético.</li> + <li>Cambia la línea que calcula x, para que el recuadro tenga un ancho de 250px, y que el 250 se calcule utilizando dos números y el operador del resto (módulo).</li> + <li>Cambia la línea que calcula y, para que el cuadro tenga 150px de altura, y que el 150 se calcule utilizando tres números, y los operadores de resta y división.</li> + <li>Cambia la línea que calcula x, para que el cuadro tenga 200px de ancho y que el 200 se calcule utilizando el número 4 y un operador de asignación.</li> + <li>Cambia la línea que calcula y, para que el cuadro tenga 200px de altura y que el 200 se calcule utilizando los números 50 y 3, el operador de multiplicación y el operador de asignación de suma.</li> +</ul> + +<p>No te preocupes si arruinas totalmente el código. Siempre puedes presionar el botón Restablecer para que las cosas vuelvan a funcionar. Después de haber respondido correctamente a todas las preguntas anteriores, siéntete libre de jugar con el código un poco más, o establece desafíos para tus amigos/compañeros de clase..</p> + +<h2 id="Operadores_de_comparación">Operadores de comparación</h2> + +<p>A veces querremos ejecutar pruebas de verdadero/falso, y luego actuaremos de acuerdo con el resultado de esa prueba. Para ello, utilizamos <strong>operadores de comparación</strong>.</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Operador</th> + <th scope="col">Nombre</th> + <th scope="col">Propósito</th> + <th scope="col">Ejemplo</th> + </tr> + <tr> + <td><code>===</code></td> + <td>Igual estricto</td> + <td>Comprueba si los valores izquierdo y derecho son idénticos entre sí</td> + <td><code>5 === 2 + 4</code></td> + </tr> + <tr> + <td><code>!==</code></td> + <td>Igual no-estricto</td> + <td>Comprueba si los valores izquierdo y derecho <strong>no</strong> son idénticos entre sí</td> + <td><code>5 !== 2 + 3</code></td> + </tr> + <tr> + <td><code><</code></td> + <td>Menor que</td> + <td>Comprueba si el valor izquierdo es menor que el derecho.</td> + <td><code>10 < 6</code></td> + </tr> + <tr> + <td><code>></code></td> + <td>Mayor que</td> + <td>Comprueba si el valor izquierdo es mayor que el derecho.</td> + <td><code>10 > 20</code></td> + </tr> + <tr> + <td><=</td> + <td>Menor o igual a</td> + <td>Comprueba si el valor izquierdo es menor o igual que el derecho.</td> + <td><code>3 <= 2</code></td> + </tr> + <tr> + <td>>=</td> + <td>Mayor o igual a</td> + <td>Comprueba si el valor izquierdo es mayor o igual que el derecho..</td> + <td><code>5 >= 4</code></td> + </tr> + </thead> +</table> + +<div class="note"> +<p><strong>Nota</strong>: Es posible que algunas personas utilicen == y != en sus pruebas de igualdad y no igualdad. Estos son operadores válidos en JavaScript, pero difieren de === /! ==: la prueba anterior indica si los valores son iguales. pero el tipo de datos puede ser diferente, mientras que las últimas versiones estrictas prueban si el valor y el tipo de datos son los mismos. Las versiones estrictas tienden a reducir el número de errores que no se detectan, por lo que te recomendamos que los utilices.</p> +</div> + +<p>Si intentas ingresar algunos de estos valores en una consola, verás que todos devuelven valores verdaderos/falsos, esos booleanos que mencionamos en el artículo anterior. Son muy útiles ya que nos permiten tomar decisiones en nuestro código; se usan cada vez que queremos hacer una elección de algún tipo, por ejemplo.:</p> + +<ul> + <li>Mostrar la etiqueta de texto correcta en un botón dependiendo de si una función está activada o desactivada.</li> + <li>Mostrar un mensaje sobre un juego si ha terminado, o un mensaje de victoria si el juego ha sido ganado.</li> + <li>Mostrando el saludo estacional correcto dependiendo de la temporada de vacaciones.</li> + <li>Acercar o alejar un mapa según el nivel de zoom seleccionado.</li> +</ul> + +<p>Veremos cómo codificar dicha lógica cuando veamos declaraciones condicionales en un artículo futuro. Por ahora, veamos un ejemplo rápido:</p> + +<pre class="brush: html notranslate"><button>Iniciar máquina</button> +<p>La máquina se detuvo.</p> +</pre> + +<pre class="brush: js notranslate">var btn = document.querySelector('button'); +var txt = document.querySelector('p'); + +btn.addEventListener('click', updateBtn); + +function updateBtn() { + if (btn.textContent === 'Iniciar máquina') { + btn.textContent = 'Detener máquina'; + txt.textContent = 'La máquina se inició!'; + } else { + btn.textContent = 'Iniciar máquina'; + txt.textContent = 'La máquina se detuvo.'; + } +}</pre> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/maths/conditional.html", '100%', 100)}}</p> + +<p><strong><a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/maths/conditional.html">Abrir en una nueva ventana</a></strong></p> + +<p>Puede ver el operador de igualdad utilizado justo dentro de la función <code>updateBtn().</code> En este caso, no estamos probando si dos expresiones matemáticas tienen el mismo valor (estamos comprobando si el contenido de texto de un botón contiene una cadena determinada), pero sigue siendo el mismo principio. Si el botón está actualmente diciendo "Iniciar máquina" cuando se presiona, cambiamos su etiqueta a "Detener máquina" y actualizamos la etiqueta según corresponda. Si el botón está actualmente diciendo "Detener máquina" cuando se presiona, volvemos a cambiar la pantalla.</p> + +<div class="note"> +<p><strong>Nota</strong>: Un control de este tipo que intercambia entre dos estados generalmente se conoce como <strong>conmutador</strong>. Conmuta entre un estado y otro — Luces on, luces off, etc.</p> +</div> + +<h2 id="Pon_a_prueba_tus_habilidades">Pon a prueba tus habilidades</h2> + +<p>Llegaste al final de este artículo, pero ¿puédes recordar la información más importante? Puedes encontrar algunas pruebas para verificar que has comprendido esta información antes de seguir avanzando — Ve <a href="/es/docs/Learn/JavaScript/First_steps/Test_your_skills:_Math">¡Pon a prueba tus habilidades!: Matemáticas</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En este artículo hemos cubierto la información fundamental que necesitas saber sobre los números en JavaScript, por ahora. Verás los números usados una y otra vez, a lo largo de tu aprendizaje de JavaScript, por lo que es una buena idea hacer esto ahora. Si eres una de esas personas que no disfruta de las matemáticas, puedes sentirte cómodo por el hecho de que este capítulo fue bastante breve.</p> + +<p>En el siguiente artículo, exploraremos el texto y cómo JavaScript nos permite manipularlo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si disfrutas de las matemáticas y quieres leer más sobre cómo se implementa en JavaScript, puedes encontrar muchos más detalles en la sección principal de JavaScript de MDN. Los mejores lugares para iniciar con artículos sobre <a href="/es/docs/Web/JavaScript/Guide/Numbers_and_dates">Numero y fechas</a> y <a href="/es/docs/Web/JavaScript/Guide/Expressions_and_Operators">Expresiones y operadores</a>.</p> +</div> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_is_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/A_first_splash">Un primer acercamiento a JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_went_wrong">¿Qué salió mal? Corrigiendo JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Variables">Guardando la información que necesitas— Variables</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Matem%C3%A1ticas">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos útiles para el manejo de cadenas</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Arrays">Arreglos</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Silly_story_generator" rel="nofollow">Evaluaciones: Generador de historias absurdas</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/prueba_tus_habilidades_colon__strings/index.html b/files/es/learn/javascript/first_steps/prueba_tus_habilidades_colon__strings/index.html new file mode 100644 index 0000000000..f919ac1ee3 --- /dev/null +++ b/files/es/learn/javascript/first_steps/prueba_tus_habilidades_colon__strings/index.html @@ -0,0 +1,122 @@ +--- +title: 'Prueba tus habilidades: Strings' +slug: 'Learn/JavaScript/First_steps/Prueba_tus_habilidades:_Strings' +tags: + - Cadenas + - JavaScript + - Novato + - Principiante + - Prueba tus habilidades + - aprende + - strings +translation_of: 'Learn/JavaScript/First_steps/Test_your_skills:_Strings' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta prueba de habilidad es evaluar si has entendido nuestros artículos <a href="/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a> y <a href="/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos de cadena útiles</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes probar las soluciones en los editores interactivos a continuación, sin embargo, puede ser útil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, o <a href="https://glitch.com/">Glitch</a> para trabajar en las tareas.<br> + <br> + Si te quedas atascado, pídenos ayuda — consulta la sección {{anch("Evaluación o ayuda adicional")}} en la parte inferior de esta página.</p> +</div> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: En los siguientes ejemplos, si hay un error en tu código, se mostrará en el panel de resultados de la página, para ayudarte a intentar averiguar la respuesta (o en la consola JavaScript del navegador, en el caso de la versión descargable).</p> +</div> + +<h2 id="Cadenas_1">Cadenas 1</h2> + +<p>En nuestra primera tarea de cadenas, comenzaremos con algo pequeño. Ya tienes la mitad de una cita famosa dentro de una variable llamada <code>quoteStart</code>; nos gustaría que:</p> + +<ol> + <li>Busques la otra mitad de la cita y la agregues al ejemplo dentro de una variable llamada <code>quoteEnd</code>.</li> + <li>Concatenes las dos cadenas para hacer una sola cadena que contenga la cita completa. Guardes el resultado dentro de una variable llamada <code>finalQuote</code>.</li> +</ol> + +<p>Verás que obtienes un error en este punto. ¿Puedes solucionar el problema con <code>quoteStart</code> para que la cita completa se muestre correctamente?</p> + +<p>Intenta actualizar el código en vivo a continuación para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/strings/strings1.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/strings/strings1-download.html">Descarga el punto de partida de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Cadenas_2">Cadenas 2</h2> + +<p>En esta tarea, se te proporcionan dos variables, <code>quote</code> y <code>substring</code>, que contienen dos cadenas. Nos gustaría que:</p> + +<ol> + <li>Recuperes la longitud de la cita y la guardes en una variable llamada <code>quoteLength</code>.</li> + <li>Busques la posición del índice donde aparece <code>substring</code> en <code>quote</code>, y almacenes ese valor en una variable llamada <code>index</code>.</li> + <li>Uses una combinación de las variables que tienes y las propiedades/métodos de cadena disponibles para recortar la cita original a "No me gustan los huevos verdes y el jamón", y la guardes en una variable llamada <code>revisedQuote</code>.</li> +</ol> + +<p>Intenta actualizar el código en vivo a continuación para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/strings/strings2.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/strings/strings2-download.html">Descarga el punto de partida de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Cadenas_3">Cadenas 3</h2> + +<p>En la siguiente tarea de cadenas, se te da la misma cita con la que terminaste en la tarea anterior, ¡pero está algo rota! Queremos que la arregles y actualices, así:</p> + +<ol> + <li>Cambia la letra mayúscula para corregir con mayúscula inicial la oración (todo en minúsculas, excepto la primera letra mayúscula). Almacena la nueva cita en una variable llamada <code>fixedQuote</code>.</li> + <li>En <code>fixedQuote</code>, reemplaza "huevos verdes con jamón" con otro alimento que realmente no te guste.</li> + <li>Hay una pequeña solución más por hacer: agrega un punto al final de la cita y guarda la versión final en una variable llamada <code>finalQuote</code>.</li> +</ol> + +<p>Intenta actualizar el código en vivo a continuación para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/strings/strings3.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/strings/strings3-download.html">Descarga el punto de partida de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Cadenas_4">Cadenas 4</h2> + +<p>En la tarea de cadena final, te hemos dado el nombre de un teorema, dos valores numéricos y una cadena incompleta (los bits que se deben agregar están marcados con asteriscos (<code>*</code>)). Queremos que cambies el valor de la cadena de la siguiente manera:</p> + +<ol> + <li>Cámbiala de un literal de cadena normal a una plantilla literal.</li> + <li>Reemplaza los cuatro asteriscos con cuatro marcadores de posición en la plantilla literal. Estos deben ser: + <ol> + <li>El nombre del teorema.</li> + <li>Los dos valores numéricos que tenemos.</li> + <li>La longitud de la hipotenusa de un triángulo rectángulo, dado que las longitudes de los otros dos lados son iguales a los dos valores que tenemos. Deberás buscar cómo calcular esto a partir de lo que tienes. Haz el cálculo dentro del marcador de posición.</li> + </ol> + </li> +</ol> + +<p>Intenta actualizar el código en vivo a continuación para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/strings/strings4.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/strings/strings4-download.html">Descarga el punto de partida de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Puedes practicar estos ejemplos en los editores interactivos anteriores.</p> + +<p>Si deseas que se evalúe tu trabajo o estás atascado y deseas pedir ayuda:</p> + +<ol> + <li>Coloca tu trabajo en un editor que se pueda compartir en línea, como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a> o <a href="https://glitch.com/">Glitch</a>. Puedes escribir el código tú mismo o utilizar los archivos de punto de partida vinculados en las secciones anteriores.</li> + <li>Escribe una publicación solicitando evaluación y/o ayuda en la <a href="https://discourse.mozilla.org/c/mdn/learn">categoría de aprendizaje del foro de discusión de MDN</a>. Tu publicación debe incluir: + <ul> + <li>Un título descriptivo como "Se busca evaluación para la prueba de habilidad de Cadenas 1".</li> + <li>Detalles de lo que ya has probado y lo que te gustaría que hiciéramos, p. ej. si estás atascado y necesitas ayuda, o quiere una evaluación.</li> + <li>Un enlace al ejemplo que deseas evaluar o con el que necesitas ayuda, en un editor que se pueda compartir en línea (como se mencionó en el paso 1 anterior). Esta es una buena práctica para entrar — es muy difícil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la página de la tarea o evaluación real, para que podamos encontrar la pregunta con la que deseas ayuda.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/javascript/first_steps/qué_es_javascript/index.html b/files/es/learn/javascript/first_steps/qué_es_javascript/index.html new file mode 100644 index 0000000000..bd845c8681 --- /dev/null +++ b/files/es/learn/javascript/first_steps/qué_es_javascript/index.html @@ -0,0 +1,436 @@ +--- +title: ¿Qué es JavaScript? +slug: Learn/JavaScript/First_steps/Qué_es_JavaScript +tags: + - APIs + - Aprender + - Artículo + - Añadir JavaScript + - Curso + - Dinámico + - En línea + - Gestores de JavaScript en linea + - JavaScript + - Navegador + - Núcleo + - Principiante + - comentários + - externo +translation_of: Learn/JavaScript/First_steps/What_is_JavaScript +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">¡Bienvenido al curso de JavaScript para principiantes de MDN! En este artículo veremos JavaScript desde un alto nivel, respondiendo preguntas como "¿Qué es?" y "¿Qué puedes hacer con él?", y asegúrate de estar cómodo con el propósito de JavaScript.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, conocimientos básicos de HTML y CSS.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarte con lo que es JavaScript, lo que puede hacer y cómo encaja en un sitio web.</td> + </tr> + </tbody> +</table> + +<h2 id="Una_definición_de_alto_nivel">Una definición de alto nivel</h2> + +<p>JavaScript es un lenguaje de programación o de secuencias de comandos que te permite implementar funciones complejas en páginas web, cada vez que una página web hace algo más que sentarse allí y mostrar información estática para que la veas, muestra oportunas actualizaciones de contenido, mapas interactivos, animación de Gráficos 2D/3D, desplazamiento de máquinas reproductoras de vídeo, etc., puedes apostar que probablemente JavaScript está involucrado. Es la tercera capa del pastel de las tecnologías web estándar, dos de las cuales (<a href="/es/docs/Learn/HTML">HTML</a> y <a href="/es/docs/Learn/CSS">CSS</a>) hemos cubierto con mucho más detalle en otras partes del Área de aprendizaje.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13502/cake.png" style="display: block; margin: 0 auto;"></p> + +<ul> + <li>{{Glossary("HTML")}} es el lenguaje de marcado que usamos para estructurar y dar significado a nuestro contenido web, por ejemplo, definiendo párrafos, encabezados y tablas de datos, o insertando imágenes y videos en la página.</li> + <li>{{Glossary("CSS")}} es un lenguaje de reglas de estilo que usamos para aplicar estilo a nuestro contenido HTML, por ejemplo, establecer colores de fondo y tipos de letra, y distribuir nuestro contenido en múltiples columnas.</li> + <li>{{Glossary("JavaScript")}} es un lenguaje de secuencias de comandos que te permite crear contenido de actualización dinámica, controlar multimedia, animar imágenes y prácticamente todo lo demás. (Está bien, no todo, pero es sorprendente lo que puedes lograr con unas pocas líneas de código JavaScript).</li> +</ul> + +<p>Las tres capas se superponen muy bien. Tomemos una etiqueta de texto simple como ejemplo. Podemos marcarla usando HTML para darle estructura y propósito:</p> + +<pre class="brush: html notranslate"><p>Player 1: Chris</p></pre> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13422/just-html.png" style="height: 28px; width: 108px;"></p> + +<p>Luego, podemos agregar algo de CSS a la mezcla para que se vea bien:</p> + +<pre class="brush: css notranslate">p { + font-family: 'helvetica neue', helvetica, sans-serif; + letter-spacing: 1px; + text-transform: uppercase; + text-align: center; + border: 2px solid rgba(0,0,200,0.6); + background: rgba(0,0,200,0.3); + color: rgba(0,0,200,0.6); + box-shadow: 1px 1px 2px rgba(0,0,200,0.4); + border-radius: 10px; + padding: 3px 10px; + display: inline-block; + cursor: pointer; +}</pre> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13424/html-and-css.png" style="height: 48px; width: 187px;"></p> + +<p>Y finalmente, podemos agregar algo de JavaScript para implementar un comportamiento dinámico:</p> + +<pre class="brush: js notranslate">const para = document.querySelector('p'); + +para.addEventListener('click', updateName); + +function updateName() { + let name = prompt('Enter a new name'); + para.textContent = 'Player 1: ' + name; +} +</pre> + +<p>{{ EmbedLiveSample('A_high-level_definition', '100%', 80, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Intenta hacer clic en esta última versión de la etiqueta de texto para ver qué sucede (ten en cuenta también que puedes encontrar esta demostración en GitHub — ¡consulta el <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/javascript-label.html">código fuente</a> o <a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/javascript-label.html">ejecútalo en vivo</a>)!</p> + +<p>JavaScript puede hacer mucho más que eso — exploremos qué con más detalle.</p> + +<h2 id="Entonces_¿qué_puede_hacer_realmente">Entonces, ¿qué puede hacer realmente?</h2> + +<p>El núcleo del lenguaje JavaScript de lado del cliente consta de algunas características de programación comunes que te permiten hacer cosas como:</p> + +<ul> + <li>Almacenar valores útiles dentro de variables. En el ejemplo anterior, por ejemplo, pedimos que ingreses un nuevo nombre y luego almacenamos ese nombre en una variable llamada <code>name</code>.</li> + <li>Operaciones sobre fragmentos de texto (conocidas como "cadenas" (<code>strings</code>) en programación). En el ejemplo anterior, tomamos la cadena "<code>Player1</code>:" y la unimos a la variable <code>name</code> para crear la etiqueta de texto completa, p. ej. ''<code>Player1: Chris</code>".</li> + <li>Y ejecuta código en respuesta a ciertos eventos que ocurren en una página web. Usamos un evento {{Event("click")}} en nuestro ejemplo anterior para detectar cuándo se hace clic en el botón y luego ejecutar el código que actualiza la etiqueta de texto.</li> + <li>¡Y mucho más!</li> +</ul> + +<p>Sin embargo, lo que aún es más emocionante es la funcionalidad construida sobre el lenguaje JavaScript de lado del cliente. Las denominadas <strong>interfaces de programación de aplicaciones</strong> (<strong>API</strong>) te proporcionan superpoderes adicionales para utilizar en tu código JavaScript.</p> + +<p>Las API son conjuntos de bloques de construcción de código listos para usar que permiten a un desarrollador implementar programas que de otro modo serían difíciles o imposibles de implementar. Hacen lo mismo para la programación que los kits de muebles prefabricados para la construcción de viviendas — es mucho más fácil tomar paneles precortados y atornillarlos para hacer una estantería que elaborar el diseño tú mismo, que ir y encontrar la madera correcta, cortar todos los paneles del tamaño y la forma correctos, buscar los tornillos del tamaño correcto y <em>luego</em> júntalos para hacer una estantería.</p> + +<p>Generalmente se dividen en dos categorías.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13508/browser.png" style="display: block; height: 511px; margin: 0px auto; width: 815px;"></p> + +<p>Las <strong>APIs del navegador</strong> están integradas en tu navegador web y pueden exponer datos del entorno informático circundante o realizar tareas complejas y útiles. Por ejemplo:</p> + +<ul> + <li>La {{domxref("Document_Object_Model", " API del DOM (<code>Document Object Model</code>)")}} te permite manipular HTML y CSS, crear, eliminar y cambiar el HTML, aplicar dinámicamente nuevos estilos a tu página, etc. Cada vez que ves aparecer una ventana emergente en una página, o se muestra algún nuevo contenido (como vimos anteriormente en nuestra sencilla demostración), por ejemplo, ese es el DOM en acción.</li> + <li>La {{domxref("Geolocalization", "API de Geolocalización")}} recupera información geográfica. Así es como <a href="https://www.google.com/maps">Google Maps</a> puede encontrar tu ubicación y trazarla en un mapa.</li> + <li>Las APIs {{domxref("Canvas_API", "Canvas")}} y {{domxref("WebGL_API", "WebGL")}} te permiten crear gráficos animados en 2D y 3D. Las personas están haciendo cosas increíbles con estas tecnologías web — consulta <a href="https://www.chromeexperiments.com">Experimentos de Chrome</a> y <a href="http://webglsamples.org/">webglsamples</a>.</li> + <li><a href="https://developer.mozilla.org/es/Apps/Fundamentals/Audio_and_video_delivery">APIs de audio y video</a> como {{domxref("HTMLMediaElement")}} y {{domxref("WebRTC API", "WebRTC")}} te permiten hacer cosas realmente interesantes con multimedia, como reproducir audio y video directamente en una página web, o tomar video de tu cámara web y mostrarlo en la computadora de otra persona (prueba nuestra sencilla <a href="http://chrisdavidmills.github.io/snapshot/">demostración instantánea</a> para hacerte una idea).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Muchas de las demostraciones anteriores no funcionarán en un navegador antiguo — al experimentar, es una buena idea utilizar un navegador moderno como Firefox, Chrome, Edge u Opera para ejecutar tu código. Deberás considerar las <a href="/es/docs/Learn/Tools_and_testing/Cross_browser_testing">pruebas en varios navegadores</a> con más detalle cuando estés más cerca de entregar el código de producción (es decir, código real que usarán los clientes reales).</p> +</div> + +<p>Las <strong>APIs de terceros</strong> no están integradas en el navegador de forma predeterminada y, por lo general, debes obtener su código e información de algún lugar de la Web. Por ejemplo:</p> + +<ul> + <li>La <a href="https://dev.twitter.com/overview/documentation">API de Twitter</a> te permite hacer cosas como mostrar tus últimos tweets en tu sitio web.</li> + <li>La <a href="https://developers.google.com/maps/">API de Google Maps</a> y la <a href="https://wiki.openstreetmap.org/wiki/API">API de OpenStreetMap</a> te permiten insertar mapas personalizados en tu sitio web y otras funciones similares.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: estas APIs son avanzadas y no cubriremos ninguna de ellas en este módulo. Puedes obtener más información sobre estas en nuestro <a href="/es/docs/Learn/JavaScript/Client-side_web_APIs">módulo de APIs web de lado del cliente</a>.</p> +</div> + +<p>¡También hay mucho más disponible! Sin embargo, no te emociones demasiado todavía. No podrás crear el próximo Facebook, Google Maps o Instagram después de estudiar JavaScript durante 24 horas — hay muchos conceptos básicos que cubrir primero. Y es por eso que estás aquí — ¡sigamos adelante!</p> + +<h2 id="¿Qué_está_haciendo_JavaScript_en_tu_página">¿Qué está haciendo JavaScript en tu página?</h2> + +<p>Aquí, de hecho, comenzaremos a ver algo de código y, mientras lo hacemos, exploraremos lo que realmente sucede cuando ejecutas JavaScript en tu página.</p> + +<p>Recapitulemos brevemente sobre la historia de lo que sucede cuando cargas una página web en un navegador (de lo que hablamos por primera vez en nuestro artículo <a href="/es/Learn/CSS/Introduction_to_CSS/How_CSS_works#How_does_CSS_actually_work">Cómo funciona CSS</a>). Cuando cargas una página web en tu navegador, estás ejecutando tu código (HTML, CSS y JavaScript) dentro de un entorno de ejecución (la pestaña del navegador). Esto es como una fábrica que toma materias primas (el código) y genera un producto (la página web).</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13504/execution.png" style="display: block; margin: 0 auto;"></p> + +<p>Un uso muy común de JavaScript es modificar dinámicamente HTML y CSS para actualizar una interfaz de usuario, a través de la API del modelo de objetos del documento (como se mencionó anteriormente). Ten en cuenta que el código de tus documentos web generalmente se cargan y ejecutan en el orden en que aparece en la página. Si JavaScript se carga e intenta ejecutarse antes de que se hayan cargado el HTML y el CSS al que afecta, pueden producirse errores. Aprenderás formas de evitar esto más adelante en el artículo, en la sección <a href="/es/docs/Learn/JavaScript/First_steps/What_is_JavaScript#Script_loading_strategies">Estrategias de carga de scripts</a>.</p> + +<h3 id="Seguridad_del_navegador">Seguridad del navegador</h3> + +<p>Cada pestaña del navegador tiene su propio depósito separado para ejecutar código (estos depósitos se denominan "entornos de ejecución" en términos técnicos) — esto significa que, en la mayoría de los casos, el código de cada pestaña se ejecuta de forma completamente independiente y el código de una pestaña no puede afectar el código en otra pestaña, o en otro sitio web. Esta es una buena medida de seguridad — si este no fuera el caso, los piratas podrían comenzar a escribir código para robar información de otros sitios web y otras cosas muy malas.</p> + +<div class="note"> +<p><strong>Nota</strong>: Existen formas de enviar código y datos entre diferentes sitios web/pestañas de manera segura, pero estas son técnicas avanzadas que no cubriremos en este curso.</p> +</div> + +<h3 id="Orden_de_ejecución_de_JavaScript">Orden de ejecución de JavaScript</h3> + +<p>Cuando el navegador encuentra un bloque de JavaScript, generalmente lo ejecuta en orden, de arriba a abajo. Esto significa que debes tener cuidado con el orden en el que colocas las cosas. Por ejemplo, volvamos al bloque de JavaScript que vimos en nuestro primer ejemplo:</p> + +<pre class="brush: js notranslate">const para = document.querySelector('p'); + +para.addEventListener('click', updateName); + +function updateName() { + let name = prompt('Enter a new name'); + para.textContent = 'Player 1: ' + name; +}</pre> + +<p>Aquí seleccionamos un párrafo de texto (línea 1), luego adjuntamos un detector de eventos (línea 3) de modo que cuando se hace clic en el párrafo, el bloque de código <code>updateName()</code> (líneas 5-8) se ejecuta. El bloque de código <code>updateName()</code> (estos tipos de bloques de código reutilizables se denominan "funciones") pide al usuario un nuevo nombre y luego inserta ese nombre en el párrafo para actualizar la pantalla.</p> + +<p>Si cambiaras el orden de las dos primeras líneas de código, ya no funcionaría — en su lugar, obtendrías un error en la <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">consola del desarrollador del navegador</a> — <code>TypeError: para is undefined</code>. Esto significa que el objeto <code>para</code> aún no existe, por lo que no podemos agregarle un detector de eventos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Este es un error muy común; debes tener cuidado de que los objetos a los que se hace referencia en tu código existan antes de intentar hacer algo con ellos.</p> +</div> + +<h3 id="Código_interpretado_versus_compilado">Código interpretado versus compilado</h3> + +<p>Es posible que escuches los términos <strong>interpretados</strong> y <strong>compilados</strong> en el contexto de la programación. En los lenguajes interpretados, el código se ejecuta de arriba a abajo y el resultado de ejecutar el código se devuelve inmediatamente. No tienes que transformar el código en una forma diferente antes de que el navegador lo ejecute. El código se recibe en su forma de texto amigable para el programador y se procesa directamente desde allí.</p> + +<p>Los lenguajes compilados, por otro lado, se transforman (compilan) a código máquina antes de que sean ejecutados por la computadora. Por ejemplo, C/C++ se compila a código máquina que luego ejecuta la computadora. El programa se ejecuta desde un formato binario, que se generó a partir del código fuente del programa original.</p> + +<p>JavaScript es un lenguaje de programación interpretado ligero. El navegador web recibe el código JavaScript en su forma de texto original y ejecuta el script a partir de ahí. Desde un punto de vista técnico, la mayoría de los intérpretes de JavaScript modernos utilizan una técnica llamada <strong>compilación en tiempo real</strong> para mejorar el rendimiento; el código fuente de JavaScript se compila en un formato binario más rápido mientras se usa el script, de modo que se pueda ejecutar lo más rápido posible. Sin embargo, JavaScript todavía se considera un lenguaje interpretado, ya que la compilación se maneja en el entorno de ejecución, en lugar de antes.</p> + +<p>Ambos tipos de lenguaje tienen ventajas, pero no las abordaremos ahora.</p> + +<h3 id="Código_de_lado_del_servidor_versus_de_lado_del_cliente">Código de lado del servidor versus de lado del cliente</h3> + +<p>También puedes escuchar los términos código <strong>de lado del servidor</strong> y <strong>de lado del cliente</strong>, especialmente en el contexto del desarrollo web. El código de lado del cliente es un código que se ejecuta en la computadora del usuario — cuando se ve una página web, el código de lado del cliente de la página se descarga, luego se ejecuta y se muestra en el navegador. En este módulo estamos hablando explícitamente de <strong>JavaScript de lado del cliente</strong>.</p> + +<p>El código de lado del servidor, por otro lado, se ejecuta en el servidor, luego sus resultados se descargan y se muestran en el navegador. Ejemplos de lenguajes web populares de lado del servidor incluyen a ¡PHP, Python, Ruby, ASP.NET y... JavaScript! JavaScript también se puede utilizar como lenguaje de lado del servidor, por ejemplo, en el popular entorno Node.js — puedes obtener más información sobre JavaScript de lado del servidor en nuestro tema <a href="/es/docs/Learn/Server-side">Sitios web dinámicos — Programación de lado del servidor</a>.</p> + +<h3 id="Código_dinámico_versus_estático">Código dinámico versus estático</h3> + +<p>La palabra <strong>dinámico</strong> se usa para describir tanto a JavaScript de lado del cliente como a los lenguajes de lado del servidor — se refiere a la capacidad de actualizar la visualización de una página web/aplicación para mostrar diferentes cosas en diferentes circunstancias, generando contenido nuevo según sea necesario. El código de lado del servidor genera dinámicamente nuevo contenido en el servidor, p. ej. extraer datos de una base de datos, mientras que JavaScript de lado del cliente genera dinámicamente nuevo contenido dentro del navegador del cliente, p. ej. creando una nueva tabla HTML, llenándola con los datos solicitados al servidor y luego mostrando la tabla en una página web que se muestra al usuario. El significado es ligeramente diferente en los dos contextos, pero relacionado, y ambos enfoques (de lado del servidor y de lado del cliente) generalmente funcionan juntos.</p> + +<p>Una página web sin contenido que se actualiza dinámicamente se denomina <strong>estática</strong> — simplemente muestra el mismo contenido todo el tiempo.</p> + +<h2 id="¿Cómo_agregas_JavaScript_a_tu_página">¿Cómo agregas JavaScript a tu página?</h2> + +<p>JavaScript se aplica a tu página HTML de manera similar a CSS. Mientras que CSS usa elementos {{htmlelement("link")}} para aplicar hojas de estilo externas y elementos {{htmlelement("style")}} para aplicar hojas de estilo internas a HTML, JavaScript solo necesita un amigo en el mundo de HTML: el elemento {htmlelement("script")}}. Aprendamos cómo funciona esto.</p> + +<h3 id="JavaScript_interno">JavaScript interno</h3> + +<ol> + <li>En primer lugar, haz una copia local de nuestro archivo de ejemplo <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript.html">apply-javascript.html</a>. Guárdalo en un directorio en algún lugar accesible.</li> + <li>Abre el archivo en tu navegador web y en tu editor de texto. Verás que el HTML crea una página web simple que contiene un botón en el que se puede hacer clic.</li> + <li>A continuación, ve a tu editor de texto y agrega lo siguiente en tu <code>head</code>, justo antes de tu etiqueta de cierre <code></head></code>: + <pre class="brush: html notranslate"><script> + + // JavaScript va aquí + +</script></pre> + </li> + <li>Ahora agregaremos algo de JavaScript dentro de nuestro elemento {{htmlelement("script")}} para que la página haga algo más interesante — agrega el siguiente código justo debajo de la línea "// El código JavaScript va aquí": + <pre class="brush: js notranslate">document.addEventListener("DOMContentLoaded", function() { + function createParagraph() { + let para = document.createElement('p'); + para.textContent = 'You clicked the button!'; + document.body.appendChild(para); + } + + const buttons = document.querySelectorAll('button'); + + for(let i = 0; i < buttons.length ; i++) { + buttons[i].addEventListener('click', createParagraph); + } +});</pre> + </li> + <li>Guarda tu archivo y actualiza el navegador — ahora deberías ver que cuando haces clic en el botón, se genera un nuevo párrafo y se coloca debajo.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si tu ejemplo no parece funcionar, sigue los pasos nuevamente y verifica que hiciste todo bien. ¿Guardaste tu copia local del código de inicio como un archivo <code>.html</code>? ¿Agregaste tu elemento {{htmlelement("script")}} justo antes de la etiqueta <code></head></code>? ¿Ingresaste el JavaScript exactamente como se muestra? <strong>JavaScript distingue entre mayúsculas y minúsculas y es muy exigente, por lo que debes ingresar la sintaxis exactamente como se muestra; de lo contrario, es posible que no funcione.</strong></p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Puedes ver esta versión en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript-internal.html">apply-javascript-internal.html</a> o (<a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/apply-javascript-internal.html">verla en vivo también</a>).</p> +</div> + +<h3 id="JavaScript_externo">JavaScript externo</h3> + +<p>Esto funciona muy bien, pero ¿y si quisiéramos poner nuestro JavaScript en un archivo externo? Exploremos esto ahora.</p> + +<ol> + <li>Primero, crea un nuevo archivo en el mismo directorio que tu archivo HTML del ejemplo. Como nombre ponle <code>script.js</code>; asegúrate de que el nombre tenga la extensión <code>.js</code>, ya que así es como se reconoce como JavaScript.</li> + <li>Reemplaza tu elemento {{htmlelement("script")}} actual con lo siguiente: + <pre class="brush: html notranslate"><script src="script.js" defer></script></pre> + </li> + <li>Dentro de <code>script.js</code>, agrega el siguiente script: + <pre class="brush: js notranslate">function createParagraph() { + let para = document.createElement('p'); + para.textContent = 'You clicked the button!'; + document.body.appendChild(para); +} + +const buttons = document.querySelectorAll('button'); + +for(let i = 0; i < buttons.length ; i++) { + buttons[i].addEventListener('click', createParagraph); +}</pre> + </li> + <li>Guarda y actualiza tu navegador, ¡y deberías ver lo mismo! Funciona igual, pero ahora tenemos nuestro JavaScript en un archivo externo. Por lo general, esto es bueno en términos de organización de tu código y para hacerlo reutilizable en varios archivos HTML. Además, el HTML es más fácil de leer sin grandes trozos de script en él.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Puedes ver esta versión en GitHub como <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/apply-javascript-external.html">apply-javascript-external.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/what-is-js/script.js">script.js</a> (<a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/what-is-js/apply-javascript-external.html">verla en vivo también</a>).</p> +</div> + +<h3 id="Controladores_de_JavaScript_en_línea">Controladores de JavaScript en línea</h3> + +<p>Ten en cuenta que a veces te encontrarás con fragmentos de código JavaScript real dentro de HTML. Podría verse algo similar a esto:</p> + +<div id="inline_js_example"> +<pre class="brush: js example-bad notranslate">function createParagraph() { + let para = document.createElement('p'); + para.textContent = 'You clicked the button!'; + document.body.appendChild(para); +}</pre> + +<pre class="brush: html example-bad notranslate"><button onclick="createParagraph()">Click me!</button></pre> +</div> + +<p>Puedes probar esta versión de nuestra demostración a continuación.</p> + +<p>{{ EmbedLiveSample('inline_js_example', '100%', 150, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Esta demostración tiene exactamente la misma funcionalidad que en las dos secciones anteriores, excepto que el elemento {{htmlelement("button")}} incluye un controlador <code>onclick</code> en línea para que la función se ejecute cuando se presiona el botón .</p> + +<p><strong>Sin embargo, no hagas esto</strong>. Es una mala práctica contaminar tu HTML con JavaScript, y es ineficiente; tendrías que incluir el atributo <code>onclick="createParagraph()"</code> en cada botón al que desees que se aplique JavaScript.</p> + +<p>El uso de una construcción de JavaScript pura te permite seleccionar todos los botones usando una instrucción. El código que usamos anteriormente para cumplir este propósito se ve así:</p> + +<pre class="brush: js notranslate">const buttons = document.querySelectorAll('button'); + +for(let i = 0; i < buttons.length ; i++) { + buttons[i].addEventListener('click', createParagraph); +}</pre> + +<p>Esto puede ser un poco más largo que el atributo <code>onclick</code>, pero funcionará para todos los botones, sin importar cuántos haya en la página, ni cuántos se agreguen o eliminen. No es necesario cambiar el JavaScript.</p> + +<div class="note"> +<p><strong>Nota</strong>: Intenta editar tu versión de <code>apply-javascript.html</code> y agrega algunos botones más en el archivo. Cuando la vuelvas a cargar, deberías encontrar que todos los botones al hacer clic crearán un párrafo. Limpio, ¿eh?</p> +</div> + +<h3 id="Estrategias_para_la_carga_de_scripts">Estrategias para la carga de scripts</h3> + +<p>Hay una serie de problemas relacionados con la carga de los scripts en el momento adecuado. ¡Nada es tan simple como parece! Un problema común es que todo el HTML de una página se carga en el orden en que aparece. Si estás utilizando JavaScript para manipular elementos en la página (o exactamente, el <a href="/es/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents#The_document_object_model">Modelo de objetos del documento</a>), tu código no funcionará si el JavaScript se carga y procesa antes que el HTML que estás intentando haga algo.</p> + +<p>En los ejemplos de código anteriores, en los ejemplos internos y externos, JavaScript se carga y se ejecuta en el encabezado del documento, antes de analizar el cuerpo HTML. Esto podría causar un error, por lo que hemos utilizado algunas construcciones para solucionarlo.</p> + +<p>En el ejemplo interno, puedes ver esta estructura alrededor del código:</p> + +<pre class="brush: js notranslate">document.addEventListener("DOMContentLoaded", function() { + ... +});</pre> + +<p>Este es un detector de eventos, que escucha el evento "DOMContentLoaded" del navegador, lo cual significa que el cuerpo HTML está completamente cargado y analizado. El JavaScript dentro de este bloque no se ejecutará hasta que se active ese evento, por lo que se evita el error (<a href="/es/docs/Learn/JavaScript/Building_blocks/Events">aprenderás sobre los eventos</a> más adelante en el curso).</p> + +<p>En el ejemplo externo, usamos una función de JavaScript más moderno para resolver el problema, el atributo <code>defer</code>, que le dice al navegador que continúe descargando el contenido HTML una vez que se ha alcanzado la etiqueta del elemento <code><script></code>.</p> + +<pre class="brush: js notranslate"><script src="script.js" defer></script></pre> + +<p>En este caso, tanto el script como el HTML se cargarán simultáneamente y el código funcionará.</p> + +<div class="note"> +<p><strong>Nota</strong>: En el caso externo, no necesitamos usar el evento <code>DOMContentLoaded</code> porque el atributo <code>defer</code> nos resolvió el problema. No usamos la solución <code>defer</code> para el ejemplo interno de JavaScript porque <code>defer</code> solo funciona para scripts externos.</p> +</div> + +<p>Una solución pasada de moda a este problema solía ser colocar tu elemento <code>script</code> justo en la parte inferior del cuerpo (por ejemplo, justo antes de la etiqueta <code></body></code>), para que se cargara después de haber procesado todo el HTML. El problema con esta solución es que la carga/procesamiento del script está completamente bloqueado hasta que se haya cargado el DOM HTML. En sitios muy grandes con mucho JavaScript, esto puede causar un importante problema de rendimiento y ralentizar tu sitio.</p> + +<h4 id="async_y_defer"><code>async</code> y <code>defer</code></h4> + +<p>En realidad, hay dos modernas características que podemos usar para evitar el problema del bloqueo de <code>script</code>: <code>async</code> y <code>defer</code> (que vimos anteriormente). Veamos la diferencia entre estas dos.</p> + +<p>Los scripts cargados con el atributo <code>async</code> (ve más abajo) descargarán el <code>script</code> sin bloquear el renderizado de la página y lo ejecutará tan pronto como el <code>script</code> se termine de descargar. No tienes garantía de que los <code>script</code>s se ejecuten en un orden específico, solo que no detendrán la visualización del resto de la página. Es mejor usar <code>async</code> cuando los <code>script</code>s de la página se ejecutan de forma independiente y no dependen de ningún otro <code>script</code> de la página.</p> + +<p>Por ejemplo, si tienes los siguientes elementos <code>script</code>:</p> + +<pre class="brush: html notranslate"><script async src="js/vendor/jquery.js"></script> + +<script async src="js/script2.js"></script> + +<script async src="js/script3.js"></script></pre> + +<p>No puedes confiar en el orden en que se cargarán los <code>script</code>s. <code>jquery.js</code> se puede cargar antes o después de <code>script2.js</code> y <code>script3.js</code> y si este es el caso, cualquier función en esos <code>script</code>s dependiendo de <code>jquery</code> producirá un error porque <code>jquery</code> no se definirá en el momento en que se ejecute el <code>script</code>.</p> + +<p><code>async</code> se debe usar cuando tienes un montón de <code>script</code>s en segundo plano para cargar, y solo deseas ponerlos en su lugar lo antes posible. Por ejemplo, tal vez tengas algunos archivos de datos del juego para cargar, que serán necesarios cuando el juego realmente comience, pero por ahora solo deseas continuar mostrando la introducción del juego, los títulos y el lobby, sin que se bloqueen al cargar el <code>script</code>.</p> + +<p>Los <code>script</code>s cargados con el atributo <code>defer</code> (ve a continuación) se ejecutarán en el orden en que aparecen en la página y los ejecutará tan pronto como se descarguen el <code>script</code> y el contenido:</p> + +<pre class="brush: html notranslate"><script defer src="js/vendor/jquery.js"></script> + +<script defer src="js/script2.js"></script> + +<script defer src="js/script3.js"></script></pre> + +<p>Todos los <code>script</code>s con el atributo <code>defer</code> se cargarán en el orden en que aparecen en la página. Entonces, en el segundo ejemplo, podemos estar seguros de que <code>jquery.js</code> se cargará antes que <code>script2.js</code> y <code>script3.js</code> y que <code>script2.js</code> se cargará antes de <code>script3.js</code>. No se ejecutarán hasta que se haya cargado todo el contenido de la página, lo cual es útil si tus <code>script</code>s dependen de que el DOM esté en su lugar (por ejemplo, modifican uno o más elementos de la página).</p> + +<p>Para resumir:</p> + +<ul> + <li><code>async</code> y <code>defer</code> indican al navegador que descargue los <code>script</code>s en un hilo separado, mientras que el resto de la página (el DOM, etc.) se descarga, por lo que los <code>script</code>s no bloquean la carga de la página.</li> + <li>Si tus <code>script</code>s se deben ejecutar inmediatamente y no tienen ninguna dependencia, utiliza <code>async</code>.</li> + <li>Si tus <code>script</code>s necesitan esperar a ser procesados y dependen de otros <code>script</code>s y/o del DOM en su lugar, cárgalos usando <code>defer</code>y coloca tus elementos <code><script></code> correspondientes en el orden que desees que el navegador los ejecute.</li> +</ul> + +<h2 id="Comentarios">Comentarios</h2> + +<p>Al igual que con HTML y CSS, es posible escribir comentarios en tu código JavaScript que el navegador ignorará y que existen simplemente para proporcionar instrucciones a tus compañeros desarrolladores sobre cómo funciona el código (y a ti, si regresas a tu código después de seis meses y no puedes recordar lo que hiciste). Los comentarios son muy útiles y deberías utilizarlos con frecuencia, especialmente para aplicaciones grandes. Hay dos tipos:</p> + +<ul> + <li>Un comentario de una sola línea se escribe después de una doble barra inclinada (//), p. ej. + <pre class="brush: js notranslate">// soy un comentario</pre> + </li> + <li>Se escribe un comentario de varias líneas entre las cadenas /* y */, p. ej. + <pre class="brush: js notranslate">/* + Yo también soy + un comentario +*/</pre> + </li> +</ul> + +<p>Entonces, por ejemplo, podríamos anotar el JavaScript de nuestra última demostración con comentarios como este:</p> + +<pre class="brush: js notranslate">// Función: crea un nuevo párrafo y lo agrega al final del cuerpo HTML. + +function createParagraph() { + let para = document.createElement('p'); + para.textContent = 'You clicked the button!'; + document.body.appendChild(para); +} + +/* + 1. Obtiene referencias de todos los botones de la página en un formato de arreglo. + 2. Recorre todos los botones y agrega un detector de eventos 'click' a cada uno. + + Cuando se presione cualquier botón, se ejecutará la función createParagraph(). +*/ + +const buttons = document.querySelectorAll('button'); + +for (let i = 0; i < buttons.length ; i++) { + buttons[i].addEventListener('click', createParagraph); +}</pre> + +<div class="note"> +<p><strong>Nota</strong>: En general, más comentarios suelen ser mejor que menos, pero debes tener cuidado si agregas muchos comentarios para explicar qué son las variables (los nombres de tus variables tal vez deberían ser más intuitivos), o para explicar operaciones muy simples (tal vez tu código sea demasiado complicado).</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p>Así que ahí tienes, tu primer paso en el mundo de JavaScript. Comenzamos solo con teoría, para comenzar a acostumbrarte a por qué usarías JavaScript y qué tipo de cosas puedes hacer con él. En el camino, viste algunos ejemplos de código y aprendiste cómo encaja JavaScript con el resto del código en tu sitio web, entre otras cosas.</p> + +<p>JavaScript puede parecer un poco abrumador en este momento, pero no te preocupes — en este curso, te guiaremos en pasos simples que tendrán sentido en el futuro. En el próximo artículo, <a href="/es/docs/Learn/JavaScript/Introduction_to_JavaScript_1/A_first_splash">nos sumergiremos directamente en lo práctico</a>, lo que te permitirá comenzar directamente y crear tus propios ejemplos de JavaScript.</p> + +<ul> +</ul> + +<p>{{NextMenu("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_is_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/A_first_splash">Primer contacto con JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_went_wrong">¿Qué salió mal? Solución de problemas de JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Variables">Almacenamiento de la información que necesita — Variables</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Math">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos de cadena útiles</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Arrays">Arreglos</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Silly_story_generator">Evaluación: Generador de historias tontas</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/strings/index.html b/files/es/learn/javascript/first_steps/strings/index.html new file mode 100644 index 0000000000..e86560ae54 --- /dev/null +++ b/files/es/learn/javascript/first_steps/strings/index.html @@ -0,0 +1,299 @@ +--- +title: Manejar texto — cadenas en JavaScript +slug: Learn/JavaScript/First_steps/Strings +tags: + - Artículo + - Cadenas + - Comillas + - Guía + - JavaScript + - Novato + - Principiante + - Union + - Unir + - concatenación + - 'l10n:priority' + - strings +translation_of: Learn/JavaScript/First_steps/Strings +--- +<p id="Manejo_de_texto_—_cadenas_en_JavaScript">{{LearnSidebar}}</p> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary"><span id="result_box" lang="es"><span>A continuación, centraremos nuestra atención en las </span></span>cadenas<span lang="es"><span> de caracteres (<code>string</code>s)</span></span><span lang="es"><span>: así es como se llaman los fragmentos de texto en programación.</span> <span>En este artículo veremos todas las cosas comunes que realmente deberías saber sobre </span></span>cadenas<span lang="es"><span> de caracteres al aprender JavaScript, como crear cadenas, comillas en cadenas y unir cadenas.</span></span></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de informática, una comprensión básica de HTML y CSS y de lo que es JavaScript.</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td><span id="result_box" lang="es"><span>Familiarizarte con los aspectos básicos de las </span></span>cadenas<span lang="es"><span> de caracteres en JavaScript.</span></span></td> + </tr> + </tbody> +</table> + +<h2 id="El_poder_de_las_palabras"><span class="short_text" id="result_box" lang="es"><span>El poder de las palabras</span></span></h2> + +<p>Las palabras son muy importantes para los humanos — son una parte fundamental de nuestra comunicación. Dado que la Web es un medio en gran parte basado en texto diseñado para permitir a los humanos comunicarse y compartir información, es útil para nosotros tener control sobre las palabras que aparecen en él. {{glossary("HTML")}} proporciona estructura y significado a nuestro texto, {{glossary("CSS")}} nos permite personalizarlo con precisión, y JavaScript contiene una serie de funciones para manipular cadenas, crear mensajes personalizados de bienvenida, mostrar las etiquetas de texto adecuadas cuando sea necesario, organizar los términos en el orden deseado y mucho más.</p> + +<p>Casi todos los programas que hemos mostrado hasta ahora en el curso han involucrado alguna manipulación de cadenas.</p> + +<h2 id="Cadenas_—_las_bases">Cadenas — las bases</h2> + +<p>A primera vista, las cadenas se tratan de forma similar a los números, pero cuando profundizas empiezas a ver diferencias notables. Comencemos ingresando algunas líneas de texto básicas en la consola para familiarizarnos. Te proveeremos de una aquí abajo (también puedes <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir la consola</a> en una pestaña o ventana separada, o usar la <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">consola de desarrollo del navegador</a> si así lo prefieres).</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>Consola JavaScript</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class','input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + if(document.querySelectorAll('div').length > 1) { + inputForm.focus(); + } + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Resultado: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Creando_una_cadena">Creando una cadena</h3> + +<ol> + <li>Para comenzar, ingresa las siguientes líneas: + <pre class="brush: js notranslate">var string = 'La revolución no será televisada.'; +string;</pre> + Al igual que con los números, declaramos una variable, iniciandola con el valor de una cadena, y luego retornamos dicho valor. La única diferencia es que al escribir una cadena, necesitas envolverla con comillas.</li> + <li>Si no lo haces, u olvidas una de las comillas, obtendrás un error. Intenta ingresando las siguientes líneas: + <pre class="brush: js example-bad notranslate">var malString = Esto es una prueba; +var malString = 'Esto es una prueba; +var malString = Esto es una prueba';</pre> + Estas líneas no funcionan porque el texto sin comillas alrededor es tomado como nombre de una variable, propiedad, palabra reservada, o algo similar. Si el navegador no las encuentra, entonces se recibe un error( ej. "missing ; before statement"). Si el navegador puede ver dónde comienza una cadena, pero no dónde termine, como se indica en la segunda oración, devuelve error (con "unterminated string literal"). Si tu programa devuelve estos errores, revisa desde el inicio que todas tus cadenas posean sus comillas.</li> + <li>Lo siguiente funcionará si previamente definiste la variable <code>string</code> — inténtalo: + <pre class="brush: js notranslate">var maltring = string; +malString;</pre> + <code>malString</code> ahora tiene el mismo valor que <code>string</code>.</li> +</ol> + +<h3 id="Comillas_simples_vs._comillas_dobles">Comillas simples vs. comillas dobles</h3> + +<ol> + <li>En JavaScript, puedes escoger entre comillas simple y dobles para envolver tus cadenas. Ambas funcionarán correctamente: + <pre class="brush: js notranslate">var simp = 'Comillas simples.'; +var dobl = "Comillas dobles."; +simp; +dobl;</pre> + </li> + <li>Hay muy poca diferencia entre las dos, y la que utilices dependerá de tus preferencias personales. Sin embargo, deberías de elegir una y mantenerla; usar diferentes tipos de comillas en el código podría llegar a ser confuso, especialmente si utilizas diferentes comillas en la misma cadena. El siguiente ejemplo devolverá un error: + <pre class="brush: js example-bad notranslate">var badQuotes = 'What on earth?";</pre> + </li> + <li>El navegador pensará que la cadena no se ha cerrado correctamente, porque el otro tipo de cita que no estás usando, puede aparecer en la cadena. Por ejemplo, en estos dos casos su uso es correcto: + <pre class="brush: js notranslate">var sglDbl = 'Would you eat a "fish supper"?'; +var dblSgl = "I'm feeling blue."; +sglDbl; +dblSgl;</pre> + </li> + <li>Sin embargo, no puedes usar el mismo tipo de comillas en el interior de una cadena que ya las tiene en los extremos. Lo siguiente devuelve error, porque confunde al navegador respecto de dónde termina la cadena: + <pre class="brush: js example-bad notranslate">var bigmouth = 'I've got no right to take my place...';</pre> + Lo que nos lleva directamente al siguiente tema.</li> +</ol> + +<h3 id="Escapando_caracteres_en_una_cadena">Escapando caracteres en una cadena</h3> + +<p>Para solucionar nuestro problema anterior, necesitamos "escapar" el asunto de las comillas. Escapar caracteres significa que les hacemos algo para asegurarnos que sean reconocidos como texto, y no parte del código. En JavaScript, colocamos una barra invertida justo antes del caracter. Intenta ésto:</p> + +<pre class="brush: js notranslate">var bigmouth = 'I\'ve got no right to take my place...'; +bigmouth;</pre> + +<p>Ahora funciona correctamente. Puedes escapar otros caracteres de la misma forma, ej. <code>\"</code>, y hay varios códigos más. Ve a <a href="/es/docs/Web/JavaScript/Reference/Global_Objects/String#Escape_notation">Notación de Escape</a> para más detalles.</p> + +<h2 id="Concatenando_cadenas">Concatenando cadenas</h2> + +<ol> + <li>Concatenar es una elegante palabra de la programación que significa: "unir". Para unir cadenas en JavaScript el símbolo de más (+), el mismo operador que usamos para sumar números, pero en este contexto hace algo diferente. Vamos a probar un ejemplo en nuestra consola. + <pre class="brush: js notranslate">var one = 'Hello, '; +var two = 'how are you?'; +var joined = one + two; +joined;</pre> + El resultado de este código es una variable llamada <code>joined</code>, que contiene el valor: "Hello, how are you?" ("Hola, cómo estas?").</li> + <li>En la última instancia del código, unimos dos strings, pero lo puedes hacer con cuantas desees, mientras que incluyas el símbolo de <code>+</code> entre ellas. Prueba esto: + <pre class="brush: js notranslate">var multiple = one + one + one + one + two; +multiple;</pre> + </li> + <li>También puedes usar una combinación de variables y strings reales. Prueba esto: + <pre class="brush: js notranslate">var response = one + 'I am fine — ' + two; +response;</pre> + </li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Cuando ingresas una string real en tu código, entre comillas simples o dobles, se llama <strong>string literal</strong>.</p> +</div> + +<h3 id="La_concatenación_en_contexto">La concatenación en contexto</h3> + +<p>Vamos a revisar la concatenación que usamos en la siguiente acción — veamos este ejemplo ya citado previamente en el curso:</p> + +<pre class="brush: html notranslate"><button>Press me</button></pre> + +<pre class="brush: js notranslate">var button = document.querySelector('button'); + +button.onclick = function() { + var name = prompt('What is your name?'); + alert('Hello ' + name + ', nice to see you!'); +}</pre> + +<p>{{ EmbedLiveSample('Concatenation_in_context', '100%', 50, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>Aquí estamos usando una función {{domxref("Window.prompt()", "Window.prompt()")}} en la línea 4, que le pide al usuario la respuesta a una pregunta, através de un cuadro emergente (también llamado popup) y luego, almacenará el dato dentro de una variable dada — en este caso llamada <code>name (nombre)</code>. Luego, en la línea 5, usamos una función {{domxref("Window.alert()", "Window.alert()")}} para mostrar otra ventana emergente que contiene una cadena que hemos unido de la concatenación de dos string literales y la variable <code>name (</code>nombre). </p> + +<h3 id="Números_versus_cadenas">Números versus cadenas</h3> + +<ol> + <li>Entonces, ¿qué sucede cuando intentamos agregar (o concatenar) un string y un número? Vamos a probar en la consola: + <pre class="brush: js notranslate">'Front ' + 242; +</pre> + Podrías esperar que diera un error, pero funciona a la perfección. Tratar de representar un string como un número no tiene sentido, pero representar un número como string si que lo tiene, así que el navegador convierte el número en una string y las muestra juntas. </li> + <li>Incluso puedes hacer esto con dos números — puedes forar un número para que se convierta en una string envolviéndolo entre comillas. Prueba lo siguiente (estamos utilizando el operador <code>typeof</code> para verificar si la variable es un número o una cadena): + <pre class="brush: js notranslate">var myDate = '19' + '67'; +typeof myDate;</pre> + </li> + <li>Si tienes una variable numérica, que deseas convertir en una string, pero no cambiar de otra forma, o una variable string, que deseas convertir a número, pero no cambiarla de otra forma, puedes usar las siguientes construcciones: + <ul> + <li>El objecto {{jsxref("Number")}} convertirá cualquier cosa que se le pase en un número, si puede. Intenta lo siguiente: + <pre class="brush: js notranslate">var myString = '123'; +var myNum = Number(myString); +typeof myNum;</pre> + </li> + <li>Por otra parte, cada número tiene un método llamado <code><a href="/es/docs/Web/JavaScript/Reference/Global_Objects/Number/toString">toString()</a></code> que convertirá el equivalente en una string. Prueba esto: + <pre class="brush: js notranslate">var myNum = 123; +var myString = myNum.toString(); +typeof myString;</pre> + </li> + </ul> + Estas construcciones pueden ser muy útiles en ciertas situaciones. Por ejemplo, si un usuario introduce un número en un campo de texto de un formulario, será un string. Sin embargo, si quieres añadir ese número a algo, lo necesitas convertir a número, así que puedes usar esta construcción para hacerlo. Hicimos exactamente esto en el ejercicio de ejemplo: Juego adivina el número en la línea 54 (<a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/first-splash/number-guessing-game.html#L54">Juego Adivina el número, en la línea 54</a>).</li> +</ol> + +<h2 id="Prueba_tus_habilidades_2">Prueba tus habilidades</h2> + +<p id="Prueba_tus_habilidades">Llegaste al final de este artículo, pero ¿puédes recordar la información más importante? Puedes encontrar algunas pruebas para verificar que has comprendido esta información antes de seguir avanzando — Ve <a href="/es/docs/Learn/JavaScript/First_steps/Test_your_skills:_Strings">Prueba tus habilidades: Strings</a>. Ten en cuenta que esto requiere conocimiento del próximo artículo, por lo que podrías leerlo antes.</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>Esto es lo básico que debes saber sobre las cadenas o <code>string</code>s en JavaScript. En el siguiente artículo desarrollaremos más sobre esto, observando métodos de construcción de strings disponibles en JavaScript y cómo podemos usarlos para manipular nuestras cadenas de la forma que queremos. </p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps/Useful_string_methods", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_is_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/A_first_splash">Un primer acercamiento a JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_went_wrong">¿Qué salió mal? Corrigiendo JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Variables">Guardando la información que necesitas— Variables</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Math">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos útiles para el manejo de cadenas</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Arrays">Arreglos</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Silly_story_generator" rel="nofollow">Evaluaciones: Generador de historias absurdas</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/test_your_skills_colon__math/index.html b/files/es/learn/javascript/first_steps/test_your_skills_colon__math/index.html new file mode 100644 index 0000000000..e02f502bce --- /dev/null +++ b/files/es/learn/javascript/first_steps/test_your_skills_colon__math/index.html @@ -0,0 +1,91 @@ +--- +title: 'Comprueba tus habilidades: Matematicas.' +slug: 'Learn/JavaScript/First_steps/Test_your_skills:_Math' +tags: + - JavaScript + - Matemática + - Principiante + - Prueba tus habilidades + - aprende +translation_of: 'Learn/JavaScript/First_steps/Test_your_skills:_Math' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta prueba de habilidad es conocer si has entendido nuestra clase sobre el articulo <a href="/en-US/docs/Learn/JavaScript/First_steps/Math">Matematica basica en JavaScript — números y operadores</a>.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: Puedes probar soluciones en los editores interactivos a continuación, sin embargo, puede ser útil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, o <a href="https://glitch.com/">Glitch</a> para trabajar en las tareas.</p> + +<p>Si se queda atascado, pídanos ayuda; consulte la sección {{anch ("Evaluación o ayuda adicional")}} en la parte inferior de esta página.</p> + +<p><strong>Nota</strong>: En los ejemplos a continuación, si hay un error en su código, se mostrará en el panel de resultados de la página, para ayudarlo a tratar de averiguar la respuesta (o en la consola JavaScript del navegador, en el caso de la versión descargable).</p> +</div> + +<h2 id="Math_1">Math 1</h2> + +<p>Iniciemos poniendo a prueba sus conocimientos acerca de los operadores matemáticos básicos. Usted tendrá que crear 4 valores númericos, unir los 2 primeros, hacer una resta del cuarto con el tercero y multiplicar los resultados secundarios juntos para obtener un resultado final de 48. Y finalmente, necesita ejecutar una prueba para comprobar si el resultado es un numero par.</p> + +<p>Asi que intente realizar la actualización del código descrito abajo para crear el ejemplo terminado, siguendo estos pasos:</p> + +<ol> + <li>Crea cuatro variables que contengan numeros. Llama a las variables razonablemente.</li> + <li>Agrega las dos primeras variables juntas y guarda el resultado en otra variable.</li> + <li>Subtract the fourth variable from the third and store the result in another variable.</li> + <li>Multiply the results from the last two steps together, storing the result in a variable called <code>finalResult</code>. The product should be 48. If it isn't, you'll have to adjust some of the initial input values.</li> + <li>Finally, write a calculation that checks whether <code>finalResult</code> is an even number. Store the result in a variable called <code>evenOddResult</code>.</li> +</ol> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/math/math1.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/math/math1-download.html">Download the starting point for this task</a> to work in your own editor or in an online editor.</p> +</div> + +<h2 id="Math_2">Math 2</h2> + +<p>In the second task you are already provided with two calculations, with the results stored in the variables <code>result</code> and <code>result2</code>. But these results aren't what we want; you'll need to take the calculations and change them to give us what we want.</p> + +<p>What do we want? After multiplying the two results together and formatting the result to 2 decimal places, the final result should be 10.42.</p> + +<p>Try updating the live code below to recreate the finished example, following these steps:</p> + +<ol> + <li>Write a calculation that multiples <code>result</code> and <code>result2</code> together and assigns the result back to <code>result</code>. This will require assignment shorthand.</li> + <li>Write a line of code that takes result and formats it to 2 decimal places, storing the result of this in a variable called <code>finalResult</code>.</li> + <li>Check the data type of <code>finalResult</code> using <code>typeof</code>; you'll probably see that it is actually of <code>string</code> type! Write a line of code that converts it to a <code>number</code> type, storing the result in a variable called <code>finalNumber</code>.</li> + <li>The value of <code>finalNumber</code> needs to be <code>10.42</code>. Go back and update the original calculations you were provided with so that they give this final result. Don't update the numbers or the operators.</li> +</ol> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/math/math2.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/math/math2-download.html">Download the starting point for this task</a> to work in your own editor or in an online editor.</p> +</div> + +<h2 id="Math_3">Math 3</h2> + +<p>In the final task for this article, we want you to write some tests. You've got three groups, each consisting of a statement and two variables. For each one, write a test that proves or disproves the statement made. Store the results of those tests in variables called <code>weightComparison</code>, <code>heightComparison</code>, and <code>pwdMatch</code>, respectively.</p> + +<p>{{EmbedGHLiveSample("learning-area/javascript/introduction-to-js-1/tasks/math/math3.html", '100%', 400)}}</p> + +<div class="blockIndicator note"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/math/math3-download.html">Download the starting point for this task</a> to work in your own editor or in an online editor.</p> +</div> + +<h2 id="Assessment_or_further_help">Assessment or further help</h2> + +<p>You can practice these examples in the Interactive Editors above.</p> + +<p>If you would like your work assessed, or are stuck and want to ask for help:</p> + +<ol> + <li>Put your work into an online shareable editor such as <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, or <a href="https://glitch.com/">Glitch</a>. You can write the code yourself, or use the starting point files linked to in the above sections.</li> + <li>Write a post asking for assessment and/or help at the <a href="https://discourse.mozilla.org/c/mdn/learn">MDN Discourse forum Learning category</a>. Your post should include: + <ul> + <li>A descriptive title such as "Assessment wanted for Math 1 skill test".</li> + <li>Details of what you have already tried, and what you would like us to do, e.g. if you are stuck and need help, or want an assessment.</li> + <li>A link to the example you want assessed or need help with, in an online shareable editor (as mentioned in step 1 above). This is a good practice to get into — it's very hard to help someone with a coding problem if you can't see their code.</li> + <li>A link to the actual task or assessment page, so we can find the question you want help with.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/javascript/first_steps/test_your_skills_colon__variables/index.html b/files/es/learn/javascript/first_steps/test_your_skills_colon__variables/index.html new file mode 100644 index 0000000000..c242ff5ccc --- /dev/null +++ b/files/es/learn/javascript/first_steps/test_your_skills_colon__variables/index.html @@ -0,0 +1,84 @@ +--- +title: '¡Pon a prueba tus habilidades!: Variables' +slug: 'Learn/JavaScript/First_steps/Test_your_skills:_variables' +tags: + - JavaScript + - Principiante + - Tus habilidades con texto + - Variables + - aprende +translation_of: 'Learn/JavaScript/First_steps/Test_your_skills:_variables' +--- +<div>{{learnsidebar}}</div> + +<p>El objetivo de esta prueba de habilidad es evaluar si has entendido nuestro artículo <a href="/es/docs/Learn/JavaScript/First_steps/Variables">Almacenando la información que necesitas — Variables</a>.</p> + +<div class="blockIndicator"> +<p><strong>Nota</strong>: Puedes probar las soluciones en los editores interactivos a continuación, sin embargo, puede ser útil descargar el código y usar una herramienta en línea como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a>, o <a href="https://glitch.com/">Glitch</a> para trabajar en las tareas.<br> + <br> + Si te atascas, pídenos ayuda; consulta la sección {{anch('Evaluación o ayuda adicional')}} en la parte inferior de esta página.</p> +</div> + +<div class="blockIndicator"> +<p><strong>Nota</strong>: En los siguientes ejemplos, si hay un error en tu código, se mostrará en el panel de resultados de la página, para ayudarte a intentar averiguar la respuesta (o en la consola JavaScript del navegador, en el caso de la versión descargable).</p> +</div> + +<h2 id="Variables_1">Variables 1</h2> + +<p>En esta tarea queremos que:</p> + +<ul> + <li>Declares una variable llamada <code>myName</code>.</li> + <li>Inicies <code>myName</code> con un valor adecuado, en una línea separada (puedes usar tu nombre real o algo más).</li> + <li>Declares una variable llamada <code>myAge</code> la inicies con un valor, en la misma línea.</li> +</ul> + +<p>Intenta actualizar el código en vivo a continuación para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample('learning-area/javascript/introduction-to-js-1/tasks/variables/variables1.html', '100%', 400)}}</p> + +<div class="blockIndicator"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables1-download.html">Descarga el punto de partida de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Variables_2">Variables 2</h2> + +<p>En esta tarea, debes agregar una nueva línea para corregir el valor almacenado en la variable <code>myName</code> existente a tu propio nombre.</p> + +<p>Intenta actualizar el código en vivo a continuación para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample('learning-area/javascript/introduction-to-js-1/tasks/variables/variables2.html', '100%', 400)}}</p> + +<div class="blockIndicator"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables2-download.html">Descarga el punto de partida de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Variables_3">Variables 3</h2> + +<p>La tarea final por ahora — en este caso, se te proporciona un código existente, que tiene dos errores presentes. El panel de resultados debería mostrar el nombre <code>Chris</code> y una declaración sobre la edad que tendrá Chris dentro de 20 años. ¿Cómo puedes solucionar el problema y corregir la salida?</p> + +<p>Intenta actualizar el código en vivo a continuación para recrear el ejemplo terminado:</p> + +<p>{{EmbedGHLiveSample('learning-area/javascript/introduction-to-js-1/tasks/variables/variables3.html', '100%', 400)}}</p> + +<div class="blockIndicator"> +<p><a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/tasks/variables/variables3-download.html">Descarga el punto de partida de esta tarea</a> para trabajar en tu propio editor o en un editor en línea.</p> +</div> + +<h2 id="Evaluación_o_ayuda_adicional">Evaluación o ayuda adicional</h2> + +<p>Puedes practicar estos ejemplos en los editores interactivos anteriores.</p> + +<p>Si deseas que se evalúe tu trabajo o estás atascado y deseas pedir ayuda:</p> + +<ol> + <li>Coloca tu trabajo en un editor que se pueda compartir en línea, como <a href="https://codepen.io/">CodePen</a>, <a href="https://jsfiddle.net/">jsFiddle</a> o <a href="https://glitch.com/">Glitch</a>. Puedes escribir el código tú mismo o utilizar los archivos de punto de partida vinculados en las secciones anteriores.</li> + <li>Escribe una publicación solicitando evaluación y/o ayuda en la <a href="https://discourse.mozilla.org/c/mdn/learn">categoría de aprendizaje del foro de discusión de MDN</a>. Tu publicación debe incluir: + <ul> + <li>Un título descriptivo como Evaluación deseada para la prueba de habilidad de Variables 1.</li> + <li>Detalles de lo que ya has probado y lo que te gustaría que hiciéramos, p. ej. si estás atascado y necesitas ayuda, o quieres una evaluación.</li> + <li>Un enlace al ejemplo que deseas evaluar o con el que necesitas ayuda, en un editor que se pueda compartir en línea (como se mencionó en el paso 1 anterior). Esta es una buena práctica para empezar — es muy difícil ayudar a alguien con un problema de codificación si no puedes ver su código.</li> + <li>Un enlace a la página de la tarea o evaluación real, para que podamos encontrar la pregunta con la que deseas ayuda.</li> + </ul> + </li> +</ol> diff --git a/files/es/learn/javascript/first_steps/useful_string_methods/index.html b/files/es/learn/javascript/first_steps/useful_string_methods/index.html new file mode 100644 index 0000000000..09c6cfea08 --- /dev/null +++ b/files/es/learn/javascript/first_steps/useful_string_methods/index.html @@ -0,0 +1,718 @@ +--- +title: Métodos útiles con cadenas +slug: Learn/JavaScript/First_steps/Useful_string_methods +tags: + - Artículo + - Cadenas + - JavaScript + - Métodos + - Principiante +translation_of: Learn/JavaScript/First_steps/Useful_string_methods +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Ahora que hemos analizado los conceptos básicos de las cadenas, aumentemos la velocidad y comencemos a pensar qué operaciones útiles podemos hacer en cadenas con métodos integados, como encontrar la longitud de una cadena de texto, unir y dividir cadenas, sustituyendo un caracter de una cadena por otro, y más.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de informática, una comprensión básica de HTML y CSS, una comprensión de lo que es JavaScript.</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Comprender que las cadenas son objetos y aprender a usar algunos de los métodos básicos disponibles en esos objetos para manipular cadenas.</td> + </tr> + </tbody> +</table> + +<h2 id="Cadenas_como_objetos">Cadenas como objetos</h2> + +<p id="Useful_string_methods">Ya lo dijimos antes, y lo diremos de nuevo — <em>todo</em> es un objeto en JavaScript. Cuando creas una cadena, por ejemplo, usando:</p> + +<pre class="brush: js notranslate">let string = 'This is my string';</pre> + +<p>Tu variable se convierte en una instancia del objeto cadena y, como resultado, tiene una gran cantidad de propiedades y métodos disponibles. Puedes ver esto si vas a la página de objeto {{jsxref("String")}} y miras la lista al costado de la página.</p> + +<p><strong>Ahora, antes de que tu cerebro comience a derretirse, ¡no te preocupes!</strong> Realmente no necesitas saber acerca de la mayoría de estos principios en tu viaje de aprendizaje. Pero hay algunos que posiblemente utilizarás con bastante frecuencia así como veremos aquí. </p> + +<p>Ingresemos algunos ejemplos en una nueva consola. A continuación, proporcionamos uno (también puedes <a href="https://mdn.github.io/learning-area/javascript/introduction-to-js-1/variables/index.html">abrir esta consola</a> en una ventana o pestaña por separado, o si prefieres usar la <a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">consola de desarrolladores del navegador</a>).</p> + +<div class="hidden"> +<h6 id="Hidden_code">Hidden code</h6> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="utf-8"> + <title>JavaScript console</title> + <style> + * { + box-sizing: border-box; + } + + html { + background-color: #0C323D; + color: #809089; + font-family: monospace; + } + + body { + max-width: 700px; + } + + p { + margin: 0; + width: 1%; + padding: 0 1%; + font-size: 16px; + line-height: 1.5; + float: left; + } + + .input p { + margin-right: 1%; + } + + .output p { + width: 100%; + } + + .input input { + width: 96%; + float: left; + border: none; + font-size: 16px; + line-height: 1.5; + font-family: monospace; + padding: 0; + background: #0C323D; + color: #809089; + } + + div { + clear: both; + } + + </style> + </head> + <body> + + + </body> + + <script> + var geval = eval; + function createInput() { + var inputDiv = document.createElement('div'); + var inputPara = document.createElement('p'); + var inputForm = document.createElement('input'); + + inputDiv.setAttribute('class', 'input'); + inputPara.textContent = '>'; + inputDiv.appendChild(inputPara); + inputDiv.appendChild(inputForm); + document.body.appendChild(inputDiv); + + inputForm.addEventListener('change', executeCode); + } + + function executeCode(e) { + try { + var result = geval(e.target.value); + } catch(e) { + var result = 'error — ' + e.message; + } + + var outputDiv = document.createElement('div'); + var outputPara = document.createElement('p'); + + outputDiv.setAttribute('class','output'); + outputPara.textContent = 'Result: ' + result; + outputDiv.appendChild(outputPara); + document.body.appendChild(outputDiv); + + e.target.disabled = true; + e.target.parentNode.style.opacity = '0.5'; + + createInput() + } + + createInput(); + + </script> +</html></pre> +</div> + +<p>{{ EmbedLiveSample('Hidden_code', '100%', 300, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Encontrar_la_longitud_de_un_cadena">Encontrar la longitud de un cadena</h3> + +<p>Esto es fácil — simplemente usa la propiedad {{jsxref("String.prototype.length", "length")}} . Intenta ingresar las siguientes líneas:</p> + +<pre class="brush: js notranslate">let browserType = 'mozilla'; +browserType.length;</pre> + +<p>Esto debería devolver el número 7, porque "mozilla" tiene 7 caracteres. Esto es útil por muchas razones; por ejemplo, es posible que quieras buscar las longitudes de una serie de nombres para que puedas mostrarlos en orden de su longitud, o dejar que un usuario sepa que un nombre ingresado en un campo de formulario es demasiado largo o si tiene una longitud determinada.</p> + +<h3 id="Extrayendo_un_específico_caracter_de_la_cadena">Extrayendo un específico caracter de la cadena</h3> + +<p>En una nota relacionada, puedes devolver cualquier carácter de una cadena usando la <strong>notación de corchetes</strong> — esto significa que incluyes corchetes (<code>[]</code>) al final del nombre de tu variable. Dentro de los corchetes, incluye el número del caracter que deseas extraer, así que, por ejemplo, para extraer la primera letra harías esto:</p> + +<pre class="brush: js notranslate">browserType[0];</pre> + +<p>¡ Las computadoras cuentan desde 0, no desde 1! Para extraer el último caracter de <em>cualquier</em> cadena, podríamos usar la siguiente línea, combinando esta técnica con la propiedad <code>length</code> que vimos arriba:</p> + +<pre class="brush: js notranslate">browserType[browserType.length-1];</pre> + +<p>El largo de "mozilla" es 7, pero es porque el contador comienza en 0, la posición del caracter es 6, por lo tanto, necesitamos <code>length-1</code>. Puedes usar esto para, por ejemplo, encontrar la primera letra de una serie de cadenas y ordenarlas alfabéticamente.</p> + +<h3 id="Encontrar_una_subcadena_dentro_de_una_cadena_y_extraerla">Encontrar una subcadena dentro de una cadena y extraerla</h3> + +<ol> + <li>Algunas veces querrás encontrar si hay una cadena más pequeña dentro de una más grande (generalmente decimos <em>si una subcadena está presente dentro de una cadena</em>). Esto se puede hacer utilizando el método {{jsxref("String.prototype.indexOf()", "indexOf()")}}, que toma un único <a href="https://developer.mozilla.org/en-US/docs/Glossary/Parameter">parámetro</a> — la subcadena que deseas buscar. Intenta esto: + + <pre class="brush: js notranslate">browserType.indexOf('zilla');</pre> + Esto nos dá un resultado de 2, porque la subcadena "zilla" comienza en la posición 2 (0, 1, 2 — por tanto 3 caracteres en total) dentro de "mozilla". Tal código podría usarse para filtrar cadena. Por ejemplo, podemos tener una lista de direcciones web y solo queremos imprimir las que contienen "mozilla".</li> +</ol> + +<ol start="2"> + <li>Esto se puede hacer de otra manera, que posiblemente sea aún más efectiva. Intenta lo siguiente: + <pre class="brush: js notranslate">browserType.indexOf('vanilla');</pre> + Esto debería darte un resultado de <code>-1</code> — Esto se devuelve cuando la subcadena, en este caso 'vanilla', no es encontrada en la cadena principal.<br> + <br> + Puedes usar esto para encontrar todas las instancias de las cadenas que <strong>no</strong> contengan la subcadena 'mozilla', o <strong>hacerlo,</strong> si usas el operador de negación, como se muestra a continuación. Podrías hacer algo como esto: + + <pre class="brush: js notranslate">if(browserType.indexOf('mozilla') !== -1) { + // do stuff with the string +}</pre> + </li> + <li>Cuando sabes donde comienza una subcadena dentro de una cadena, y sabes hasta cuál caracter deseas que termine, puede usarse {{jsxref("String.prototype.slice()", "slice()")}} para extraerla. Prueba lo siguiente: + <pre class="brush: js notranslate">browserType.slice(0,3);</pre> + Esto devuelve "moz" — El primer parámetro es la posición del caracter en la que comenzar a extraer, y el segundo parámetro es la posición del caracter posterior al último a ser extraído. Por lo tanto, el corte ocurre desde la primera posición en adelante, pero excluyendo la última posición. En este ejemplo, dado que el índice inicial es 0, el segundo parámetro es igual a la longitud de la cadena que se devuelve.<br> + </li> + <li>Además, si sabes que deseas extraer todos los caracteres restantes de una cadena después de cierto caracter, ¡no necesitas incluir el segundo parámetro! En cambio, solo necesitas incluir la posición del caracter desde donde deseas extraer los caracteres restante en la cadena. Prueba lo siguiente: + <pre class="brush: js notranslate">browserType.slice(2);</pre> + Esto devuelve "zilla" — debido a que la posición del caracter de 2 es la letra z, y como no incluiste un segundo parámetro, la subcadena que que se devolvío fué el resto de los caracteres de la cadena. </li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: El segundo parámetro de <code>slice()</code> es opcional: si no lo incluyes, el corte termina al final de la cadena original. Hay otras opciones también; estudia la página {{jsxref("String.prototype.slice()", "slice()")}} para ver que mas puedes averiguar.</p> +</div> + +<h3 id="Cambiando_todo_a_mayúscula_o_minúscula">Cambiando todo a mayúscula o minúscula</h3> + +<p>Los métodos de cadena {{jsxref("String.prototype.toLowerCase()", "toLowerCase()")}} y {{jsxref("String.prototype.toUpperCase()", "toUpperCase()")}} toman una cadena y convierten todos sus caracteres a mayúscula o minúscula, respectivamente. Esto puede ser útil, por ejemplo, si deseas normalizar todos los datos ingresados por el usuario antes de almacenarlos en una base de datos.</p> + +<p>Intentemos ingresar las siguentes líneas para ver que sucede:</p> + +<pre class="brush: js notranslate">let radData = 'My NaMe Is MuD'; +radData.toLowerCase(); +radData.toUpperCase();</pre> + +<h3 id="Actualizando_partes_de_una_cadena">Actualizando partes de una cadena</h3> + +<p>En una cadena puedes reemplazar una subcadena por otra usando el método {{jsxref("String.prototype.replace()", "replace()")}}. Esto funciona de manera muy simple a un nivel básico, aunque hay algunas cosas avanzadas que puedes hacer con él en lo que todavía no entraremos.</p> + +<p>Toma dos parámetros — la cadena que deseas reemplazar, y la cadena con la que deseas reemplazarla. Prueba este ejemplo:</p> + +<pre class="brush: js notranslate">browserType.replace('moz','van');</pre> + +<p>Ten en cuenta que para obtener realmente el valor actualizado reflejado en la variable <code>browserType</code> en un programa real, debes establecer que el valor de la variable sea el resultado de la operación; No solo actualiza el valor de la subcadena automáticamente. Así que tendrías que escribir esto: <code>browserType = browserType.replace('moz','van');</code></p> + +<h2 id="Ejemplos_de_aprendizaje_activo">Ejemplos de aprendizaje activo</h2> + +<p>En esta sección, conseguiremos que intentes escribir algún código de manipulación de cadenas. En cada ejercicio a continuación, tenemos una matríz de cadenas y un bucle que procesa cada valor en la matríz y lo muestra en una lista con viñetas. No es necesario que comprendas matrices y bucles en este mismo momento — estos se explicarán en futuros artículos. Todo lo que necesitas hacer en cada caso es escribir el código que dará de salida a las cadenas en el formato que las queremos.</p> + +<p>Cada ejemplo viene con un botón de "Reset" , Que puedes utilizar para reestablecer el código si cometes un error y no puedes hacerlo funcionar nuevamente, y un botón "Show solution" que puedes presionar para ver una posible respuesta si te encuentras realmente atorado.</p> + +<h3 id="Filtrado_de_mensajes_de_saludo">Filtrado de mensajes de saludo</h3> + +<p>En el primer ejercicio, comenzamos de manera simple — tenemos una matríz de mensajes de tarjetas de felicitación, pero queremos ordenarlos para que aparezcan solo los mensajes de Navidad. Queremos que completes un test condicional dentro de la estructura <code>if( ... )</code>, para comprobar cada cadena y solo imprimirla en la lista si es un mensaje de Navidad.</p> + +<ol> + <li>Primero piensa en cómo puedes probar si el mensaje en cada caso es un mensaje de Navidad. ¿Qué cadena está presente en todos esos mensajes, y qué método podrías usar para comprobar si está presente?</li> + <li>A continuación, deberá escribir un test condicional de la forma <em>operand1 operator operand2</em>. ¿Es lo que está a la izquierda igual a lo que está a la derecha? O en este caso, ¿el método llamado a la izquierda devuelve el resultado a la derecha?</li> + <li>Sugerencia: En este caso, probablemente sea más útil comprobar si la llamada al método <em>no es</em> igual a un determinado resultado.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code">Playable code</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> + +<div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 290px; width: 95%"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var greetings = ['Happy Birthday!', + 'Merry Christmas my love', + 'A happy Christmas to all the family', + 'You\'re all I want for Christmas', + 'Get well soon']; + +for (var i = 0; i < greetings.length; i++) { + var input = greetings[i]; + // Your conditional test needs to go inside the parentheses + // in the line below, replacing what's currently there + if (greetings[i]) { + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); + } +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar greetings = [\'Happy Birthday!\',\n \'Merry Christmas my love\',\n \'A happy Christmas to all the family\',\n \'You\\\'re all I want for Christmas\',\n \'Get well soon\'];\n\nfor(var i = 0; i < greetings.length; i++) {\n var input = greetings[i];\n if(greetings[i].indexOf(\'Christmas\') !== -1) {\n var result = input;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n }\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code', '100%', 590, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Corrección_de_mayúscula">Corrección de mayúscula</h3> + +<p>En este ejercicio tenemos los nombres de las ciudades del Reino Unido, Pero las mayúsculas estan completamente desordenadas. Queremos que los cambies para que estén en minúscula, a excepción de la primera letra. Una buena manera de hacerlo es:</p> + +<ol> + <li>Convierte la totalidad de la cadena contenida en la variable <code>input</code> a minúsculas y guárdalas en una nueva variable.</li> + <li>Toma la primera letra de la cadena en esta nueva variable y guárdala en otra variable.</li> + <li>Usando esta última variable como una subcadena, reemplaza la primera letra de la cadena en minúscula con la subcadena en mayúscula. Almacena el resultado de este procedimiento de reemplazo en otra nueva variable.</li> + <li>Cambia el valor de la variable <code>result</code> a igual al resultado final. en vez de <code>input</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Una pista — los parámetros de los métodos de cadena no tienen que ser literales de cadenas; también pueden ser variables, o incluso variables con un método invocados en ellas.</p> +</div> + +<div class="hidden"> +<h6 id="Playable_code_2">Playable code 2</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> + +<div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 250px; width: 95%"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var cities = ['lonDon', 'ManCHESTer', 'BiRmiNGHAM', 'liVERpoOL']; +for(var i = 0; i < cities.length; i++) { + var input = cities[i]; + // write your code just below here + + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +}</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar cities = [\'lonDon\', \'ManCHESTer\', \'BiRmiNGHAM\', \'liVERpoOL\'];\n\nfor(var i = 0; i < cities.length; i++) {\n var input = cities[i];\n var lower = input.toLowerCase();\n var firstLetter = lower.slice(0,1);\n var capitalized = lower.replace(firstLetter,firstLetter.toUpperCase());\n var result = capitalized;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_2', '100%', 550, "", "", "hide-codepen-jsfiddle") }}</p> + +<h3 id="Creando_nuevas_cadenas_de_partes_viejas">Creando nuevas cadenas de partes viejas</h3> + +<p>En este último ejercicio, la matríz contiene un conjunto de cadenas que contienen información sobre estaciones de tren en el Norte de Inglaterra. Las cadenas son elementos de datos que contienen el código de estación de tres letras, seguidos de más datos legibles por máquina, seguidos de un punto y coma, seguidos por el nombre de la estación legible por humanos. Por ejemplo:</p> + +<pre class="notranslate">MAN675847583748sjt567654;Manchester Piccadilly</pre> + +<p>Queremos extraer el código y el nombre de la estación, y juntarlos en una cadena con la siguiente estructura:</p> + +<pre class="notranslate">MAN: Manchester Piccadilly</pre> + +<p>Recomendamos hacerlo así:</p> + +<ol> + <li>Extrae las tres letras del código de estación y almacénalo en una nueva variable.</li> + <li>Encuentra el número de índice de caracter del punto y coma.</li> + <li>Extrae el nombre de la estación legible por humanos utilizando el número de índice de caracter del punto y coma a modo de referencia y guardalo en una nueva variable.</li> + <li>Concatenar las dos nuevas variables y un literal de cadena para hacer la cadena final.</li> + <li>Cambia el valor de la variable de <code>result</code> a igual a la cadena final, no a <code>input</code>.</li> +</ol> + +<div class="hidden"> +<h6 id="Playable_code_3">Playable code 3</h6> + +<pre class="brush: html notranslate"><h2>Live output</h2> + +<div class="output" style="min-height: 125px;"> + +<ul> + +</ul> + +</div> + +<h2>Editable code</h2> +<p class="a11y-label">Press Esc to move focus away from the code area (Tab inserts a tab character).</p> + +<textarea id="code" class="playable-code" style="height: 285px; width: 95%"> +var list = document.querySelector('.output ul'); +list.innerHTML = ''; +var stations = ['MAN675847583748sjt567654;Manchester Piccadilly', + 'GNF576746573fhdg4737dh4;Greenfield', + 'LIV5hg65hd737456236dch46dg4;Liverpool Lime Street', + 'SYB4f65hf75f736463;Stalybridge', + 'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield']; + +for (var i = 0; i < stations.length; i++) { + var input = stations[i]; + // write your code just below here + + var result = input; + var listItem = document.createElement('li'); + listItem.textContent = result; + list.appendChild(listItem); +} +</textarea> + +<div class="playable-buttons"> + <input id="reset" type="button" value="Reset"> + <input id="solution" type="button" value="Show solution"> +</div> +</pre> + +<pre class="brush: css notranslate">html { + font-family: sans-serif; +} + +h2 { + font-size: 16px; +} + +.a11y-label { + margin: 0; + text-align: right; + font-size: 0.7rem; + width: 98%; +} + +body { + margin: 10px; + background: #f5f9fa; +} +</pre> + +<pre class="brush: js notranslate">var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var solution = document.getElementById('solution'); +var code = textarea.value; +var userEntry = textarea.value; + +function updateCode() { + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + userEntry = textarea.value; + solutionEntry = jsSolution; + solution.value = 'Show solution'; + updateCode(); +}); + +solution.addEventListener('click', function() { + if(solution.value === 'Show solution') { + textarea.value = solutionEntry; + solution.value = 'Hide solution'; + } else { + textarea.value = userEntry; + solution.value = 'Show solution'; + } + updateCode(); +}); + +var jsSolution = 'var list = document.querySelector(\'.output ul\');\nlist.innerHTML = \'\';\nvar stations = [\'MAN675847583748sjt567654;Manchester Piccadilly\',\n \'GNF576746573fhdg4737dh4;Greenfield\',\n \'LIV5hg65hd737456236dch46dg4;Liverpool Lime Street\',\n \'SYB4f65hf75f736463;Stalybridge\',\n \'HUD5767ghtyfyr4536dh45dg45dg3;Huddersfield\'];\n\nfor(var i = 0; i < stations.length; i++) {\n var input = stations[i];\n var code = input.slice(0,3);\n var semiC = input.indexOf(\';\');\n var name = input.slice(semiC + 1);\n var result = code + \': \' + name;\n var listItem = document.createElement(\'li\');\n listItem.textContent = result;\n list.appendChild(listItem);\n}'; +var solutionEntry = jsSolution; + +textarea.addEventListener('input', updateCode); +window.addEventListener('load', updateCode); + +// stop tab key tabbing out of textarea and +// make it write a tab at the caret position instead + +textarea.onkeydown = function(e){ + if (e.keyCode === 9) { + e.preventDefault(); + insertAtCaret('\t'); + } + + if (e.keyCode === 27) { + textarea.blur(); + } +}; + +function insertAtCaret(text) { + var scrollPos = textarea.scrollTop; + var caretPos = textarea.selectionStart; + + var front = (textarea.value).substring(0, caretPos); + var back = (textarea.value).substring(textarea.selectionEnd, textarea.value.length); + textarea.value = front + text + back; + caretPos = caretPos + text.length; + textarea.selectionStart = caretPos; + textarea.selectionEnd = caretPos; + textarea.focus(); + textarea.scrollTop = scrollPos; +} + +// Update the saved userCode every time the user updates the text area code + +textarea.onkeyup = function(){ + // We only want to save the state when the user code is being shown, + // not the solution, so that solution is not saved over the user code + if(solution.value === 'Show solution') { + userEntry = textarea.value; + } else { + solutionEntry = textarea.value; + } + + updateCode(); +};</pre> +</div> + +<p>{{ EmbedLiveSample('Playable_code_3', '100%', 585, "", "", "hide-codepen-jsfiddle") }}</p> + +<h2 id="Conclusión">Conclusión</h2> + +<p>No puedes negar el hecho de que ser capaz de manejar palablas y oraciones en la programación es muy importante — especialmente en JavaScript, ya que los sitios web tratan sobre la comunicación con las personas. Este artículo te ha proporcionado los conceptos básicos que necesitas saber sobre la manipulación de cadenas por ahora. Esto debería servirte bien a medida que abordas temas más complejos en el futuro. A continuación, vamos a ver el último tipo importante de datos en el que necesitamos enfocarnos en el corto plazo — matrices.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/Strings", "Learn/JavaScript/First_steps/Arrays", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Qu%C3%A9_es_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/A_first_splash">Un primer acercamiento a JavaScript</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/What_went_wrong">¿Qué salió mal? Corrigiendo JavaScript</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Variables">Guardando la información que necesitas— Variables</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Matem%C3%A1ticas">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos útiles para el manejo de cadenas</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/First_steps/Arrays">Arreglos</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Silly_story_generator" rel="nofollow">Evaluaciones: Generador de historias absurdas</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/variables/index.html b/files/es/learn/javascript/first_steps/variables/index.html new file mode 100644 index 0000000000..728ad187aa --- /dev/null +++ b/files/es/learn/javascript/first_steps/variables/index.html @@ -0,0 +1,340 @@ +--- +title: Almacenando la información que necesitas - Variables +slug: Learn/JavaScript/First_steps/Variables +tags: + - Arreglos + - Booleanos + - Booleans + - JavaScript + - Numeros + - Objetos + - Variables + - cadenas de texto + - 'l10n:priority' + - strings +translation_of: Learn/JavaScript/First_steps/Variables +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Math", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Después de leer los últimos artículos, deberías saber qué es JavaScript, qué puede hacer por ti, cómo usarlo junto con otras tecnologías web y cómo se ven sus características principales desde un alto nivel. En este artículo, llegaremos a los conceptos básicos reales, y veremos cómo trabajar con los bloques de construcción más básicos de JavaScript — Variables.</p> + +<table class="learn-box"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, comprensión básica de HTML y CSS, comprensión de lo que es JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarte con los conceptos básicos de las variables de JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Herramientas_que_necesitas">Herramientas que necesitas</h2> + +<p>A lo largo de este artículo, se te pedirá que escribas líneas de código para probar tu comprensión del contenido. Si estás utilizando un navegador de escritorio, el mejor lugar para escribir tu código de ejemplo es la consola JavaScript de tu navegador (consulta <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">¿Qué son las herramientas para el desarrollador del navegador?</a> para obtener más información sobre cómo acceder a esta herramienta).</p> + +<h2 id="¿Qué_es_una_variable">¿Qué es una variable?</h2> + +<p>Una variable es un contenedor para un valor, como un número que podríamos usar en una suma, o una cadena que podríamos usar como parte de una oración. Pero una cosa especial acerca de las variables es que los valores que contienen pueden cambiar. Veamos un sencillo ejemplo:</p> + +<pre class="brush: html notranslate"><button>Presióname</button></pre> + +<pre class="brush: js notranslate">const button = document.querySelector('button'); + +button.onclick = function() { + let name = prompt('¿Cuál es tu nombre?'); + alert('¡Hola ' + name + ', encantado de verte!'); +}</pre> + +<p>{{ EmbedLiveSample('What_is_a_variable', '100%', 50, "", "", "hide-codepen-jsfiddle") }}</p> + +<p>En este ejemplo, al presionar el botón se ejecutan un par de líneas de código. La primera línea muestra un cuadro en la pantalla que pide al lector que ingrese su nombre y luego almacena el valor en una variable. La segunda línea muestra un mensaje de bienvenida que incluye su nombre, tomado del valor de la variable.</p> + +<p>Para entender por qué esto es tan útil, pensemos en cómo escribiríamos este ejemplo sin usar una variable. Terminaría luciendo algo como esto:</p> + +<pre class="example-bad notranslate">let name = prompt('¿Cuál es tu nombre?'); + +if (name === 'Adam') { + alert('¡Hola Adam, encantado de verte!'); +} else if (name === 'Alan') { + alert('¡Hola Alan, encantado de verte!'); +} else if (name === 'Bella') { + alert('¡Hola Bella, encantado de verte!'); +} else if (name === 'Bianca') { + alert('¡Hola Bianca, encantado de verte!'); +} else if (name === 'Chris') { + alert('¡Hola Chris, encantado de verte!'); +} + +// ... y así sucesivamente ...</pre> + +<p>Es posible que (¡todavía!) no comprendas completamente la sintaxis que estamos usando, Pero deberías poder hacerte una idea — si no tuviéramos variables disponibles, tendríamos que implementar un bloque de código gigante que verificara cuál era el nombre ingresado, y luego muestra el mensaje apropiado para cualquier nombre. Obviamente, esto realmente es ineficiente (el código es mucho más grande, incluso para solo cinco opciones), y simplemente no funcionaría — no podrías almacenar todas las opciones posibles.</p> + +<p>Las variables simplemente tienen sentido y, a medida que aprendas más sobre JavaScript, comenzarán a convertirse en una segunda naturaleza.</p> + +<p>Otra cosa especial acerca de las variables es que pueden contener casi cualquier cosa, no solo cadenas y números. Las variables también pueden contener datos complejos e incluso funciones completas para hacer cosas asombrosas. Aprenderás más sobre esto a medida que avances.</p> + +<div class="note"> +<p><strong>Nota</strong>: Decimos que las variables contienen valores. Ésta es una importante distinción que debemos reconocer. Las variables no son los valores en sí mismos; son contenedores de valores. Puedes pensar en ellas como pequeñas cajas de cartón en las que puedes guardar cosas.</p> +</div> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13506/boxes.png" style="display: block; height: 436px; margin: 0px auto; width: 1052px;"></p> + +<h2 id="Declarar_una_variable">Declarar una variable</h2> + +<p>Para usar una variable, primero debes crearla — precisamente, a esto lo llamamos declarar la variable. Para hacerlo, escribimos la palabra clave <code>var</code> o <code>let</code> seguida del nombre con el que deseas llamar a tu variable:</p> + +<pre class="brush: js notranslate">let myName; +let myAge;</pre> + +<p>Aquí estamos creando dos variables llamadas <code>myName</code> y <code>myAge</code>. Intenta escribir estas líneas en la consola de tu navegador web. Después de eso, intenta crear una variable (o dos) eligiendo tú su nombre.</p> + +<div class="note"> +<p><strong>Nota</strong>: En JavaScript, todas las instrucciones en el código deben terminar con un punto y coma (<code>;</code>) — tu código puede funcionar correctamente para líneas individuales, pero probablemente no lo hará cuando estés escribiendo varias líneas de código juntas. Trata de adquirir el hábito de incluirlo.</p> +</div> + +<p>Puedes probar si estos valores existen ahora en el entorno de ejecución escribiendo solo el nombre de la variable, p. ej.</p> + +<pre class="brush: js notranslate">myName; +myAge;</pre> + +<p>Actualmente no tienen ningún valor; son contenedores vacíos. Cuando ingreses los nombres de las variables, deberías obtener devuelto un valor <code>undefined</code>. Si no existen, recibirás un mensaje de error; intenta escribir</p> + +<pre class="brush: js notranslate">scoobyDoo;</pre> + +<div class="note"> +<p><strong>Nota</strong>: No confundas una variable que existe pero no tiene un valor definido, con una variable que no existe en absoluto — son cosas muy diferentes. En la analogía de cajas que viste arriba, no existir significaría que no hay una caja (variable) para guardar un valor. Ningún valor definido significaría que HAY una caja, pero no tiene ningún valor dentro de ella.</p> +</div> + +<h2 id="Iniciar_una_variable">Iniciar una variable</h2> + +<p>Una vez que hayas declarado una variable, la puedes iniciar con un valor. Para ello, escribe el nombre de la variable, seguido de un signo igual (<code>=</code>), seguido del valor que deseas darle. Por ejemplo:</p> + +<pre class="brush: js notranslate">myName = 'Chris'; +myAge = 37;</pre> + +<p>Intenta volver a la consola ahora y escribe estas líneas. Deberías ver el valor que le has asignado a la variable devuelto en la consola para confirmarlo, en cada caso. Nuevamente, puedes devolver los valores de tus variables simplemente escribiendo su nombre en la consola; inténtalo nuevamente:</p> + +<pre class="brush: js notranslate">myName; +myAge;</pre> + +<p>Puedes declarar e iniciar una variable al mismo tiempo, así:</p> + +<pre class="brush: js notranslate">let myDog = 'Rover';</pre> + +<p>Esto probablemente es lo que harás la mayor parte del tiempo, ya que es más rápido que realizar las dos acciones en dos líneas separadas.</p> + +<h2 id="Diferencia_entre_var_y_let">Diferencia entre <code>var</code> y <code>let</code></h2> + +<p>En este punto, puedes estar pensando "¿por qué necesitamos dos palabras clave para definir variables? ¿Por qué <code>var</code> <em>y</em> <code>let</code>?".</p> + +<p>Las razones son algo históricas. Cuando se creó JavaScript por primera vez, solo existía <code>var</code>. Esto básicamente funciona bien en la mayoría de los casos, pero tiene algunos problemas en la forma en que trabaja — su diseño a veces puede ser confuso o francamente molesto. Entonces, se creó <code>let</code> en versiones modernas de JavaScript, una nueva palabra clave para crear variables que funciona de manera algo diferente a <code>var</code>, solucionando sus problemas en el proceso.</p> + +<p>A continuación se explican un par de diferencias simples. No abordaremos todas las diferencias ahora, pero comenzarás a descubrirlas a medida que aprendas más sobre JavaScript (si realmente deseas leer sobre ellas ahora, no dudes en consultar {{jsxref("Sentencias/let", "let")}} en nuestra página de referencia.</p> + +<p>Para empezar, si escribes un programa JavaScript de varias líneas que declara e inicia una variable, puedes declarar una variable con <code>var</code> después de iniciarla y seguirá funcionando. Por ejemplo:</p> + +<pre class="brush: js notranslate">myName = 'Chris'; + +function logName() { + console.log(myName); +} + +logName(); + +var myName;</pre> + +<div class="note"> +<p><strong>Nota</strong>: Esto no funcionará al escribir líneas individuales en una consola de JavaScript, solo cuando se ejecutan varias líneas de JavaScript en un documento web.</p> +</div> + +<p>Esto funciona debido a la <strong>elevación</strong> — lee {{jsxref("Sentencias/var", "Elevación de variables", "#Elevación_de_variables")}} para obtener más detalles sobre el tema.</p> + +<p>La elevación (<code>hoisting</code>) ya no funciona con <code>let</code>. Si cambiamos <code>var</code> a <code>let</code> en el ejemplo anterior, fallaría con un error. Esto es bueno — declarar una variable después de iniciarla resulta en un código confuso y más difícil de entender.</p> + +<p>En segundo lugar, cuando usas <code>var</code>, puedes declarar la misma variable tantas veces como desees, pero con <code>let</code> no puedes. Lo siguiente funcionaría:</p> + +<pre class="brush: js notranslate">var myName = 'Chris'; +var myName = 'Bob';</pre> + +<p>Pero lo siguiente arrojaría un error en la segunda línea:</p> + +<pre class="brush: js notranslate">let myName = 'Chris'; +let myName = 'Bob';</pre> + +<p>Tendrías que hacer esto en su lugar:</p> + +<pre class="brush: js notranslate">let myName = 'Chris'; +myName = 'Bob';</pre> + +<p>Nuevamente, esta es una sensata decisión del lenguaje. No hay razón para volver a declarar las variables — solo hace que las cosas sean más confusas.</p> + +<p>Por estas y otras razones, se recomienda utilizar <code>let</code> tanto como sea posible en tu código, en lugar de <code>var</code>. No hay ninguna razón para usar <code>var</code>, a menos que necesites admitir versiones antiguas de Internet Explorer con tu código (no es compatible con <code>let</code> hasta la versión 11; Edge el moderno navegador de Windows admite <code>let</code> perfectamente).</p> + +<h2 id="Actualizar_una_variable">Actualizar una variable</h2> + +<p>Una vez que una variable se ha iniciado con un valor, puedes cambiar (o actualizar) ese valor simplemente dándole un valor diferente. Intenta ingresar las siguientes líneas en tu consola:</p> + +<pre class="brush: js notranslate">myName = 'Bob'; +myAge = 40;</pre> + +<h3 id="Un_consejo_sobre_las_reglas_de_nomenclatura_de_variables">Un consejo sobre las reglas de nomenclatura de variables</h3> + +<p>Puedes llamar a una variable prácticamente como quieras, pero existen limitaciones. En general, debes limitarte a usar caracteres latinos (0-9, a-z, A-Z) y el caracter de subrayado.</p> + +<ul> + <li>No debes usar otros caracteres porque pueden causar errores o ser difíciles de entender para una audiencia internacional.</li> + <li>No use guiones bajos al comienzo de los nombres de las variables — esto se usa en ciertas construcciones de JavaScript para significar cosas específicas, por lo que puede resultar confuso.</li> + <li>No uses números al comienzo de las variables. Esto no está permitido y provoca un error.</li> + <li>Una convención segura a seguir es la llamada <a href="https://en.wikipedia.org/wiki/CamelCase#Variations_and_synonyms">"minúscula mayúsculas intercaladas"</a>, en la que se juntan varias palabras con minúsculas para la primera palabra completa y luego en mayúsculas las primeras letras de las siguientes palabras. Así lo hemos estado haciendo en nuestros nombres de variables en el artículo hasta ahora.</li> + <li>Haz que los nombres de las variables sean intuitivos, para que describan los datos que contienen. No uses solo letras/números o frases grandes y largas.</li> + <li>Las variables distinguen entre mayúsculas y minúsculas — por lo tanto <code>myage</code> es una variable diferente de <code>myAge</code>.</li> + <li>Un último punto: también debes evitar el uso de palabras reservadas de JavaScript como nombres de variables — con esto, nos referimos a las palabras que componen la sintaxis real de JavaScript. Por lo tanto, no puedes usar palabras como <code>var</code>, <code>function</code>, <code>let</code> y <code>for</code> como nombres de variables. Los navegadores las reconocen como elementos de código diferentes, por lo que obtendrás errores.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Puedes encontrar una lista bastante completa de palabras clave reservadas que debes evitar en {{jsxref("Gramática_léxica", "Gramática léxica — Palabras clave", "#Palabras_clave")}}.</p> +</div> + +<p>Ejemplos de buenos nombres:</p> + +<pre class="example-good notranslate">age +myAge +init +initialColor +finalOutputValue +audio1 +audio2</pre> + +<p>Ejemplos de nombres incorrectos:</p> + +<pre class="example-bad notranslate">1 +a +_12 +myage +MYAGE +var +Document +skjfndskjfnbdskjfb +thisisareallylongstupidvariablenameman</pre> + +<p>Ahora, intenta crear algunas variables más, con la guía anterior en mente.</p> + +<h2 id="Tipo_de_las_variables">Tipo de las variables</h2> + +<p>Hay algunos tipos de datos diferentes que podemos almacenar en variables. En esta sección, los describiremos brevemente, luego, en artículos futuros, aprenderás más detalles.</p> + +<p>Hasta ahora hemos analizado los dos primeros, pero hay otros.</p> + +<h3 id="Números">Números</h3> + +<p>Puedes almacenar números en variables, ya sea números enteros como 30 (también llamados enteros — "<code>integer</code>") o números decimales como 2.456 (también llamados números flotantes o de coma flotante — "<code>number</code>"). No es necesario declarar el tipo de las variables en JavaScript, a diferencia de otros lenguajes de programación. Cuando le das a una variable un valor numérico, no incluye comillas:</p> + +<pre class="brush: js notranslate">let myAge = 17;</pre> + +<h3 id="Cadenas_de_caracteres_Strings">Cadenas de caracteres (<code>String</code>s)</h3> + +<p>Las <code>string</code>s (cadenas) son piezas de texto. Cuando le das a una variable un valor de cadena, debes encerrarlo entre comillas simples o dobles; de lo contrario, JavaScript intenta interpretarlo como otro nombre de variable.</p> + +<pre class="brush: js notranslate">let dolphinGoodbye = 'Hasta luego y gracias por todos los peces';</pre> + +<h3 id="Booleanos">Booleanos</h3> + +<p>Los booleanos son valores verdadero/falso — pueden tener dos valores, <code>true</code> o <code>false</code>. Estos, generalmente se utilizan para probar una condición, después de lo cual se ejecuta el código según corresponda. Así, por ejemplo, un caso simple sería:</p> + +<pre class="brush: js notranslate">let iAmAlive = true;</pre> + +<p>Mientras que en realidad se usaría más así:</p> + +<pre class="brush: js notranslate">let test = 6 < 3;</pre> + +<p>Aquí se está usando el operador "menor que" (<code><</code>) para probar si 6 es menor que 3. Como era de esperar, devuelve <code>false</code>, ¡porque 6 no es menor que 3! Aprenderás mucho más sobre estos operadores más adelante en el curso.</p> + +<h3 id="Arreglos">Arreglos</h3> + +<p>Un arreglo es un objeto único que contiene múltiples valores encerrados entre corchetes y separados por comas. Intenta ingresar las siguientes líneas en tu consola:</p> + +<pre class="brush: js notranslate">let myNameArray = ['Chris', 'Bob', 'Jim']; +let myNumberArray = [10, 15, 40];</pre> + +<p>Una vez que se definen estos arreglos, puedes acceder a cada valor por su ubicación dentro del arreglo. Prueba estas líneas:</p> + +<pre class="brush: js notranslate">myNameArray[0]; // debería devolver 'Chris' +myNumberArray[2]; // debe devolver 40</pre> + +<p>Los corchetes especifican un valor de índice correspondiente a la posición del valor que deseas devolver. Posiblemente hayas notado que los arreglos en JavaScript tienen índice cero: el primer elemento está en el índice 0.</p> + +<p>Aprenderás mucho más sobre los arreglos en <a href="/es/docs/Learn/JavaScript/First_steps/Arrays">un futuro artículo</a>.</p> + +<h3 id="Objetos">Objetos</h3> + +<p>En programación, un objeto es una estructura de código que modela un objeto de la vida real. Puedes tener un objeto simple que represente una caja y contenga información sobre su ancho, largo y alto, o podrías tener un objeto que represente a una persona y contenga datos sobre su nombre, estatura, peso, qué idioma habla, cómo saludarlo, y más.</p> + +<p>Intenta ingresar la siguiente línea en tu consola:</p> + +<pre class="brush: js notranslate">let dog = { name : 'Spot', breed : 'Dalmatian' };</pre> + +<p>Para recuperar la información almacenada en el objeto, puedes utilizar la siguiente sintaxis:</p> + +<pre class="brush: js notranslate">dog.name</pre> + +<p>Por ahora, no veremos más objetos. Puedes obtener más información sobre ellos en <a href="/es/docs/Learn/JavaScript/Objects">un futuro módulo</a>.</p> + +<h2 id="Tipado_dinámico">Tipado dinámico</h2> + +<p>JavaScript es un "lenguaje tipado dinámicamente", lo cual significa que, a diferencia de otros lenguajes, no es necesario especificar qué tipo de datos contendrá una variable (números, cadenas, arreglos, etc.).</p> + +<p>Por ejemplo, si declaras una variable y le das un valor entre comillas, el navegador trata a la variable como una cadena (<code>string</code>):</p> + +<pre class="brush: js notranslate">let myString = 'Hello';</pre> + +<p>Incluso si el valor contiene números, sigue siendo una cadena, así que ten cuidado:</p> + +<pre class="brush: js notranslate">let myNumber = '500'; // Vaya, esto sigue siendo una cadena +typeof myNumber; +myNumber = 500; // mucho mejor — ahora este es un número +typeof myNumber;</pre> + +<p>Intenta ingresar las cuatro líneas anteriores en tu consola una por una y ve cuáles son los resultados. Notarás que estamos usando un operador especial llamado {{jsxref("Operadores/typeof", "typeof")}} — esto devuelve el tipo de datos de la variable que escribes después. La primera vez que se llama, debe devolver <code>string</code>, ya que en ese punto la variable <code>myNumber</code> contiene una cadena, <code>'500'</code>. Échale un vistazo y ve qué devuelve la segunda vez que lo llamas.</p> + +<h2 id="Constantes_en_JavaScript">Constantes en JavaScript</h2> + +<p>Muchos lenguajes de programación tienen el concepto de una <em>constante</em> — un valor que, una vez declarado no se puede cambiar. Hay muchas razones por las que querrías hacer esto, desde la seguridad (si un script de un tercero cambia dichos valores, podría causar problemas) hasta la depuración y la comprensión del código (es más difícil cambiar accidentalmente valores que no se deben cambiar y estropear cosas claras).</p> + +<p>En los primeros días de JavaScript, las constantes no existían. En JavaScript moderno, tenemos la palabra clave <code>const</code>, que nos permite almacenar valores que nunca se pueden cambiar:</p> + +<pre class="brush: js notranslate">const daysInWeek = 7<span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number">; +const hoursInDay = 24;</span></span></span></span></pre> + +<p><span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number"><code>const</code> funciona exactamente de la misma manera que <code>let</code>, excepto que a <code>const</code> no le puedes dar un nuevo valor. En el siguiente ejemplo, la segunda línea arrojará un error:</span></span></span></span></p> + +<pre class="brush: js notranslate">const daysInWeek = 7<span class="message-body-wrapper"><span class="message-flex-body"><span class="devtools-monospace message-body"><span class="objectBox objectBox-number">; +daysInWeek = 8;</span></span></span></span></pre> + +<h2 id="¡Pon_a_prueba_tus_habilidades!">¡Pon a prueba tus habilidades!</h2> + +<p>Has llegado al final de este artículo, pero ¿puedes recordar la información más importante? Puedes encontrar más pruebas para verificar que has retenido esta información antes de continuar — consulta <a href="/es/docs/Learn/JavaScript/First_steps/Test_your_skills:_variables">Pon a prueba tus habilidades: variables</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>A estas alturas, deberías saber bastante sobre las variables de JavaScript y cómo crearlas. En el próximo artículo, nos centraremos en los números con más detalle, y veremos cómo hacer matemáticas básicas en JavaScript.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/What_went_wrong", "Learn/JavaScript/First_steps/Maths", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_is_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/A_first_splash">Un primer acercamiento a JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_went_wrong">¿Qué salió mal? Solución de problemas de JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Variables">Almacenar la información que necesitas — Variables</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Math">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Útiles métodos de cadena</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Arrays">Arreglos</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Silly_story_generator">Evaluación: Generador de historias absurdas</a></li> +</ul> diff --git a/files/es/learn/javascript/first_steps/what_went_wrong/index.html b/files/es/learn/javascript/first_steps/what_went_wrong/index.html new file mode 100644 index 0000000000..af36c20852 --- /dev/null +++ b/files/es/learn/javascript/first_steps/what_went_wrong/index.html @@ -0,0 +1,268 @@ +--- +title: ¿Qué ha salido mal? Corrigiendo JavaScript +slug: Learn/JavaScript/First_steps/What_went_wrong +tags: + - Aprender + - Artículo + - CodingScripting + - Debugging + - Depurando + - Error + - Herramientas de Desarrollador + - JavaScript + - Novato + - Principiante + - Tutorial + - console.log + - depurar + - 'l10n:priority' +translation_of: Learn/JavaScript/First_steps/What_went_wrong +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}</div> + +<p class="summary">Cuando construiste el juego "Adivina el número" en el artículo anterior, es posible que hayas descubierto que no funcionó. Tranquilo — este artículo tiene como objetivo evitar que te rasques la cabeza por este tipo de problemas brindándote algunos consejos sobre cómo encontrar y corregir errores en programas JavaScript.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Conocimientos básicos de informática, comprensión básica de HTML y CSS, comprensión de lo que es JavaScript.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para ganar habilidad y confianza para comenzar a solucionar problemas en tu propio código.</td> + </tr> + </tbody> +</table> + +<h2 id="Tipos_de_errores">Tipos de errores</h2> + +<p>En general, cuando haces algo mal en el código, hay dos tipos principales de errores con los que te encontrarás:</p> + +<ul> + <li><strong>Errores de sintaxis</strong>: estos son errores de ortografía en tu código que provocan que tu programa no se ejecute en absoluto, o que deje de funcionar a mitad del camino — por lo general, también te proporcionarán algunos mensajes de error. Normalmente no es tan difícil corregirlos, ¡siempre y cuando estés familiarizado con las herramientas adecuadas y sepas qué significan los mensajes de error!</li> + <li><strong>Errores lógicos</strong>: Estos son errores en los que la sintaxis realmente es correcta pero el código no hace lo que pretendías, lo cual significa que el programa se ejecuta pero da resultados incorrectos. A menudo, estos son más difíciles de arreglar que los errores sintácticos, ya que generalmente no hay un mensaje de error que te pueda orientar hacia la fuente del error.</li> +</ul> + +<p>Bueno, tampoco es <em>así de simple</em> — a medida que profundices hay algunas otras diferencias. Pero las clasificaciones anteriores funcionarán en esta temprana etapa de tu carrera. Veremos ambos tipos en el futuro.</p> + +<h2 id="Un_ejemplo_erróneo">Un ejemplo erróneo</h2> + +<p>Para empezar, regresemos a nuestro juego de adivinan el número — excepto que esta vez vamos a explorar una versión que tiene algunos errores insertados deliberadamente. Ve a GitHub y haz una copia local de <a href="https://github.com/mdn/learning-area/blob/master/javascript/introduction-to-js-1/troubleshooting/number-game-errors.html">number-game-errors.html</a> (puedes verlo <a href="http://mdn.github.io/learning-area/javascript/introduction-to-js-1/troubleshooting/number-game-errors.html">en vivo aquí</a>).</p> + +<ol> + <li>Para comenzar, abre la copia local dentro de tu editor de texto favorito y tu navegador.</li> + <li>Intenta jugarlo — notarás que cuando presionas el botón "Enviar respuesta", ¡no funciona!</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: ¡Posiblemente tengas tu propia versión del ejemplo del juego que no funciona, y quizás la quieras arreglar! Aún así nos gustaría que en el artículo trabajes con nuestra versión, para que puedas aprender las técnicas que estamos enseñando. Después puedes tratar de arreglar tu ejemplo.</p> +</div> + +<p>En este punto, consultemos la consola del desarrollador para ver si podemos ver algún informe de error de sintaxis y luego tratar de solucionarlo. Abajo aprenderás cómo.</p> + +<h2 id="Solucionar_errores_de_sintaxis">Solucionar errores de sintaxis</h2> + +<p>Anteriormente en este curso, hicimos que escribieras algunos comandos JavaScript simples en la <a href="/es/docs/Learn/Common_questions/What_are_browser_developer_tools">consola JavaScript de las herramientas para desarrolladores</a> (si no recuerdas cómo abrirla en tu navegador, sigue el enlace anterior para descubrirlo). Lo más útil es que la consola te brinda mensajes de error cada vez que ocurre algún error de sintaxis dentro del JavaScript que alimenta al motor JavaScript del navegador. Ahora vayamos a cazar.</p> + +<ol> + <li>Ve a la pestaña dónde tienes abierto <code>number-game-errors.html</code> y abre tu consola JavaScript. Deberías ver un mensaje de error con las siguientes líneas: <img alt="" src="https://mdn.mozillademos.org/files/13496/not-a-function.png" style="display: block; margin: 0 auto;"></li> + <li>Este es un error bastante fácil de rastrear, y el navegador le brinda varios bits de información útil para ayudarte (la captura de pantalla anterior es de Firefox, pero otros navegadores proporcionan información similar). De izquierda a derecha, tenemos: + <ul> + <li>Una "x" roja para indicar que se trata de un error.</li> + <li>Un mensaje de error para indicar qué salió mal: "TypeError: guessSubmit.addeventListener no es una función"</li> + <li>Un enlace a "Más información" que te lleva a una página de MDN dónde explica detalladamente qué significa este error.</li> + <li>El nombre del archivo JavaScript, que enlaza con la pestaña "Depurador" de las herramientas para desarrolladores. Si sigues este enlace, verás la línea exacta donde se resalta el error.</li> + <li>El número de línea donde está el error y el número de carácter en esa línea donde se detectó el error por primera vez. En este caso, tenemos la línea 86, carácter número 3.</li> + </ul> + </li> + <li>Si miramos la línea 86 en nuestro editor de código, encontraremos esta línea: + <pre class="brush: js notranslate">guessSubmit.addeventListener('click', checkGuess);</pre> + </li> + <li>El mensaje de error dice "<code>guessSubmit.addeventListener no es una función</code>", lo cual significa que el intérprete de JavaScript no reconoce la función que estamos llamando. A menudo, este mensaje de error en realidad significa que hemos escrito algo mal. Si no estás seguro de la ortografía correcta de una parte de la sintaxis, a menudo es bueno buscar la función en MDN. La mejor manera de hacer esto es, en tu navegador favorito, buscar "mdn <em>nombre-de-característica</em>". Aquí hay un atajo para ahorrarte algo de tiempo en esta instancia: <code><a href="/es/docs/Web/API/EventTarget/addEventListener">addEventListener()</a></code>.</li> + <li>Entonces, al mirar esta página, ¡el error parece ser que hemos escrito mal el nombre de la función!. Recuerda que JavaScript distingue entre mayúsculas y minúsculas, por lo que cualquier pequeña diferencia en la ortografía o en mayúsculas provocará un error. Cambiar <code>addeventListener</code> a <code>addEventListener</code> debería solucionar este problema. Hazlo ahora.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Échale un vistazo a nuestra página de referencia <a href="/es/docs/Web/JavaScript/Reference/Errors/Not_a_function">TypeError: "x" no es una función</a> para obtener más detalles sobre este error.</p> +</div> + +<h3 id="Errores_sintácticos_segunda_ronda">Errores sintácticos, segunda ronda</h3> + +<ol> + <li>Guarda tu página y refréscala, ahora deberías ver que el error ha desaparecido.</li> + <li>Ahora, si intentas ingresar un número y presionas el botón "Enviar respuesta", verás... ¡otro error! <img alt="" src="https://mdn.mozillademos.org/files/13498/variable-is-null.png" style="display: block; margin: 0 auto;"></li> + <li>Esta vez, el error que se informa es "<code>TypeError: lowOrHi es nulo</code>", en la línea 78. + <div class="note"><strong>Nota</strong>: <code><a href="/es/docs/Glossary/Null">Null</a></code> es un valor especial que significa "nada" o "sin valor". Por lo tanto, <code>lowOrHi</code> ha sido declarado e iniciado, pero no con algún valor significativo — no tiene tipo ni valor.</div> + + <div class="note"><strong>Nota</strong>: Este error no apareció tan pronto como se cargó la página porque este error ocurrió dentro de una función (dentro del bloque <code>checkGuess() {...}</code>). Como pronto aprenderás con más detalle en nuestro <a href="/es/docs/Learn/JavaScript/Building_blocks/Functions">artículo de funciones</a>, el código dentro de las funciones se ejecuta en un ámbito separado que el código fuera de las funciones. En este caso, el código no se ejecutó y el error no se lanzó hasta que la función <code>checkGuess()</code> se ejecutó en la línea 86.</div> + </li> + <li>Échale un vistazo a la línea 78 y verás el siguiente código: + <pre class="brush: js notranslate">lowOrHi.textContent = '¡El número es muy grande!';</pre> + </li> + <li>Esta línea está intentando establecer la propiedad <code>textContent</code> de la constante <code>lowOrHi</code> en una cadena de texto, pero no funciona porque <code>lowOrHi</code> no contiene lo que es supone. Veamos por qué es así — intenta buscar otras instancias de <code>lowOrHi</code> en el código. La primera instancia que encontrarás en JavaScript está en la línea 48: + <pre class="brush: js notranslate">const lowOrHi = document.querySelector('lowOrHi');</pre> + </li> + <li>En este punto, estamos intentando hacer que la variable contenga una referencia a un elemento en el HTML del documento. Comprobemos si el valor es <code>null</code> después de ejecutar esta línea. Agrega el siguiente código en la línea 49: + <pre class="brush: js notranslate">console.log(lowOrHi);</pre> + + <div class="note"> + <p><strong>Nota</strong>: <code><a href="/es/docs/Web/API/Console/log">console.log()</a></code> es una función de depuración realmente útil que imprime un valor en la consola. Por lo tanto, imprimirá el valor de <code>lowOrHi</code> en la consola tan pronto como intentemos configurarlo en la línea 48.</p> + </div> + </li> + <li>Guarda y refresca, y ahora deberías ver el resultado de <code>console.log()</code> en tu consola. <img alt="" src="https://mdn.mozillademos.org/files/13494/console-log-output.png" style="display: block; margin: 0 auto;">Efectivamente, el valor de <code>lowOrHi</code>es <code>null</code> en este punto, así que definitivamente hay un problema con la línea 48.</li> + <li>Pensemos en cuál podría ser el problema. La línea 48 está utilizando un método <code><a href="/es/docs/Web/API/Document/querySelector">document.querySelector()</a></code> para obtener una referencia a un elemento seleccionándolo con un selector CSS. Buscando más adelante en nuestro archivo, podemos encontrar el párrafo en cuestión: + <pre class="brush: js notranslate"><p class="lowOrHi"></p></pre> + </li> + <li>Entonces necesitamos un selector de clase aquí, que comienza con un punto (<code>.</code>), pero el selector que se pasa al método <code>querySelector()</code> en la línea 48 no tiene punto. ¡Este podría ser el problema! Intenta cambiar <code>lowOrHi</code> a <code>.lowOrHi</code> en la línea 48.</li> + <li>Ahora guarda y refresca nuevamente, y tu declaración <code>console.log()</code> debería devolver el elemento <code><p></code> que queremos. ¡Uf! ¡Otro error solucionado! Ahora puedes eliminar tu línea <code>console.log()</code>, o mantenerla como referencia más adelante — tu elección.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Consulta nuestra página de referencia <a href="/es/docs/Web/JavaScript/Reference/Errors/Unexpected_type">TypeError: "x" (no) es "y"</a> para obtener más detalles sobre este error.</p> +</div> + +<h3 id="Errores_sintácticos_tercera_ronda">Errores sintácticos, tercera ronda</h3> + +<ol> + <li>Ahora, si intentas jugar de nuevo, deberías tener más éxito — el juego debería funcionar absolutamente bien, hasta que termines el juego, ya sea adivinando el número correcto o porque agotaste los intentos.</li> + <li>En ese momento, el juego vuelve a fallar y lanza el mismo error que obtuvimos al principio: "<code>TypeError: resetButton.addeventListener no es una función</code>". Sin embargo, esta vez aparece como procedente de la línea 94.</li> + <li>Mirando la línea número 94, es fácil ver que hemos cometido el mismo error aquí. Nuevamente, solo necesitamos cambiar <code>addeventListener</code> a <code>.addEventListener</code>. Hazlo ahora.</li> +</ol> + +<h2 id="Un_error_de_lógica">Un error de lógica</h2> + +<p>En este punto, el juego debería trabajar bien, sin embargo, después de jugar varias veces, sin duda notarás que el número "aleatorio" que debes adivinar siempre es 1. ¡Definitivamente no es exactamente como queremos que se desarrolle el juego!</p> + +<p>Obviamente hay un problema en la lógica del juego en alguna parte — el juego no devuelve un error; simplemente no está jugando bien.</p> + +<ol> + <li>Busca la variable <code>randomNumber</code> y las líneas donde se establece primero el número aleatorio. La instancia que almacena el número aleatorio que queremos adivinar al comienzo del juego debe estar alrededor de la línea número 44: + + <pre class="brush: js notranslate">let randomNumber = Math.floor(Math.random()) + 1;</pre> + Y la que genera el número aleatorio antes de cada juego subsiguiente está alrededor de la línea 113:</li> + <li> + <pre class="brush: js notranslate">randomNumber = Math.floor(Math.random()) + 1;</pre> + </li> + <li>Para comprobar si estas líneas son realmente el problema, volvamos a echar mano de nuestra amiga <code>console.log()</code> — inserta la siguiente línea directamente debajo de cada una de las dos líneas anteriores: + <pre class="brush: js notranslate">console.log(randomNumber);</pre> + </li> + <li>Guarda y refresca, luego juega un par de veces — verás que <code>randomNumber</code> es igual a 1 en cada punto en el que se registra en la consola.</li> +</ol> + +<h3 id="Desentrañando_la_lógica">Desentrañando la lógica</h3> + +<p>Para solucionar esto, consideremos cómo está funcionando esta línea. Primero, invocamos a <code><a href="/es/docs/Web/JavaScript/Reference/Global_Objects/Math/random">Math.random()</a></code>, que genera un número decimal aleatorio entre 0 y 1, p. ej. 0.5675493843.</p> + +<pre class="brush: js notranslate">Math.random()</pre> + +<p>A continuación, pasamos el resultado de invocar a <code>Math.random()</code> a <code><a href="/es/docs/Web/JavaScript/Reference/Global_Objects/Math/floor">Math.floor()</a></code>, que redondea el número pasado al número entero más cercano. Luego agregamos 1 a ese resultado:</p> + +<pre class="notranslate">Math.floor(Math.random()) + 1</pre> + +<p>Redondear un número decimal aleatorio entre 0 y 1 siempre devolverá 0, por lo que agregarle 1 siempre devolverá 1. Necesitamos multiplicar el número aleatorio por 100 antes de redondearlo hacia abajo. Lo siguiente nos daría un número aleatorio entre 0 y 99:</p> + +<pre class="brush: js notranslate">Math.floor(Math.random()*100);</pre> + +<p>De ahí que queramos sumar 1, para darnos un número aleatorio entre 1 y 100:</p> + +<pre class="brush: js notranslate">Math.floor(Math.random()*100) + 1;</pre> + +<p>Intenta actualizar ambas líneas de esta manera, luego guarda y refresca — ¡el juego ahora debería trabajar como pretendemos!</p> + +<h2 id="Otros_errores_comunes">Otros errores comunes</h2> + +<p>Hay otros errores comunes que encontrarás en tu código. Esta sección destaca la mayoría de ellos.</p> + +<h3 id="SyntaxError_falta_antes_de_la_declaración">SyntaxError: <code>falta ; antes de la declaración</code></h3> + +<p>Este error generalmente significa que has omitido un punto y coma al final de una de sus líneas de código, pero a veces puede ser más críptico. Por ejemplo, si cambiamos esta línea dentro de la función <code>checkGuess()</code>:</p> + +<pre class="brush: js notranslate">var userGuess = Number(guessField.value);</pre> + +<p>a</p> + +<pre class="brush: js notranslate">var userGuess === Number(guessField.value);</pre> + +<p>Lanza este error porque cree que estás intentando hacer algo diferente. Debes asegurarte de no confundir el operador de asignación (<code>=</code>), que establece una variable para que sea igual a un valor — con el operador de igualdad estricta (<code>===</code>), que prueba si un valor es igual a otro y devuelve un resultado <code>true</code>/<code>false</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Ve más detalles sobre este error en nuestra página de referencia <a href="/es/docs/Web/JavaScript/Reference/Errors/Missing_semicolon_before_statement">SyntaxError: falta ; antes de la declaración</a>.</p> +</div> + +<h3 id="El_programa_siempre_dice_que_has_ganado_independientemente_de_lo_que_hayas_ingresado">El programa siempre dice que has ganado, independientemente de lo que hayas ingresado</h3> + +<p>Este podría ser otro síntoma de confusión entre la asignación y los operadores de igualdad estricta. Por ejemplo, si cambiamos esta línea dentro de <code>checkGuess()</code>:</p> + +<pre class="brush: js notranslate">if (userGuess === randomNumber) {</pre> + +<p>a</p> + +<pre class="brush: js notranslate">if (userGuess = randomNumber) {</pre> + +<p>la prueba siempre devolvería <code>true</code>, haciendo que el programa informe que se ganó el juego. ¡Ten cuidado!</p> + +<h3 id="SyntaxError_falta_después_de_la_lista_de_argumentos">SyntaxError: <code>falta ) después de la lista de argumentos</code></h3> + +<p>Este es bastante simple — generalmente significa que olvidaste colocar el paréntesis de cierre al final de una llamada a una función/método.</p> + +<div class="note"> +<p><strong>Nota</strong>: Ve más detalles sobre este error en nuestra página de referencia <a href="/es/docs/Web/JavaScript/Reference/Errors/Missing_parenthesis_after_argument_list">SyntaxError: falta ) después de la lista de argumentos</a>.</p> +</div> + +<h3 id="SyntaxError_falta_después_de_la_propiedad_id">SyntaxError: <code>falta : después de la propiedad id</code></h3> + +<p>Este error generalmente se relaciona con un objeto JavaScript formado incorrectamente, pero en este caso logramos obtenerlo cambiando</p> + +<pre class="brush: js notranslate">function checkGuess() {</pre> + +<p>a</p> + +<pre class="brush: js notranslate">function checkGuess( {</pre> + +<p>Esto ha hecho que el navegador piense que estamos tratando de pasar el contenido de la función a la función como un argumento. ¡Cuidado con esos paréntesis!</p> + +<h3 id="SyntaxError_falta_después_del_cuerpo_de_la_función">SyntaxError: <code>falta } después del cuerpo de la función</code></h3> + +<p>Esto es fácil — generalmente significa que has omitido una de tus llaves de una función o estructura condicional. Obtuvimos este error al eliminar una de las llaves de cierre cerca de la parte inferior de la función <code>checkGuess()</code>.</p> + +<h3 id="SyntaxError_esperaba_expresión_obtuve_string_o_SyntaxError_Cadena_literal_sin_terminar">SyntaxError: <code>esperaba expresión, obtuve '<em>string</em>'</code> o SyntaxError: <code>Cadena literal sin terminar</code></h3> + +<p>Estos errores generalmente significan que has omitido las comillas de apertura o cierre de un valor de cadena. En el primer error anterior, <em>string</em> se reemplazaría con los caracteres inesperados que encontró el navegador en lugar de una comilla al comienzo de una cadena. El segundo error significa que la cadena no se ha terminado con comillas.</p> + +<p>Para todos estos errores, piensa en cómo abordamos los ejemplos que vimos en el tutorial. Cuando surge un error, mira el número de línea que te dan, ve a esa línea y revísala para detectar lo que está mal. Ten en cuenta que el error no necesariamente estará en esa línea, y también que el error podría no ser causado por el mismo problema que mencionamos anteriormente.</p> + +<div class="note"> +<p><strong>Nota</strong>: Obtén más detalles sobre estos errores en nuestras páginas de referencia <a href="/es/docs/Web/JavaScript/Reference/Errors/Unexpected_token">SyntaxError: símbolo inesperado</a> y <a href="/es/docs/Web/JavaScript/Reference/Errors/Unterminated_string_literal">SyntaxError: cadena literal sin terminar</a>.</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahí lo tienes, los conceptos básicos para descubrir errores en programas sencillos de JavaScript. No siempre será tan sencillo averiguar qué está mal en tu código, pero al menos esto te ahorrará algunas horas de sueño y te permitirá progresar un poco más rápido cuando las cosas no salgan bien, especialmente en las primeras etapas de tu viaje de aprendizaje.</p> + +<h2 id="Ve_también">Ve también</h2> + +<div> +<ul> + <li>Hay muchos otros tipos de errores que no se enumeran aquí; estamos compilando una referencia que explica lo que significan en detalle; consulta la <a href="/es/docs/Web/JavaScript/Reference/Errors">referencia de error de JavaScript</a>.</li> + <li>Si encuentras algún error en tu código que no estás seguro de cómo solucionarlo después de leer este artículo, ¡puedes obtener ayuda! Solicita ayuda en la <a href="https://discourse.mozilla.org/c/mdn/learn">categoría de aprendizaje del foro de discusión de MDN</a>, o en la <a href="https://chat.mozilla.org/#/room/#mdn:mozilla.org">sala de MDN Web Docs</a> en <a class="external external-icon" href="https://wiki.mozilla.org/Matrix">Matrix</a>. Dinos cuál es tu error e intentaremos ayudarte. Una copia de tu código también sería útil.</li> +</ul> +</div> + +<p>{{PreviousMenuNext("Learn/JavaScript/First_steps/A_first_splash", "Learn/JavaScript/First_steps/Variables", "Learn/JavaScript/First_steps")}}</p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_is_JavaScript">¿Qué es JavaScript?</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/A_first_splash">Primer contacto con JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/What_went_wrong">¿Qué salió mal? Solución de problemas de JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Variables">Almacenamiento de la información que necesita — Variables</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Math">Matemáticas básicas en JavaScript — números y operadores</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Strings">Manejo de texto — cadenas en JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Useful_string_methods">Métodos de cadena útiles</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Arrays">Arreglos</a></li> + <li><a href="/es/docs/Learn/JavaScript/First_steps/Silly_story_generator">Evaluación: Generador de historias absurdas</a></li> +</ul> diff --git a/files/es/learn/javascript/howto/index.html b/files/es/learn/javascript/howto/index.html new file mode 100644 index 0000000000..b0abd6c044 --- /dev/null +++ b/files/es/learn/javascript/howto/index.html @@ -0,0 +1,317 @@ +--- +title: Resuelva problemas comunes en su código JavaScript +slug: Learn/JavaScript/Howto +tags: + - Aprendizaje + - JavaScript + - Principante +translation_of: Learn/JavaScript/Howto +--- +<div>{{LearnSidebar}}</div> + +<p class="summary"></p> + +<p class="summary">Los siguientes enlaces apuntan a soluciones a problemas comunes de todos los días que deberá solucionar para que su código JavaScript se ejecute correctamente..</p> + +<h2 id="Errores_comunes_de_principiante">Errores comunes de principiante</h2> + +<h3 id="Correcta_ortografía_y_casing">Correcta ortografía y casing</h3> + + + +<p>Si su código no funciona y / o el navegador se queja de que algo no está definido, verifique que haya escrito todos sus nombres de variables, nombres de funciones, etc. correctamente. </p> + + + +<p>Algunas funciones comunes del navegador incorporado que causan problemas son:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Correcto</th> + <th scope="col">Incorrecto</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>getElementsByTagName()</code></td> + <td><code>getElementbyTagName()</code></td> + </tr> + <tr> + <td><code>getElementsByName()</code></td> + <td><code>getElementByName()</code></td> + </tr> + <tr> + <td><code>getElementsByClassName()</code></td> + <td><code>getElementByClassName()</code></td> + </tr> + <tr> + <td><code>getElementById()</code></td> + <td><code>getElementsById()</code></td> + </tr> + </tbody> +</table> + +<h3 id="Posición_de_punto_y_coma">Posición de punto y coma</h3> + +<p>Debes estar seguro de no colocar ningún punto y coma incorrectamente. Por ejemplo:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Correcto</th> + <th scope="col">Incorrecto</th> + </tr> + <tr> + <td><code>elem.style.color = 'red';</code></td> + <td><code>elem.style.color = 'red;'</code></td> + </tr> + </thead> +</table> + +<h3 id="Funciones">Funciones</h3> + +<p>Hay una serie de cosas que pueden salir mal con la funciones.</p> + +<p>Uno de los errores más comunes es declarar una función, pero no llamarla a ninguna parte, Por ejemplo:</p> + +<pre class="brush: js">function miFuncion() { + alert('Esta es mi funcion.'); +};</pre> + +<p>Este código no hará nada a menos que lo llame, por ejemplo con</p> + +<pre class="brush: js">miFuncion();</pre> + +<h4 id="Alcance_de_la_función">Alcance de la función</h4> + + + +<p>Recuerda que las <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions#Function_scope_and_conflicts">funciones tienen su propio alcance</a> — no puedes acceder a un valor de variable establecido dentro de una función desde fuera de la función, a menos que haya declarado la variable globalmente (es decir, no dentro de ninguna función), o <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">retornar el valor</a> fuera de la función.</p> + +<h4 id="Ejecución_de_código_después_de_una_declaración_de_retorno_(Return)">Ejecución de código después de una declaración de retorno (Return)</h4> + + + +<p>Recuerde también que cuando devuelve un valor de una función, el intérprete de JavaScript sale de la función — ningún código declarado después de que se ejecute la declaración de devolución (Return).</p> + +<p>De hecho, algunos navegadores (como Firefox) le darán un mensaje de error en la consola del desarrollador si tiene código después de una declaración de devolución. Firefox te ofrece "código inalcanzable después de la declaración de devolución".</p> + +<p>Mas abajo podemos observar una función de saludo, posterior a retornar intentamos asignar a la variable x, el valor de la propiedad que viene en la función. Esto nunca ocurrira ya que posterior a retornar un valor se sale del contexto función. En pocas palabras jamas ocurrira la asignación.</p> + +<p>Ejemplo de una declaración posterior a una declaración de retorno:</p> + +<pre><code>function saludo(nombre){</code> + return "Hola, " + nombre + " que bueno que volviste"; + var x = nombre; //Esta linea jamas se ejecutara ya que viene despues de un retorno +<code>}</code></pre> + +<h3 id="Notación_de_objetos_versus_asignación_normal">Notación de objetos versus asignación normal</h3> + + + +<p>Cuando asigna algo normalmente en JavaScript, utiliza un solo signo igual, por ejemplo:</p> + +<pre class="brush: js">const miNumero= 0;</pre> + +<p>Esto no funciona en los <a href="/en-US/docs/Learn/JavaScript/Objects">Objetos</a>, sin embargo, con los objetos, debe separar los nombres de los miembros de sus valores mediante dos puntos y separar cada miembro con una coma, por ejemplo:</p> + +<pre class="brush: js">const miObjeto= { + nombre: 'Felipe', + edad: 27 +}</pre> + +<h2 id="Definiciones_básicas">Definiciones básicas</h2> + +<div class="column-container"> +<div class="column-half"> +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript#A_high-level_definition">¿Qué es JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables#What_is_a_variable">¿Qué es una variable?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings">¿Qué son los Strings?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays#What_is_an_Array">¿Qué es una matriz?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">¿Qué es un bucle?</a></li> +</ul> +</div> + +<div class="column-half"> +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions">¿Qué es una función?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events">¿Qué es un evento?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics#Object_basics">¿Qué es un objeto?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON#No_really_what_is_JSON">¿Qué es JSON?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Introduction#What_are_APIs">¿Qué es una API web?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents#The_document_object_model">¿Qué es el DOM?</a></li> +</ul> +</div> +</div> + +<h2 id="Casos_de_uso_básico">Casos de uso básico</h2> + +<div class="column-container"> +<div class="column-half"> +<h3 id="General">General</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript#How_do_you_add_JavaScript_to_your_page">¿Cómo agrega JavaScript a su página?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_is_JavaScript#Comments">¿Cómo agrega comentarios al código JavaScript?</a></li> +</ul> + +<h3 id="Variables">Variables</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables#Declaring_a_variable">¿Cómo se declara una variable?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables#Initializing_a_variable">¿Cómo se inicializa una variable con un valor?</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Variables#Updating_a_variable">¿Cómo se actualiza el valor de una variable?</a> (ver también <a href="/en-US/docs/Learn/JavaScript/First_steps/Math#Assignment_operators">Operadores de asignación</a>) </li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Variables#Variable_types">¿Qué tipos de datos pueden tener los valores en JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Variables#Loose_typing">¿Qué significa 'tipeado libremente' (loosely typed)?</a></li> +</ul> + +<h3 id="Matemáticas_(MATH)">Matemáticas (MATH)</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math#Types_of_numbers">¿Con qué tipos de números tiene que lidiar en el desarrollo web?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math#Arithmetic_operators">¿Cómo haces matemáticas básicas en JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math#Operator_precedence">¿Qué es la precedencia del operador y cómo se maneja en JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Math#Increment_and_decrement_operators">¿Cómo se incrementan y disminuyen los valores en JavaScript?</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Math#Comparison_operators">¿Cómo se comparan los valores en JavaScript?</a> (por ejemplo, para ver cuál es más grande o para ver si un valor es igual a otro).</li> +</ul> + +<h3 id="Cadenas_de_texto_(Strings)">Cadenas de texto (Strings)</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings#Creating_a_string">¿Cómo se crea una cadena de texto en JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings#Single_quotes_versus_double_quotes">¿Tienes que usar comillas simples o comillas dobles?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings#Escaping_characters_in_a_string">How do you escape characters in strings?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings#Concatenating_strings">¿Cómo se unen las cadenas de texto?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Strings#Numbers_versus_strings">¿Puedes unir cadenas de texto y números juntos?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods#Finding_the_length_of_a_string">¿Cómo encuentras la longitud de una cadena de texto (String)?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods#Retrieving_a_specific_string_character">¿Cómo encuentras qué carácter está en una posición determinada en una cadena de texto?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods#Finding_a_substring_inside_a_string_and_extracting_it">¿Cómo encontrar y extraer una subcadena específica de una cadena de texto?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods#Changing_case">¿Cómo se cambia el caso de una cadena de texto?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Useful_string_methods#Updating_parts_of_a_string">¿Cómo se reemplaza una subcadena específica por otra?</a></li> +</ul> +</div> + +<div class="column-half"> +<h3 id="Matrices_(Arrays)">Matrices (Arrays)</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays#Creating_an_array">¿Cómo se crea una matriz?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays#Accessing_and_modifying_array_items">¿Cómo accede y modifica los elementos en una matriz?</a> (esto incluye matrices multidimensionales)</li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays#Finding_the_length_of_an_array">¿Cómo encuentras la longitud de una matriz?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays#Adding_and_removing_array_items">¿Cómo agrega y elimina elementos de la matriz?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/Arrays#Converting_between_strings_and_arrays">¿Cómo se divide una cadena en elementos de la matriz, o se unen los elementos de la matriz en una cadena?</a></li> +</ul> + +<h3 id="Depuración_de_JavaScript">Depuración de JavaScript</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong#Types_of_error">¿Cuáles son los tipos básicos de error?</a></li> + <li><a href="/en-US/docs/Learn/Common_questions/What_are_browser_developer_tools">¿Qué son las herramientas de desarrollo del navegador y cómo se accede a ellas?</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/JavaScript#The_Console_API">¿Cómo se registra un valor en la consola de JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/JavaScript#Using_the_JavaScript_debugger">¿Cómo se usan los puntos de interrupción y otras funciones de depuración de JavaScript?</a></li> +</ul> + + + +<p>Para obtener más información sobre la depuración de JavaScript, consulte <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/JavaScript">Manejo de problemas comunes de JavaScript </a>; Consulte también <a href="/en-US/docs/Learn/JavaScript/First_steps/What_went_wrong#Other_common_errors">Otros errores comunes</a> para obtener una descripción de los errores comunes.</p> + +<h3 id="Tomar_decisiones_en_el_código">Tomar decisiones en el código</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals">¿Cómo ejecuta diferentes bloques de código, dependiendo del valor de una variable u otra condición?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals#if_..._else_statements">¿Cómo se usan las declaraciones if ... else?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals#Nesting_if_..._else">¿Cómo anidan un bloque de decisión dentro de otro?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals#Logical_operators_AND_OR_and_NOT">¿Cómo se usan los operadores AND, OR y NOT en JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/conditionals#switch_statements">¿Cómo maneja convenientemente una gran cantidad de opciones para una condición?</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/conditionals#Ternary_operator">¿Cómo utiliza un operador ternario para hacer una elección rápida entre dos opciones basadas en una prueba verdadera o falsa?</a></li> +</ul> + +<h3 id="Bucle_Iteración">Bucle / Iteración</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code">¿Cómo ejecutas el mismo código una y otra vez?</a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code#Exiting_loops_with_break">¿Cómo sale de un bucle antes del final si se cumple una determinada condición?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code#Skipping_iterations_with_continue">¿Cómo saltas a la siguiente iteración de un ciclo si se cumple una determinada condición?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code#while_and_do_..._while">¿Cómo usas while y do ... while loops?</a></li> + <li>Cómo iterar sobre los elementos en una matriz</li> + <li>Cómo iterar sobre los elementos en una matriz multidimensional</li> + <li>Cómo iterar sobre los miembros en un objeto</li> + <li>Cómo iterar sobre los miembros de un objeto anidado dentro de una matriz</li> +</ul> +</div> +</div> + +<h2 id="Casos_de_uso_intermedio">Casos de uso intermedio</h2> + +<div class="column-container"> +<div class="column-half"> +<h3 id="Funciones_2">Funciones</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions#Built-in_browser_functions">¿Cómo encuentras funciones en el navegador?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions#Functions_versus_methods">¿Cuál es la diferencia entre una función y un método?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Build_your_own_function">¿Cómo creas tus propias funciones?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions#Invoking_functions">¿Cómo ejecuta (llama o invoca) una función?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions#Anonymous_functions">¿Qué es una función anónima?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions#Function_parameters">¿Cómo se especifican los parámetros (o argumentos) al invocar una función?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Functions#Function_scope_and_conflicts">¿Qué es el alcance de la función?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Return_values">¿Qué son los valores de retorno y cómo los usa?</a></li> +</ul> + +<h3 id="Objetos">Objetos</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics#Object_basics">¿Cómo se crea un objeto?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics#Dot_notation">¿Qué es la notación de puntos?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics#Bracket_notation">¿Qué es la notación de corchetes?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics#Setting_object_members">¿Cómo se obtienen y establecen los métodos y propiedades de un objeto?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics#What_is_this">¿Qué es <code>this</code>, en el contexto de un objeto?</a></li> + <li><a href="/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters">¿Qué es la programación orientada a objetos?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS#Constructors_and_object_instances">¿Qué son los constructores y las instancias y cómo se crean?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS#Other_ways_to_create_object_instances">¿Qué formas diferentes hay para crear objetos en JavaScript?</a></li> +</ul> + +<h3 id="JSON">JSON</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON#JSON_structure">¿Cómo estructuran los datos JSON y los leen desde JavaScript?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON#Loading_our_JSON">¿Cómo se puede cargar un archivo JSON en una página?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON#Converting_between_objects_and_text">¿Cómo convierte un objeto JSON en una cadena de texto y viceversa?</a></li> +</ul> +</div> + +<div class="column-half"> +<h3 id="Eventos">Eventos</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_handler_properties">¿Qué son los controladores de eventos y cómo los usa?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events#Inline_event_handlers_%E2%80%94_don%27t_use_these">¿Qué son los controladores de eventos en línea?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events#addEventListener()_and_removeEventListener()">¿Qué hace la función <code>addEventListener() </code>y cómo la usa?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events#What_mechanism_should_I_use">¿Qué mecanismo debo usar para agregar código de evento a mis páginas web?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_objects">¿Qué son los objetos de evento y cómo los usa?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events#Preventing_default_behaviour">¿Cómo se previene el comportamiento de evento predeterminado?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture">¿Cómo se disparan los eventos en elementos anidados? (propagación de eventos, también relacionada - burbujeo y captura de eventos)</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_delegation">¿Qué es la delegación de eventos y cómo funciona?</a></li> +</ul> + +<h3 id="JavaScript_Orientado_a_Objetos">JavaScript Orientado a Objetos</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">¿Qué son los prototipos de objetos?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes#The_constructor_property">¿Cuál es la propiedad del constructor y cómo puede usarla?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes#Modifying_prototypes">¿Cómo se agregan métodos al constructor?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">¿Cómo se crea un nuevo constructor que herede sus miembros de un constructor principal?</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance#Object_member_summary">¿Cuándo deberías usar la herencia en JavaScript?</a></li> +</ul> + +<h3 id="Web_APIs">Web APIs</h3> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Manipulating_documents#Active_learning_Basic_DOM_manipulation">¿Cómo se manipula el DOM (por ejemplo, agregar o eliminar elementos) usando JavaScript?</a></li> +</ul> + + +</div> +</div> diff --git a/files/es/learn/javascript/index.html b/files/es/learn/javascript/index.html new file mode 100644 index 0000000000..4703c68749 --- /dev/null +++ b/files/es/learn/javascript/index.html @@ -0,0 +1,80 @@ +--- +title: JavaScript +slug: Learn/JavaScript +tags: + - JavaScript + - Novato + - Principiante + - Tema + - aterrizando + - 'l10n:priority' + - modulo + - princiante JavaScript +translation_of: Learn/JavaScript +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">{{Glossary("JavaScript")}} es un lenguaje de programación que te permite implementar cosas complejas en páginas web. Cada vez que una página web hace algo más que sentarse ahí y mostrar información estática para que la veas — mostrando actualizaciones de contenido oportunas, mapas interactivos, gráficos animados 2D/3D, desplazando máquinas reproductoras de video, o más, puedes apostar que probablemente JavaScript esté involucrado .</p> + +<div class="in-page-callout webdev"> +<h3 id="¿Quieres_convertirte_en_un_desarrollador_web_front-end">¿Quieres convertirte en un desarrollador web front-end?</h3> + +<p>Hemos elaborado un curso que incluye toda la información esencial que necesitas para trabajar hacia tu objetivo.</p> + +<p><a class="cta primary" href="/docs/Learn/Front-end_web_developer">Empezar</a></p> +</div> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Se puede decir que JavaScript es más difícil de aprender que tecnologías relacionadas como <a href="/es/docs/Learn/HTML">HTML</a> y <a href="/es/docs/Learn/CSS">CSS</a>. Antes de intentar aprender JavaScript, se recomienda encarecidamente que te familiarices con al menos estas dos tecnologías primero, y quizás también con otras. Comienza trabajando con los siguientes módulos:</p> + +<ul> + <li><a href="/es/docs/Learn/Getting_started_with_the_web">Comenzando con la Web</a></li> + <li><a href="/es/docs/Web/Guide/HTML/Introduction">Introducción a <abbr title="Lenguaje de marcado de hipertexto">HTML</abbr></a></li> + <li><a href="/es/docs/Learn/CSS/Introduction_to_CSS">Introducción a <abbr title="Hojas de estilo en cascada">CSS</abbr></a></li> +</ul> + +<p>Tener experiencia previa con otros lenguajes de programación también puede ayudar.</p> + +<p>Después de familiarizarte con los conceptos básicos de JavaScript, deberías estar en condiciones de aprender sobre temas más avanzados, por ejemplo:</p> + +<ul> + <li>JavaScript en profundidad, como se enseña en nuestra <a href="/es/docs/Web/JavaScript/Guide">guía de JavaScript</a></li> + <li><a href="/es/docs/Web/API"><abbr title="Interfaz de programación de aplicaciones">APIs</abbr> web</a></li> +</ul> + +<h2 id="Módulos">Módulos</h2> + +<p>Este tema contiene los siguientes módulos, en un orden sugerido para trabajar con ellos.</p> + +<dl> + <dt><a href="/es/docs/Learn/JavaScript/First_steps">Primeros pasos en JavaScript</a></dt> + <dd>En nuestro primer módulo de JavaScript, primero respondemos algunas preguntas fundamentales como "¿qué es JavaScript?", "¿Cómo se ve?" y "¿qué puede hacer?", antes de pasar a guiarte por tu primera experiencia práctica de escribir JavaScript. Después de eso, discutimos en detalle algunas características clave de JavaScript, tal como variables, cadenas, números y arreglos.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Building_blocks">Bloques de construcción de JavaScript</a></dt> + <dd>En este módulo, continuamos con nuestra cobertura de todas las características fundamentales clave de JavaScript, centrando nuestra atención en los tipos de bloques de código que se encuentran comúnmente, como declaraciones condicionales, bucles, funciones y eventos. Ya has visto estas cosas en el curso, pero solo de pasada; aquí lo discutiremos todas explícitamente.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Objects">Introducción a los objetos JavaScript</a></dt> + <dd>En JavaScript, la mayoría de las cosas son objetos, desde las características principales de JavaScript como cadenas y arreglos hasta las APIs del navegador creadas sobre JavaScript. Incluso puedes crear tus propios objetos para encapsular funciones y variables relacionadas en paquetes eficientes. Es importante comprender la naturaleza orientada a objetos de JavaScript si deseas ir más allá con tu conocimiento del lenguaje y escribir código más eficiente, por lo tanto, te proporcionamos este módulo para ayudarte. Aquí enseñamos la teoría y la sintaxis de objetos en detalle, vemos cómo crear tus propios objetos y explicamos qué son los datos JSON y cómo trabajar con ellos.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Asynchronous">JavaScript asíncrono</a></dt> + <dd> + <p>En este módulo, echamos un vistazo a JavaScript asíncrono, por qué es importante y cómo se puede utilizar para manejar de forma eficaz posibles operaciones de bloqueo, como la obtención de recursos desde un servidor.</p> + </dd> + <dt><a href="/es/docs/Learn/JavaScript/Client-side_web_APIs">APIs web de lado del cliente</a></dt> + <dd>Al escribir JavaScript de lado del cliente para sitios web o aplicaciones, no irás muy lejos antes de comenzar a usar las APIs — interfaces para manipular diferentes aspectos del navegador y el sistema operativo en el que se ejecuta el sitio, o incluso datos de otros sitios web o servicios. En este módulo, exploraremos qué son las APIs y cómo utilizar algunas de las APIs más populares que encontrarás a menudo en tu trabajo de desarrollo. </dd> +</dl> + +<h2 id="Resolver_problemas_comunes_de_JavaScript">Resolver problemas comunes de JavaScript</h2> + +<p><a href="/es/docs/Learn/JavaScript/Howto">Usar JavaScript para resolver problemas comunes</a> proporciona enlaces a secciones de contenido que explican cómo usar JavaScript para resolver problemas muy comunes al crear una página web.</p> + +<h2 id="Ve_también">Ve también</h2> + +<dl> + <dt><a href="/es/docs/Web/JavaScript">JavaScript en MDN</a></dt> + <dd>El principal punto de entrada para la documentación básica de JavaScript en MDN — aquí es donde encontrarás documentos de referencia extensos sobre todos los aspectos del lenguaje JavaScript y algunos tutoriales avanzados dirigidos a JavaScripters experimentados.</dd> + <dt><a href="https://learnjavascript.online/">Aprende JavaScript</a></dt> + <dd>Un excelente recurso para los aspirantes a desarrolladores web — aprende JavaScript en un entorno interactivo, con lecciones breves y pruebas interactivas, guiado por una evaluación automatizada. Las primeras 40 lecciones son gratuitas y el curso completo está disponible por un pequeño pago único.</dd> + <dt><a href="https://exlskills.com/learn-en/courses/javascript-fundamentals-basics_javascript">Fundamentos de JavaScript en EXLskills</a></dt> + <dd>Aprende JavaScript de forma gratuita con el curso de código abierto EXLskills que presenta todo lo que necesitas para comenzar a crear aplicaciones en JavaScript.</dd> + <dt><a href="https://www.youtube.com/user/codingmath">Codificación de Matemáticas</a></dt> + <dd>Una excelente serie de tutoriales en video para enseñar las matemáticas que necesitas comprender para ser un programador eficaz, por <a href="https://twitter.com/bit101">Keith Peters</a>.</dd> +</dl> diff --git a/files/es/learn/javascript/objects/adding_bouncing_balls_features/index.html b/files/es/learn/javascript/objects/adding_bouncing_balls_features/index.html new file mode 100644 index 0000000000..c2aa7a9985 --- /dev/null +++ b/files/es/learn/javascript/objects/adding_bouncing_balls_features/index.html @@ -0,0 +1,205 @@ +--- +title: Añadiendo características a nuestra demo de bouncing balls +slug: Learn/JavaScript/Objects/Adding_bouncing_balls_features +tags: + - Aprender + - Evaluación + - JavaScript + - Objetos + - Orientado a objetos + - Principiante +translation_of: Learn/JavaScript/Objects/Adding_bouncing_balls_features +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">En esta evaluación, se espera que use la demo de bouncing balls del artículo anterior como punto de partida y le agregue algunas características nuevas e interesantes.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Antes de intentar esta evaluación, debería haber revisado todos los artículos de este módulo.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Para probar la comprensión de objetos JavaScript y construcciones orientadas a objetos.</td> + </tr> + </tbody> +</table> + +<h2 id="Punto_de_partida">Punto de partida</h2> + +<p>Para iniciar esta evaluación, haz una copia local de <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index-finished.html">index-finished.html</a>, <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a>, y <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">main-finished.js</a> de nuestro último artículo en un nuevo directorio en tu ordenador.</p> + +<div class="note"> +<p><strong>Nota</strong>: Alternativamente, puede usar un sitio como <a class="external external-icon" href="http://jsbin.com/">JSBin</a> o <a class="external external-icon" href="https://thimble.mozilla.org/">Thimble</a> para hacer su evaluación. Puede pegar el HTML, CSS y JavaScript en uno de estos editores en línea. Si el editor en línea que está utilizando no tiene paneles JavaScript / CSS separados, sientase libre de poner en linea elementos <code><script></code>/<code><style></code> dentro de la página.</p> +</div> + +<h2 id="Resumen_del_proyecto">Resumen del proyecto</h2> + +<p>Nuestra demostración de la pelota hinchable es divertida, pero ahora queremos que sea un poco más interactiva agregando un círculo maligno controlado por el usuario, que se los comería si los atrapa. Tambien queremos testar nuestras destrezas como constructores de objetos creando un objeto <code>Shape()</code> genérico de que puedan heredar nuestra pelota y el círculo maligno. Finalmente, queremos añadir una puntuación para seguir el número de bolas que quedan por capturar.</p> + +<p>La siguiente captura de pantalla te da una idea de cómo debería verse el programa final.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13875/bouncing-evil-circle.png" style="display: block; margin: 0 auto;"></p> + +<ul> +</ul> + +<p>Para darle una idea eche un vistazo al <a href="http://mdn.github.io/learning-area/javascript/oojs/assessment/">ejemplo final</a> (¡no mire el código fuente!)</p> + +<h2 id="Pasos_para_completar">Pasos para completar</h2> + +<p>Las siguientes secciones describen lo que debe hacer.</p> + +<h3 id="Creando_nuestro_nuevos_objetos">Creando nuestro nuevos objetos</h3> + +<p>Primero de todo, cambia la constructora existente de <code>Ball()</code> para que se convierta en un constructor <code>Shape()</code> y añade un nuevo constructor <code>Ball()</code>:</p> + +<ol> + <li>El constructor <code>Shape()</code> debe definir las propiedades <code>x</code>, <code>y</code>, <code>velX</code>, y <code>velY</code> del mismo modo que lo hacía el constructor <code>Ball()</code> constructor original, pero no las propiedades <code>color</code> y <code>size</code>.</li> + <li>También debe definir una nueva propiedad <code>exists</code>, que se utiliza para realizar un seguimiento de si existen las bolas en el programa (no se han comido por el círculo maligno). Debe ser un boolean (<code>true</code>/<code>false</code>).</li> + <li>El constructor <code>Ball()</code> debe heredar las propiedades <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code>, y <code>exists</code> del constructor <code>Shape()</code>.</li> + <li>También debe definir propiedades <code>color</code> y <code>size</code>, como el constructor original <code>Ball()</code> hacía.</li> + <li>Recuerda configurar el <code>prototype </code>del constructor <code>Ball()</code> correctamente.</li> +</ol> + +<p>Los métodos de la pelota <code>draw()</code>, <code>update()</code>, y <code>collisionDetect()</code> deben ser capaces de permanecer exactamente igual que antes.</p> + +<p>También necesitas añadir un parámetro nuevo a la llamada del constructor <code>new Ball() ( ... )</code> — El parámetro <code>exists</code> debe ser el quinto parámetro y debe tener un valor <code>true</code>.</p> + +<p>En este punto, intente volver a cargar el código; debería funcionar igual que antes, con nuestros objetos rediseñados.</p> + +<h3 id="Definiendo_EvilCircle">Definiendo EvilCircle()</h3> + +<p>Ahora es el momento de conocer al chico malo: ¡el <code>EvilCircle()</code>! Nuestro juego solo involucrará un círculo malvado, pero lo vamos a seguir definiendo usando un constructor que hereda de <code>Shape()</code> para que tengas algo de práctica. Es posible que desee agregar otro círculo a la aplicación más adelante que pueda ser controlado por otro jugador o tener varios círculos malvados controlados por computadora. Probablemente no vas a dominar el mundo con un solo círculo maligno, pero servirá para esta evaluación.</p> + +<p>El constructor <code>EvilCircle()</code> debe heredar <code>x</code>, <code>y</code>, <code>velX</code>, <code>velY</code>, y <code>exists</code> from <code>Shape()</code>, pero <code>velX</code> y <code>velY</code> debe ser igual a 20.</p> + +<p>Debería hacer algo como <code>Shape.call(this, x, y, 20, 20, exists);</code></p> + +<p>Debe definir también sus propias propiedades, como las siguientes:</p> + +<ul> + <li><code>color</code> — <code>'white'</code></li> + <li><code>size</code> — <code>10</code></li> +</ul> + +<p>Otra vez, recuerda definir tus propiedades heredadas como parámetros en el constructor, y configura las propiedades <code>prototype</code> y <code>constructor</code> properties correc.tamente</p> + +<h3 id="Definiendo_los_métodos_de_EvilCircle">Definiendo los métodos de EvilCircle()</h3> + +<p><code>EvilCircle()</code> debe tener cuatro métodos como se desciben a continuación.</p> + +<h4 id="draw"><code>draw()</code></h4> + +<p>Este método tiene el mismo propósito que el método <code>draw()</code>de <code>Ball()</code>: Se encarga de dibujar la instancia del objeto en el lienzo. Funcionarán de una forma muy similar, así que puedes empezar copiando la definición de <code>Ball.prototype.draw</code>. Luego deberías hacer los siguientes cambios.:</p> + +<ul> + <li>Queremos que el círculo del mal no se complete, sino que simplemente tenga una línea exterior (trazo). Puedes lograr esto actualizando <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> y <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> a <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/strokeStyle">strokeStyle</a></code> y <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/stroke">stroke()</a></code>.</li> + <li>También queremos que el trazo sea un poco más grueso, para que puedas ver el círculo malvado con mayor facilidad. Podemos lograr esto configurando un valor para <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/lineWidth">lineWidth</a></code> en algún lugar después de la llamada <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> (3 hará).</li> +</ul> + +<h4 id="checkBounds"><code>checkBounds()</code></h4> + +<p>Este método hara lo mismo que la primera parte de la función <code>update()</code> de <code>Ball()</code> — mire para ver si el círculo maligno va a salir del borde de la pantalla y evite que lo haga. De nuevo, puede copiar la mayoría de la definición de <code>Ball.prototype.update</code>, hay algunos cambios que debe hacer:</p> + +<ul> + <li>Deshazte de las dos últimas líneas: no queremos actualizar automáticamente la posición del círculo maligno en cada cuadro, porque lo moveremos de alguna otra manera, como verás a continuación.</li> + <li>Dentro de las declaraciones <code>if()</code>, si el test devuelve true no queremos actualizar <code>velX</code>/<code>velY</code>; queremos cambiar el valor de <code>x</code>/<code>y</code> por lo que el círculo del mal se rebota en la pantalla ligeramente. Agregar o restar (según corresponda) la propiedad de tamaño del círculo maligno (<code>size</code>) tendría sentido.</li> +</ul> + +<h4 id="setControls"><code>setControls()</code></h4> + +<p>Este método agregará un detector de eventos <code>onkeydown</code> al objeto <code>window</code> para que cuando se presionen ciertas teclas del teclado, podamos mover el círculo maligno. El siguiente bloque de código debe colocarse dentro de la definición del método:</p> + +<pre class="brush: js notranslate">var _this = this; +window.onkeydown = function(e) { + if (e.keyCode === 65) { + _this.x -= _this.velX; + } else if (e.keyCode === 68) { + _this.x += _this.velX; + } else if (e.keyCode === 87) { + _this.y -= _this.velY; + } else if (e.keyCode === 83) { + _this.y += _this.velY; + } + }</pre> + +<p>Por tanto cuando se presiona una tecla, el evento del objeto <a href="/en-US/docs/Web/API/KeyboardEvent/keyCode">keyCode</a> se consulta para averiguar que tecla se ha presionado. Si es uno de los cuatro representados por los códigos clave especificados, entonces el círculo maligno se moverá a la izquierda / derecha / arriba / abajo.</p> + +<ul> + <li>Para obtener un punto de bonificación, avísenos a qué teclas se asignan los códigos de clave especificados.</li> + <li>Para otro punto de bonificación, ¿nos podrías decir por qué tenemos que configurar <code>var _this = this;</code> en la posición en la que está? Es algo que se hace en la función scope.</li> +</ul> + +<h4 id="collisionDetect"><code>collisionDetect()</code></h4> + +<p>Este método actuará de una forma muy similar al método <code>collisionDetect() </code>de <code>Ball()</code>, así que puede usar una copia de eso como una base para el nuevo método. Pero hay algunas diferencias:</p> + +<ul> + <li>En el exterior de la declaración <code>if</code>, ya no es necesario comprobar si la bola actual en la iteración es la misma que la bola que está haciendo la comprobación, porque ya no es una bola, ¡es el círculo del mal! En su lugar, debe hacer una prueba para ver si existe la bola que se está verificando (¿con qué propiedad podría hacerlo?). Si no existe, ya ha sido devorado por el círculo maligno, por lo que no es necesario volver a comprobarlo.</li> + <li>En el interior de la declaración <code>if</code>, ya no desea que los objetos cambien de color cuando se detecta una colisión; en cambio, desea que no existan más bolas que colisionen con el círculo maligno (una vez más, ¿cómo cree que haría eso?).</li> +</ul> + +<h3 id="Trayendo_el_círculo_del_mal_al_programa.">Trayendo el círculo del mal al programa.</h3> + +<p>Ahora que hemos definido el círculo maligno, debemos hacerlo aparecer en nuestra escena. Para hacerlo, necesitas hacer alguno cambios a la función <code>loop()</code>.</p> + +<ul> + <li>Primero de todo, crea una nueva instancia del círculo maligno (especifica los parámetros necesarios ), entonces llama al método <code>setControls()</code> . Solo necesita hacer estas dos cosas una vez, no en cada iteración del bucle.</li> + <li>En el punto en el que intera por todas las pelotas y llama a las funciones <code>draw()</code>, <code>update()</code>, y<code>collisionDetect()</code> para cada una, hazlo para que estas funciones solo sean llamadas si la bola actual existe.</li> + <li>Llama a los métodos de la instancia de la pelota maligna <code>draw()</code>, <code>checkBounds()</code>, y<code>collisionDetect()</code> en cada iteración del bucle.</li> +</ul> + +<h3 id="Implementando_el_contador_de_puntuación.">Implementando el contador de puntuación.</h3> + +<p>Para implementar el contador de puntuación sigue estos pasos:</p> + +<ol> + <li>En tu archivo HTML añade un elemento {{HTMLElement("p")}} justo debajo del elemento {{HTMLElement("h1")}} que contiene el texto "Ball count: ".</li> + <li>En tu archivo CSS, agregue la siguiente regla en la parte inferior: + <pre class="brush: css notranslate">p { + position: absolute; + margin: 0; + top: 35px; + right: 5px; + color: #aaa; +}</pre> + </li> + <li>En su JavaScript, realice las siguientes actualizaciones: + <ul> + <li>Cree una variable que almacene una referencia al párrafo.</li> + <li>Mantenga un recuento de la cantidad de bolas en la pantalla de alguna manera.</li> + <li>Incrementa el conteo y muestra el número actualizado de bolas cada vez que se agrega una bola a la escena.</li> + <li>Disminuye el conteo y muestra el número actualizado de bolas cada vez que el círculo maligno se come una bola (hace que no exista).</li> + </ul> + </li> +</ol> + +<h2 id="Consejos">Consejos</h2> + +<ul> + <li>Esta evaluación es bastante desafiante. Da cada paso despacio y con cuidado.</li> + <li>Puede ser una idea mantener una copia separada de la demostración después de que cada etapa esté funcionando, para que pueda consultarla si se encuentra en problemas más adelante.</li> +</ul> + +<h2 id="Evaluación">Evaluación</h2> + +<p>Si está siguiendo esta evaluación como parte de un curso organizado, debe poder entregar su trabajo a su maestro / mentor para que lo marque. Si está aprendiendo solo, puede obtener la guía de calificación con bastante facilidad preguntando en el <a href="https://discourse.mozilla.org/t/adding-features-to-our-bouncing-balls-demo-assessment/24689">discussion thread for this exercise</a>, o en el <a href="irc://irc.mozilla.org/mdn">#mdn</a> IRC channel en <a href="https://wiki.mozilla.org/IRC">Mozilla IRC</a>. Prueba a hacer el ejercicio primero — no hay nada que ganar con trampa!</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_building_practice", "", "Learn/JavaScript/Objects")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> diff --git a/files/es/learn/javascript/objects/basics/index.html b/files/es/learn/javascript/objects/basics/index.html new file mode 100644 index 0000000000..a04cdb6a81 --- /dev/null +++ b/files/es/learn/javascript/objects/basics/index.html @@ -0,0 +1,259 @@ +--- +title: Conceptos básicos de los objetos JavaScript +slug: Learn/JavaScript/Objects/Basics +tags: + - API + - Aprender + - Artículo + - JavaScript + - Novato + - Object + - Objeto + - Principiante + - Sintaxis + - instancia + - 'l10n:priority' + - notación de corchetes + - notación de punto + - objeto literal + - tehoría + - this +translation_of: Learn/JavaScript/Objects/Basics +--- +<div><font><font>{{LearnSidebar}}</font></font></div> + +<div>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</div> + +<p class="summary"><font><font>En éste artículo, veremos fundamentos de sintaxis de los objetos de JavaScript y revisaremos algunas características de JavaScript que ya hemos analizado anteriormente en el curso, reiterando el hecho de que muchas de las funciones con las que ya has tratado de hecho son objetos.</font></font></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row"><font><font>Prerrequisitos:</font></font></th> + <td><font><font>Conocimientos básicos de informática, conocimientos básicos de HTML y CSS, familiaridad con los principios básicos de JavaScript (consulta </font></font><a href="/es/docs/Learn/JavaScript/First_steps"><font><font>Primeros pasos</font></font></a><font><font> y </font></font><a href="/es/docs/Learn/JavaScript/Building_blocks"><font><font>Bloques de construcción</font></font></a><font><font>).</font></font></td> + </tr> + <tr> + <th scope="row"><font><font>Objetivo:</font></font></th> + <td><font><font>Para comprender la teoría básica detrás de la programación orientada a objetos, cómo esto se relaciona con JavaScript ("la mayoría de las cosas son objetos") y cómo empezar a trabajar con objetos de JavaScript.</font></font></td> + </tr> + </tbody> +</table> + +<h2 id="Conceptos_básicos_de_objeto"><font><font>Conceptos básicos de objeto</font></font></h2> + +<p><font><font>Un objeto es una colección de datos relacionados y/o funcionalidad (que generalmente consta de algunas variables y funciones, que se denominan propiedades y métodos cuando están dentro de objetos). Vamos a trabajar a través de un ejemplo para mostrate cómo son.</font></font></p> + +<p><font><font>Para empezar, haz una copia local de nuestro </font><font>archivo </font></font><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs.html"><font><font>oojs.html</font></font></a><font><font> . </font><font>Esto contiene muy poco: un elemento {{HTMLElement ("script")}} para que escribas tu código fuente en él. Lo </font><font>usaremos como base para explorar la sintaxis básica de los objetos.</font></font></p> + +<p><font><font>Al igual que con muchas cosas en JavaScript, la creación de un objeto a menudo comienza con la definición e iniciación de una variable. </font><font>Intenta ingresar lo siguiente debajo del código JavaScript que ya está en tu archivo, luego guarda y actualiza:</font></font></p> + +<pre class="brush: js notranslate"><font><font>var persona = {};</font></font></pre> + +<p><font><font>Si ingresas </font></font><code>persona</code><font><font> en tu entrada de texto y presionas el botón, debes obtener el siguiente resultado:</font></font></p> + +<pre class="brush: js notranslate"><font><font>[objeto Objeto]</font></font></pre> + +<p><font><font>¡Felicidades!, acabas de crear tu primer objeto. </font><font>¡Trabajo realizado! </font><font>Pero este es un objeto vacío, por lo que realmente no podemos hacer mucho con él. </font><font>Actualicemos nuestro objeto para que se vea así:</font></font></p> + +<pre class="brush: js notranslate"><font><font>var persona = { + nombre: ['Bob', 'Smith'], + edad: 32, + genero: 'masculino', + intereses: ['música', 'esquí'], + bio: function () { + alert(this.nombre[0] + '' + this.nombre[1] + ' tiene ' + this.edad + ' años. Le gusta ' + this.intereses[0] + ' y ' + this.intereses[1] + '.'); + }, + saludo: function() { + alert('Hola, Soy '+ this.nombre[0] + '. '); + } +};</font></font> +</pre> + +<p><font><font>Después de guardar y actualizar, intenta ingresar algunos de los siguientes en tu entrada de texto:</font></font></p> + +<pre class="brush: js notranslate"><font><font>persona.nombre +persona.nombre[0] +persona.edad +persona.intereses[1]</font></font><font><font> +persona.bio() +persona.saludo()</font></font></pre> + +<p><font><font>¡Ahora tienes algunos datos y funcionalidades dentro de tu objeto, y ahora puedes acceder a ellos con una sintaxis simple y agradable!</font></font></p> + +<div class="note"> +<p><strong>Nota</strong>: Si tienes problemas para hacer que esto funcione, intenta comparar tu código con nuestra versión - ve <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-finished.html">oojs-finished.html</a> (también <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-finished.html">ve que se ejecuta en vivo</a>). La versión en vivo te dará una pantalla en blanco, pero eso está bien. De nuevo, abre tu devtools e intenta escribir los comandos anteriores para ver la estructura del objeto.</p> +</div> + +<p>Entonces, ¿qué está pasando aquí? Bien, un objeto se compone de varios miembros, cada uno de los cuales tiene un nombre (por ejemplo, <code>nombre</code> y <code>edad</code>) y un valor (por ejemplo, <code>['Bob', 'Smith']</code> y <code>32</code>). Cada par nombre/valor debe estar separado por una coma, y el nombre y el valor en cada caso están separados por dos puntos. La sintaxis siempre sigue este patrón:</p> + +<pre class="brush: js notranslate">var nombreObjeto = { + miembro1Nombre: miembro1Valor, + miembro2Nombre: miembro2Valor, + miembro3Nombre: miembro3Valor +}</pre> + +<p>El valor de un miembro de un objeto puede ser prácticamente cualquier cosa: en nuestro objeto <code>persona </code>tenemos una cadena de texto, un número, dos arreglos y dos funciones. Los primeros cuatro elementos son elementos de datos y se denominan <strong>propiedades</strong> del objeto. Los dos últimos elementos son funciones que le permiten al objeto hacer algo con esos datos, y se les denomina <strong>métodos</strong> del objeto.</p> + +<p>Un objeto como este se conoce como un <strong>objeto literal </strong>— literalmente hemos escrito el contenido del objeto tal como lo fuimos creando. Esto está en contraste con los objetos instanciados de las clases, que veremos más adelante.</p> + +<p>Es muy común crear un objeto utilizando un objeto literal cuando deseas transferir una serie de elementos de datos relacionados y estructurados de alguna manera, por ejemplo, enviando una solicitud al servidor para ponerla en una base de datos. Enviar un solo objeto es mucho más eficiente que enviar varios elementos individualmente, y es más fácil de procesar que con un arreglo, cuando deseas identificar elementos individuales por nombre.</p> + +<h2 id="Notación_de_punto">Notación de punto</h2> + +<p>Arriba, accediste a las propiedades y métodos del objeto usando <strong>notación de punto (dot notation)</strong>. El nombre del objeto (<code>persona</code>) actúa como el <strong>espacio de nombre (namespace)</strong>; al cual se debe ingresar primero para acceder a cualquier elemento <strong>encapsulado</strong> dentro del objeto. A continuación, escribe un punto y luego el elemento al que deseas acceder: puede ser el nombre de una simple propiedad, un elemento de una propiedad de arreglo o una llamada a uno de los métodos del objeto, por ejemplo:</p> + +<pre class="brush: js notranslate">persona.edad +persona.<font><font>intereses</font></font>[1] +persona.bio()</pre> + +<h3 id="Espacios_de_nombres_secundarios">Espacios de nombres secundarios</h3> + +<p>Incluso es posible hacer que el valor de un miembro del objeto sea otro objeto. Por ejemplo, intenta cambiar el miembro nombre de</p> + +<pre class="brush: js notranslate">nombre: ['Bob', 'Smith'],</pre> + +<p>a</p> + +<pre class="brush: js notranslate">nombre : { + pila: 'Bob', + apellido: 'Smith' +},</pre> + +<p>Aquí estamos creando efectivamente un <strong>espacio de nombre secundario (sub-namespace)</strong>. Esto suena complejo, pero en realidad no es así: para acceder a estos elementos solo necesitas un paso adicional que es encadenar con otro punto al final. Prueba estos:</p> + +<pre class="brush: js notranslate">persona.nombre.pila +persona.nombre.apellido</pre> + +<p><strong>Importante</strong>: en este punto, también deberás revisar tu código y cambiar cualquier instancia de</p> + +<pre class="brush: js notranslate">nombre[0] +nombre[1]</pre> + +<p>a</p> + +<pre class="brush: js notranslate">nombre.pila +nombre.apellido</pre> + +<p>De lo contrario, sus métodos ya no funcionarán.</p> + +<h2 id="Notación_de_corchetes">Notación de corchetes</h2> + +<p>Hay otra manera de acceder a las propiedades del objeto, usando la notación de corchetes. En lugar de usar estos:</p> + +<pre class="brush: js notranslate">persona.edad +persona.nombre.pila</pre> + +<p>Puedes usar</p> + +<pre class="brush: js notranslate">persona['edad'] +persona['nombre']['pila']</pre> + +<p>Esto se ve muy similar a cómo se accede a los elementos en un arreglo, y básicamente es lo mismo: en lugar de usar un número de índice para seleccionar un elemento, se esta utilizando el nombre asociado con el valor de cada miembro. No es de extrañar que los objetos a veces se denominen <strong>arreglos asociativos</strong>: asocian cadenas de texto a valores de la misma manera que las arreglos asocian números a valores.</p> + +<h2 id="Establecer_miembros_de_objetos">Establecer miembros de objetos</h2> + +<p>Hasta ahora solo hemos buscado recuperar (u <strong>obtener</strong>) miembros del objeto: también puede <strong>establecer</strong> (actualizar) el valor de los miembros del objeto simplemente declarando el miembro que deseas establecer (usando la notación de puntos o corchetes), de esta manera:</p> + +<pre class="brush: js notranslate">persona.edad = 45; +persona['nombre']['apellido'] = 'Cratchit';</pre> + +<p>Intenta ingresar estas líneas y luego vuelve a ver a los miembros para ver cómo han cambiado:</p> + +<pre class="brush: js notranslate">persona.edad +persona['nombre']['apellido']</pre> + +<p>Establecer miembros no solo es actualizar los valores de las propiedades y métodos existentes; también puedes crear miembros completamente nuevos. Prueba estos:</p> + +<pre class="brush: js notranslate">persona['ojos'] = 'avellana'; +persona.despedida = function() { alert("¡Adiós a todos!"); }</pre> + +<p>Ahora puedes probar a los nuevos miembros:</p> + +<pre class="brush: js notranslate">persona['ojos'] +person.despedida()</pre> + +<p>Un aspecto útil de la notación de corchetes es que se puede usar para establecer dinámicamente no solo los valores de los miembros, sino también los nombres de los miembros. Digamos que queremos que los usuarios puedan almacenar tipos de valores personalizados en sus datos personales, escribiendo el nombre y el valor del miembro en dos entradas de texto. Podríamos obtener esos valores de esta manera:</p> + +<pre class="brush: js notranslate">var nombrePerzonalizado = entradaNombre.value; +var valorPerzonalizado = entradaValor.value;</pre> + +<p>entonces podríamos agregar este nuevo miembro nombre y valor al objeto <code>persona</code> de esta manera:</p> + +<pre class="brush: js notranslate">persona[nombrePerzonalizado] = valorPerzonalizado;</pre> + +<p>Para probar esto, intenta agregar las siguientes líneas en tu código, justo debajo de la llave de cierre del objeto <code>persona</code>:</p> + +<pre class="brush: js notranslate">var nombrePerzonalizado = 'altura'; +var valorPerzonalizado = '1.75m'; +persona[nombrePerzonalizado] = valorPerzonalizado;</pre> + +<p>Ahora intenta guardar y actualizar, e ingresa lo siguiente en tu entrada de texto:</p> + +<pre class="brush: js notranslate">persona.altura</pre> + +<p>Agregar una propiedad a un objeto no es posible con la notación de puntos, que solo puede aceptar un nombre de miembro literal, no un valor variable que apunte a un nombre.</p> + +<h2 id="¿Qué_es_this_este">¿Qué es "this" (este)?</h2> + +<p>Es posible que hayas notado algo un poco extraño en nuestros métodos. Mira esto, por ejemplo:</p> + +<pre class="brush: js notranslate"><font><font>saludo</font></font>: function() { + alert(<font><font>'¡Hola!, Soy '+ </font></font>this.nombre.pila + '.'); +}</pre> + +<p>Probablemente te estés preguntando qué es <code>"this"</code>. La palabra clave <code>this</code> se refiere al objeto actual en el que se está escribiendo el código, por lo que en este caso <code>this</code> es equivalente a la <code>persona</code>. Entonces, ¿por qué no escribir <code>persona</code> en su lugar? Como verás en el artículo <a href="/es/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript orientado a objetos para principiantes</a> cuando comenzaremos a crear constructores, etc., <code>this</code> es muy útil: siempre asegurará que se usen los valores correctos cuando cambie el contexto de un miembro (por ejemplo, dos diferentes instancias de objetos <code>persona</code>) pueden tener diferentes nombres, pero querráx usar su propio nombre al decir su saludo).</p> + +<p>Vamos a ilustrar lo que queremos decir con un par de objetos persona simplificados:</p> + +<pre class="brush: js notranslate">var persona1 = { + nombre: 'Chris', + saludo: function() { + alert(<font><font>'¡Hola!, Soy '+ </font></font>this.nombre + '.'); + } +} + +var persona2 = { + nombre: 'Brian', + saludo: function() { + alert(<font><font>'¡Hola!, Soy '+ </font></font>this.nombre + '.'); + } +}</pre> + +<p>En este caso, <code>persona1.saludo()</code> mostrará "<font><font>¡Hola!</font></font>, Soy Chris"; <code>persona2.saludo()</code> por otro lado mostrará "<font><font>¡Hola!</font></font>, Soy Brian", aunque el código del método es exactamente el mismo en cada caso. Como dijimos antes, <code>this</code> es igual al objeto en el que está el código; esto no es muy útil cuando se escriben objetos literales a mano, pero realmente se vuelve útil cuando se generan objetos dinámicamente (por ejemplo, usando constructores) Todo se aclarará más adelante.</p> + +<h2 id="Has_estado_usando_objetos_todo_el_tiempo">Has estado usando objetos todo el tiempo</h2> + +<p>A medida que has estado repasando estos ejemplos, probablemente hayas pensando que la notación de puntos que has usando es muy familiar. ¡Eso es porque la has estado usando a lo largo del curso! Cada vez que hemos estado trabajando en un ejemplo que utiliza una API de navegador incorporada o un objeto JavaScript, hemos estado usando objetos, porque tales características se crean usando exactamente el mismo tipo de estructuras de objetos que hemos estado viendo aquí, aunque más complejos que nuestros propios ejemplos personalizados.</p> + +<p>Entonces cuando usaste métodos de cadenas de texto como:</p> + +<pre class="brush: js notranslate">myCadena.split(',');</pre> + +<p>Estabas usando un método disponible en una instancia de la clase <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String">String</a></code>. Cada vez que creas una cadena en tu código, esa cadena se crea automáticamente como una instancia de String, y por lo tanto tiene varios métodos/propiedades comunes disponibles en ella.</p> + +<p>Cuando accediste al modelo de objetos del documento (document object model) usando líneas como esta:</p> + +<pre class="brush: js notranslate">var miDiv = document.createElement('div'); +var miVideo = document.querySelector('video');</pre> + +<p>Estaba usando métodos disponibles en una instancia de la clase <code><a href="/es/docs/Web/API/Document">Document</a></code>. Para cada página web cargada, se crea una instancia de <code>Document</code>, llamada <code>document</code>, que representa la estructura, el contenido y otras características de la página entera, como su URL. De nuevo, esto significa que tiene varios métodos/propiedades comunes disponibles en él.</p> + +<p>Lo mismo puede decirse de prácticamente cualquier otro Objeto/API incorporado que hayad estado utilizando: <code><a href="/es/docs/Web/JavaScript/Reference/Global_Objects/Array">Array</a></code>, <code><a href="/es/docs/Web/JavaScript/Reference/Global_Objects/Math">Math</a></code>, etc.</p> + +<p>Ten en cuenta que los Objetos/API incorporados no siempre crean instancias de objetos automáticamente. Como ejemplo, la <a href="/es/docs/Web/API/Notifications_API">API de Notificaciones</a>, que permite que los navegadores modernos activen las notificaciones del sistema, requiere que crees una instancia de un nuevo objeto para cada notificación que desees disparar. Intenta ingresar lo siguiente en tu consola de JavaScript:</p> + +<pre class="brush: js notranslate">var miNotificacion = new Notification('¡Hola!');</pre> + +<p>De nuevo, veremos qué son los constructores en un artículo posterior.</p> + +<div class="note"> +<p><strong>Nota</strong>: Es útil pensar en la forma en que los objetos se comunican como <strong>paso de mensajes</strong> — cuando un objeto necesita otro objeto para realizar algún tipo de acción a menudo enviará un mensaje a otro objeto a través de uno de sus métodos, y esperará una respuesta, que conocemos como un valor de retorno.</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p><font><font>Enhorabuena, has llegado al final de nuestro primer artículo sobre objetos JS: ahora debes tener una buena idea de cómo trabajar con objetos en JavaScript, incluida la creación de tus propios objetos simples. </font><font>También debes apreciar que los objetos son muy útiles como estructuras para almacenar datos y funcionalidades relacionadas; si trataras de hacer un seguimiento de todas las propiedades y métodos en nuestro </font></font><font><font>objeto </font></font><code>persona</code><font><font> como variables y funciones separadas, sería ineficiente y frustrante, y tendríamos el riesgo de chocar con otras variables y funciones que tienen los mismos nombres. </font><font>Los objetos nos permiten mantener la información segura y protegida en su propio paquete, fuera del peligro.</font></font></p> + +<p><font><font>En el próximo artículo comenzaremos a ver la teoría de programación orientada a objetos (OOP) y cómo se pueden usar dichas técnicas en JavaScript.</font></font></p> + +<p>{{NextMenu("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects")}}</p> diff --git a/files/es/learn/javascript/objects/ejercicio_práctico_de_construcción_de_objetos/index.html b/files/es/learn/javascript/objects/ejercicio_práctico_de_construcción_de_objetos/index.html new file mode 100644 index 0000000000..6dfaaf0d08 --- /dev/null +++ b/files/es/learn/javascript/objects/ejercicio_práctico_de_construcción_de_objetos/index.html @@ -0,0 +1,301 @@ +--- +title: Ejercicio práctico de construcción de objetos +slug: Learn/JavaScript/Objects/Ejercicio_práctico_de_construcción_de_objetos +translation_of: Learn/JavaScript/Objects/Object_building_practice +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">En los artículos anteriores se explicó lo fundamental de la teoría de los objetos en JavaScript asi como su sintaxis, para que Usted tenga un punto de partida sólido. En éste artículo, desarrollaremos un ejercicio práctico para ganar experiencia en la programación de objetos en JavaScript, con un resultado divertido y colorido.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td>Conocimientos básicos de computadores. Entendimiento básico de HTML y CSS. Familiaridad con los conceptos básicos de JavaScript (vea <a href="/es/docs/Learn/JavaScript/First_steps">Primeros Pasos con JavaScript</a> y <a href="/es/docs/Learn/JavaScript/Building_blocks">Elementos básicos de JavaScript</a>) y OOJS (vea <a href="/es/docs/Learn/JavaScript/Objects/Basics">Conceptos básicos de los objetos JavaScript</a>).</td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Ganar experiencia en el uso de objetos y el uso de programación orientada a objetos en un contexto realista.</td> + </tr> + </tbody> +</table> + +<h2 id="Lanzemos_algunas_pelotas">Lanzemos algunas pelotas</h2> + +<p>Es éste artículo escribiremos un programa demo del juego clásico de pelotas que rebotan para mostrar la gran útilidad de los objetos en JavaScript. En éste demo las pelotas rebotaran en la pantalla y cambiaran de color cuando choquen unas con otras. Así, al final del ejemplo tendremos algo como esto:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13865/bouncing-balls.png" style="display: block; height: 614px; margin: 0px auto; width: 800px;"></p> + +<ol> +</ol> + +<p>En este ejemplo se utilizará <a href="/en-US/docs/Learn/JavaScript/Client-side_web_APIs/Drawing_graphics">Canvas API</a> para dibujar las pelotas en la pantalla y la API <a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame</a> para animar todo el contenido de la pantalla. No es necesario que conozca estas funciones previamente. Esperamos que al final de este artículo, quizás pueda estar interesado en explorar su uso y capacidades más en detalle. Durante este desarrollo usaremos objetos y algunas técnicas para hacer que las pelotas puedan rebotar en los bordes y comprobar cuando choquen entre ellas (ésto se conoce como <strong>detección de colisiones</strong>). </p> + +<h2 id="Primeros_pasos">Primeros pasos</h2> + +<p>Para comenzar haga una copia en su computador de los archivos: <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/index.html">index.html</a></code>, <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/style.css">style.css</a></code>, y <code><a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main.js">main.js</a></code>. Estos contienen:</p> + +<ol> + <li>Un documento HTML sencillo con un elemento <h1>, un elemento <canvas> en el que podamos dibujar los gráficos y otros elementos para aplicar los estilos CSS y el código JavaScript. </li> + <li>Algunos estilos sencillos que servirán para ubicar el elemento <code><h1></code>, ocultar la barra de desplazamiento y los margenes del borde de la página (para que luzca mejor).</li> + <li>Un archivo JavaScript que sirve para definir el elemento <code><canvas></code> y las funciones que vamos a usar.</li> +</ol> + +<p>La primera parte del script es:</p> + +<pre class="brush: js">var canvas = document.querySelector('canvas'); + +var ctx = canvas.getContext('2d'); + +var width = canvas.width = window.innerWidth; +var height = canvas.height = window.innerHeight;</pre> + +<p>Este script obtiene una referencia del elemento <code><canvas></code>, luego llama al método <code><a href="/en-US/docs/Web/API/HTMLCanvasElement/getContext">getContext()</a></code> para definir un contexto en el cual se pueda comenzar a dibujar. La resultado de la variable (<code>ctx</code>) es el objeto que representa directamente el área de dibujo del <code><canvas></code> y permite dibujar elementos 2D en él. </p> + +<p>A continuación se da valor a las variables <code>width</code> and <code>height</code> que corresponden al ancho y alto del elemento <em>canvas</em> (representado por las propiedades <code>canvas.width</code> y <code>canvas.height</code>), de manera que el alto y ancho coincidan con el alto y ancho del navegador (<em>viewport</em>) cuyos valores se obtienen directamente de las propiedades <em>window.innerWidth </em>y <em>window.innerHeight</em>.</p> + +<p>Puede ver que en el código se encadenan varias asignaciones, para obtener valores más rápidamente. Esto se puede hacer.</p> + +<p>La última parte del script, es la siguiente:</p> + +<pre class="brush: js">function random(min, max) { + var num = Math.floor(Math.random() * (max - min + 1)) + min; + return num; +}</pre> + +<p>Esta función recibe dos números como argumentos de entrada (valor mínimo y maximo) y devuelve un número aleatorio entre ellos.</p> + +<h2 id="Modelando_una_pelota_en_nuestro_programa">Modelando una pelota en nuestro programa</h2> + +<p>Nuestro programa tendrá montones de pelotas rebotando por toda la pantalla. Ya que todas las pelotas tendrán el mismo comportamiento, tiene sentido representarlas con un objeto. Empezamos definiendo un constructor para el objeto pelota (<em>Ball</em>), en nuestro código.</p> + +<pre class="brush: js">function Ball(x, y, velX, velY, color, size) { + this.x = x; //posición horizontal + this.y = y; //posición vertical + this.velX = velX; //velocidad horizontal + this.velY = velY; //velocidad vertical + this.color = color; //color + this.size = size; //tamaño +}</pre> + +<p>Aquí incluimos algunos parámetros que serán las propiedades que cada pelota necesita para funcionar en nuestro programa: </p> + +<ul> + <li>las coordenadas <code>x</code> e <code>y</code>— correspondientes a la posición horizontal y vertical de la pelota. Estas pueden variar entre un valor 0 (el la esquina superior izquierda) hasta el valor del ancho y alto del navegador ( esquina inferior derecha).</li> + <li>velocidad horizontal y vertical (<code>velX</code> y <code>velY</code>) — cada pelota tiene una velocidad vertical y horizontal; en la parte práctica, estos valores se añadirán a las coordenadas x e y cuando animemos el movimiento de las pelotas, así en cada incremento de visualización de <em>frame</em>, se desplazarán esta cantidad.</li> + <li><code>color</code> — cada pelota posee un color.</li> + <li><code>size</code> — cada pelota tiene un tamaño, este será su radio en pixels.</li> +</ul> + +<p>Con esto se resuelven las propiedades del objeto, ¿Pero qué hacemos con los métodos? Ya que queremos que las pelotas realicen algo en nuestro programa. </p> + +<h3 id="Dibujando_las_pelotas">Dibujando las pelotas</h3> + +<p>Para dibujar, añadiremos el siguiente método <code>draw()</code> al prototipo del objeto <code>Ball():</code></p> + +<pre class="brush: js">Ball.prototype.draw = function() { + ctx.beginPath(); + ctx.fillStyle = this.color; + ctx.arc(this.x, this.y, this.size, 0, 2 * Math.PI); + ctx.fill(); +}</pre> + +<p>Con esta función cada objeto pelota <code>Ball()</code> puede dibujarse en la pantalla utilizando el contexto 2D definido anteriormente (<code>ctx</code>) </p> + +<ul> + <li>Primero usamos <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/beginPath">beginPath()</a></code> para declarar que empezaremos a dibujar una forma en el <em>canvas</em>.</li> + <li>A continuación usamos el <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code> para definir el color de la forma. Haremos que coincida con la propiedad <code>color.</code></li> + <li>A continuación con el método <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/arc">arc()</a></code> se traza un arco. Sus parámetros son: + <ul> + <li>La posición <code>x</code> e <code>y</code> del centro del arco. Corresponderán a las coordenadas del centro de la pelota.</li> + <li>El radio del arco - que vendrá dado por la propiedad de tamaño <code>size</code> de la pelota.</li> + <li>Los últimos dos parámetros especifican el comienzo y final del arco en radianes. En este caso se especifican 0 y <code>2*PI</code> . Que corresponden a 0 y 360 grados. Esto es un circulo completo. Si se quisiese especificar únicamente medio círculo, 180 grados, se especificaría <code>PI</code>.</li> + </ul> + </li> + <li>Por último con el método <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fill">fill()</a></code> se finaliza el dibujo, y rellena el área de la curva especificada, según se indico con el <code><a href="/en-US/docs/Web/API/CanvasRenderingContext2D/fillStyle">fillStyle</a></code>. </li> +</ul> + +<p>Ya se puede empezar a testear el objeto.</p> + +<ol> + <li>Guarde el código hasta ahora, y cargue el archivo HTML en un navegador.</li> + <li>Abra la consola de JavaScript en el navegador, y refresque la página, para que el tamaño del <em>canvas</em> modifique sus dimensiones adaptándose al <em>viewport</em> con la consola abierta. </li> + <li>Teclee lo siguiente en la consola para crear una nueva pelota. + <pre class="brush: js">var testBall = new Ball(50, 100, 4, 4, 'blue', 10);</pre> + </li> + <li>Pruebe a llamar a las variables miembro: + <pre class="brush: js">testBall.x +testBall.size +testBall.color +testBall.draw()</pre> + </li> + <li>Al teclear la última línea, debería ver que la pelota se dibuja en alguna parte del <em>canvas</em>. </li> +</ol> + +<h3 id="Actualizando_los_datos_de_la_pelota">Actualizando los datos de la pelota</h3> + +<p>Ahora podemos dibujar una pelota en una posición dada, pero para empezar a moverla, se necesita una función de actualización de algún tipo. Podemos añadir el código a continuación, al final del archivo de JavaScript, para añidir un método de actualización <code>update()</code> en el prototipo de la clase <code>Ball()</code></p> + +<pre class="brush: js">Ball.prototype.update = function() { + if ((this.x + this.size) >= width) { + this.velX = -(this.velX); + } + + if ((this.x - this.size) <= 0) { + this.velX = -(this.velX); + } + + if ((this.y + this.size) >= height) { + this.velY = -(this.velY); + } + + if ((this.y - this.size) <= 0) { + this.velY = -(this.velY); + } + + this.x += this.velX; + this.y += this.velY; +}</pre> + +<p>Las cuatro primeras partes de la función verifican si la pelota a alcanzado el borde del <em>canvas</em>. Si es así, se invierte la dirección de la velocidad, para que la pelota se mueva en la dirección contraria. Así, si la pelota va hacia arriba, (<code>velY</code> positiva) , entonces la velocidad vertical es cambiada, para que se mueva hacia abajo (<code>velY</code> negativa).</p> + +<p>Los cuatro posibles casos son: </p> + +<ul> + <li>Verificar si la coordenada <code>x</code> es mayor que el ancho del <em>canvas</em> (la pelota está saliendo por el borde derecho).</li> + <li>Verificar si la coordenada <code>x</code> es menor que la coordenada 0 (la pelota está saliendo por el borde izquierdo)</li> + <li>Verificar si la coordenada <code>y</code> es mayor que la altura del <em>canvas</em> (la pelota está saliendo por el borde inferior).</li> + <li>Verificar si la coordenada <code>y</code> es menor que la coordenada 0 ( la pelota está saliendo por el borde superior).</li> +</ul> + +<p>En cada caso, se ha tenido en cuenta el tamaño (<code>size</code>) de la pelota en los cálculos, ya que las coordenadas <code>x</code> e <code>y</code> corresponden al centro de la pelota, pero lo que queremos ver es el borde de la pelota cuando choca con el perímetro del <em>canvas</em> — que la pelota rebote, cuando está a medio camino fuera de el —.</p> + +<p>Las dos últimas líneas de código, suman la velocidad en x (<code>velX</code>) al valor de la coordenada <code>x</code> , y el valor de la velocidad en y (<code>velY</code>) a la coordenada <code>y</code> — con esto se consigue el efecto de que la pelota se mueva cada vez que este método es llamado. </p> + +<p>Llegados a este punto: ¡continuemos, con las animaciones!</p> + +<h2 id="Animando_las_pelotas">Animando las pelotas</h2> + +<p>Hagamos esto divertido! Ahora vamos a empezar a añadir pelotas al canvas, y animándolas.</p> + +<p>1. Primero, necesitamos algún sitio donde guardas las pelotas. El siguiente arreglo hará esta función — añádela al final de tu código. </p> + +<pre class="brush: js" dir="rtl">var balls = [];</pre> + +<p>Todos los programas que generan animaciones normalmente tienen un bucle de animación, que sirve para actualizar los datos del programa, para entonces generar la imagen correspondiente; esta es la estrategia básica para la mayor parte de juegos y programas similares. </p> + +<p>2. Añadamos las siguientes instrucciones al final del código: </p> + +<pre class="brush: js">function loop() { + ctx.fillStyle = 'rgba(0, 0, 0, 0.25)'; + ctx.fillRect(0, 0, width, height); + + while (balls.length < 25) { + var size = random(10,20); + var ball = new Ball( + // la posición de las pelotas, se dibujará al menos siempre + // como mínimo a un ancho de la pelota de distancia al borde del + // canvas, para evitar errores en el dibujo + random(0 + size,width - size), + random(0 + size,height - size), + random(-7,7), + random(-7,7), + 'rgb(' + random(0,255) + ',' + random(0,255) + ',' + random(0,255) +')', + size + ); + balls.push(ball); + } + + for (var i = 0; i < balls.length; i++) { + balls[i].draw(); + balls[i].update(); + } + + requestAnimationFrame(loop); +}</pre> + +<p>Nuestra función de bucle: <code>loop()</code>, hace lo siguiente: </p> + +<ul> + <li>Define el color de relleno del canvas como negro semi-transparente, entonces dibuja un rectángulo en todo el ancho y alto del canvas, usando <code>fillRect()</code>, (los cuatro parámetros definen las coordenadas de origen, el ancho y el alto del rectángulo). Esto es para cubrir el dibujo del instante anterior antes de actualizar el nuevo dibujo. Si no se realiza este paso, resultará en las imágenes se irán apilando y veremos una especie de serpientes según se mueven por el canvas en vez de las pelotas moviéndose! El color de relleno se define como semitransparente, <code>rgba(0,0,0,0.25)</code>, lo que nos permite que podamos intuir algunos de los dibujos de instantes anteriores, con lo que podremos recrear un poco el efecto de estelas detrás de las pelotas, según se mueven. Pruebe a variar este número para ver como resulta el efecto. </li> + <li>Se crea una nueva instancia de la pelota <code>Ball()</code> usando un número aleatorio mediante la función <code>random()</code>, entonces se añade este elemento al final del arreglo de las pelotas, <code>push()</code>, pero unicamente si el número de pelotas es menor que 25. Así cuando tengamos 25 pelotas en la pantalla, no crearemos nuevas pelotas. Pruebe a variar el número de pelotas en el código: <code>balls.length < 25</code>. Dependiendo de la capacidad de procesamiento del navegador, un número de pelotas muy alto podría ralentizar significativamente la animación. ¡asi que cuidado! </li> + <li>Se recorre el bucle por todo el conjunto de pelotas <code>balls</code> y se ejecuta el método para dibujar, <code>draw()</code>, cada una de las pelotas, y actualizar sus datos, <code>update()</code>, en cada una de ellas, así se conservarán las nuevas posiciones y velocidades para el siguiente intervalo de animación.</li> + <li>Se ejecuta la función de nuevo mediante el método <code>requestAnimationFrame()</code> - cuando este método está continuamente ejecutándose y llama a la misma función, esto ejecutará la función de animación un determinado número de veces por segundo para crear una animación fluida. Esto se realiza normalmente de forma recursiva — lo que quiere decir que la función se llama a sí misma cada vez que se ejecuta, de esa manera se ejecutará una y otra vez de forma continua. </li> +</ul> + +<p>3. Por último, pero no menos importante, añadimos la siguiente línea, al final del código.-- es necesario llamar a la función inicialmente para que la animación comience. </p> + +<pre class="brush: js">loop();</pre> + +<p>Eso es todo para la parte básica — pruebe a guardar el código y refrescar el navegador para comprobar si aparecen las pelotas rebotando!</p> + +<h2 id="Añadiendo_la_detección_de_colisiones">Añadiendo la detección de colisiones</h2> + +<p>Ahora, un poco de diversión, añadamos la detección de colisiones a nuestro código. Así las pelotas, sabrán cuando chocan unas contra otras.</p> + +<ol> + <li>El primer paso, será añadir el código a continuación a continuación de donde se definió el método <code>update()</code>. (en código de <code>Ball.prototype.update</code>) + + <pre class="brush: js">Ball.prototype.collisionDetect = function() { + for (var j = 0; j < balls.length; j++) { + if (!(this === balls[j])) { + var dx = this.x - balls[j].x; + var dy = this.y - balls[j].y; + var distance = Math.sqrt(dx * dx + dy * dy); + + if (distance < this.size + balls[j].size) { + balls[j].color = this.color = 'rgb(' + random(0, 255) + ',' + random(0, 255) + ',' + random(0, 255) +')'; + } + } + } +}</pre> + + <p>Esta función es un poco complicada, así que no hay que preocuparse mucho si de momento no se comprende del todo. </p> + + <ul> + <li>Para cada pelota, necesitamos comprobar si chocará con cada una de las otras pelotas. Para esto, en un bucle <code>for</code> para recorrer todas las pelotas.</li> + <li>Dentro del bucle, usamos un <code>if</code> para comprobar si la pelota que estamos mirando en ese ciclo del bucle <code>for</code> es la pelota que estamos mirando. No queremos mirar si una pelota ha chocado consigo misma. Para esto miramos si la pelota actual (es decir la pelota que está invocando al método que resuelve la detección de colisiones) es la misma que la indicada por el bucle. Usamos un operador <code>!</code> para indicar una negación en la comparación, así que el código dentro de la condición solo se ejecuta si estamos mirando dos pelotas distintas.</li> + <li>Usamos un algoritmo común para comprobar la colisión de los dos pelotas. Básicamente miramos si el área de dos círculos se superponen. Esto se explica mejor en el enlace <a href="/en-US/docs/Games/Techniques/2D_collision_detection">detección de colision 2D</a>.</li> + <li>En este caso, únicamente se define la propiedad de <code>color</code> para las dos pelotas, cambiándolas a un nuevo color aleatorio. Se podría haber hecho cosas más complicadas, como que las pelotas rebotasen una con la otra de forma realista, pero esto habría supuesto un desarrollo más complejo. Para desarrollar esos efectos de simulación física, los desarrolladores tienden a usar librerías de física como <a href="http://wellcaffeinated.net/PhysicsJS/">PhysicsJS</a>, <a href="http://brm.io/matter-js/">matter.js</a>, <a href="http://phaser.io/">Phaser</a>, etc.</li> + </ul> + </li> + <li>También es necesario llamar este método en cada instante de la animación. <code>balls[i].update();</code> en la línea: + <pre class="brush: js">balls[i].collisionDetect();</pre> + </li> + <li>Guardar y refrescar la demo de nuevo y podrá ver como las pelotas cambian de color cuando chocan entre ellas.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si tiene problemas para hacer funcionar este ejemplo, puede comparar su código JavaScript, con el código de la <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/bouncing-balls/main-finished.js">version_final</a> (y también ver como funciona al <a href="http://mdn.github.io/learning-area/javascript/oojs/bouncing-balls/index-finished.html">ejecutarla</a>).</p> +</div> + +<h2 id="Resumen">Resumen</h2> + +<p>Esperamos que se haya divertido escribiendo su propio mundo de pelotas que chocan aleatoriamente, usando objetos y programación orientada a objetos. Esto debería haberle dado una práctica útil y haber sido un buen ejemplo. </p> + +<h2 id="Lea_también">Lea también</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/Canvas_API/Tutorial">Canvas tutorial</a> — una guia de principiante para usar el canvas 2D.</li> + <li><a href="/en-US/docs/Web/API/window/requestAnimationFrame">requestAnimationFrame()</a></li> + <li><a href="/en-US/docs/Games/Techniques/2D_collision_detection">2D detección de colisiones</a></li> + <li><a href="/en-US/docs/Games/Techniques/3D_collision_detection">3D detección de colisiones</a></li> + <li><a href="/en-US/docs/Games/Tutorials/2D_Breakout_game_pure_JavaScript">2D juego de ruptura usando sólo JavaScript</a> — un gran tutorial para principiantes sobre como construir un juego 2D.</li> + <li><a href="/en-US/docs/Games/Tutorials/2D_breakout_game_Phaser">2D juego de ruptura usando Phaser</a> — explica los conceptos fundamentales para construir un juego 2D usando una librería de juegos de JavaScript. </li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects/Adding_bouncing_balls_features", "Learn/JavaScript/Objects")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Conceptos básicos de los objetos JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript orientado a objetos para principiantes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Prototipos de objetos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Herencia en JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Trabajando con datos JSON</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Ejercicio práctico de construcción de objetos</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Añadiendo características a nuestra demo de bouncing balls</a></li> +</ul> diff --git a/files/es/learn/javascript/objects/index.html b/files/es/learn/javascript/objects/index.html new file mode 100644 index 0000000000..191d23bc9f --- /dev/null +++ b/files/es/learn/javascript/objects/index.html @@ -0,0 +1,67 @@ +--- +title: Introducción a los objetos JavaScript +slug: Learn/JavaScript/Objects +tags: + - Aprender + - Artículo + - Assessment + - CodingScripting + - Evaluación + - Guía + - JavaScript + - Objetos + - Principiante + - TopicStub + - Tutorial +translation_of: Learn/JavaScript/Objects +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">En JavaScript, la mayoría de las cosas son objetos, desde características del núcleo de JavaScript como arrays hasta el explorador {{Glossary("API", "APIs")}} construído sobre JavaScript. Incluso puedes crear tus propios objetos para encapsular funciones y variables relacionadas dentro de paquetes eficientes que actúan como prácticos contenedores de datos. La naturaleza de JavaScript basada-en-objetos es importante de entender, si quieres avanzar con tu conocimiento del lenguaje, y por ello hemos hecho este módulo para ayudarte. Aquí enseñamos teoría de objetos y sintaxis en detalle, y luego veremos como crear tus propios objetos.</p> + +<h3 id="¿Buscas_convertirte_en_desarrollador_web_de_front-end">¿Buscas convertirte en desarrollador web de front-end?</h3> + +<p class="summary">Hemos puesto un curso que incluye toda la información esencial que necesitas para alcanzar esa meta</p> + +<p><a class="cta primary" href="/docs/Learn/Front-end_web_developer">Comienza aquí</a></p> + +<h2 id="Prerrequisitos">Prerrequisitos</h2> + +<p>Antes de empezar este módulo deberías estar familiarizado con {{Glossary("HTML")}} and {{Glossary("CSS")}}. Te aconsejamos trabajar los módulos <a href="https://developer.mozilla.org/es/docs/Learn/HTML/Introduccion_a_HTML"> Introducción a HTML</a> y <a href="https://developer.mozilla.org/es/docs/Learn/CSS/Introduction_to_CSS">Introducción a CSS</a> antes de empezar con JavaScript.</p> + +<p>También deberías conocer lo básico de Javascript antes de entrar en detalle en los objetos de Javascript. Antes de empezar este módulo, revisa <a href="/es/docs/Learn/JavaScript/First_steps">Primeros pasos con JavaScript</a> y <a href="/es/docs/Learn/JavaScript/Building_blocks">Elementos básicos de JavaScript</a>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si trabajas en un ordenador, tablet u otro dispositivo donde no puedas editar tus propios ficheros, prueba a ejecutar los ejemplos de código online en páginas como <a href="http://jsbin.com/">JSBin</a> o <a href="https://thimble.mozilla.org/">Thimble</a>.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/Objects/Basics">Principios básicos de los Objetos</a></dt> + <dd>En este primer artículo sobre los objetos en Javascript, aprenderemos los fundamentos de la sintaxis de objetos en Javascript y revisaremos algunas características ya vistas anteriormente en el curso, remarcando el hecho que muchas de ellas son en realidad objetos.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript Orientado a Objetos para principiantes</a></dt> + <dd>Una vez vistos los principios básicos, nos centraremos en JavaScript orientado a objetos (OOJS) — este artículo presenta los elementos básicos de la teoría de programación orientada a objetos (OOP), posteriormente explora la manera en que JavaScript emula las clases de un objeto a través de los constructores de funciones, y cómo crea las instancias de un objeto.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/JavaScript/Objects/Object_prototypes">Prototipos de Objetos</a></dt> + <dd>Los prototipos son el mecanismo por el cual los objetos en JavaScript heredan caraterísticas entre sí, y funcionan de manera distinta a los mecanismos de herencia de los lenguages de programación orientada a objetos clásicos.</dd> + <dt><a href="/es/docs/Learn/JavaScript/Objects/Inheritance">Herencia en JavaScript</a></dt> + <dd><span id="result_box" lang="es"><span>Con la mayoría de los detalles sangrientos de OOJS ahora explicados, este artículo muestra cómo crear clases de objetos "hijo" (constructores) que heredan características de sus clases "principales".</span> <span>Además, presentamos algunos consejos sobre cuándo y dónde puede usar OOJS.</span></span></dd> + <dt><a href="/es/docs/Learn/JavaScript/Objects/JSON">Trabajando con datos JSON</a></dt> + <dd><span id="result_box" lang="es"><span>La notación de objetos JavaScript (JSON) es un formato estándar basado en texto para representar datos estructurados basados en la sintaxis de objetos de JavaScript, que se usa comúnmente para representar y transmitir datos en sitios web (es decir, enviar datos desde el servidor al cliente;</span> <span>se mostrará en una página web).</span> <span>Lo encontrarás con bastante frecuencia, por lo que en este artículo te proporcionamos todo lo que necesitas para trabajar con JSON mediante JavaScript, incluido el análisis del JSON para que puedas acceder a los elementos de datos y escribir su propio JSON.</span></span></dd> + <dt><a href="/es/docs/Learn/JavaScript/Objects/Ejercicio_práctico_de_construcción_de_objetos">Práctica de Construcción de Objetos</a></dt> + <dd><span id="result_box" lang="es"><span>En artículos anteriores vimos toda la teoría esencial de los objetos de JavaScript y los detalles de sintaxis, brindándote una base sólida para comenzar.</span> <span>En este artículo nos sumergimos en un ejercicio práctico, que te dará más práctica en la construcción de objetos personalizados de JavaScript, que producen algo divertido y colorido: algunas pelotas de colores rebotando.</span></span></dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Agregar funciones a nuestra demo de "Pelotas Rebotando"</a></dt> + <dd><span id="result_box" lang="es"><span>En esta evaluación, se espera que utilices la demostración de pelotas que rebotan del artículo anterior como punto de partida y que le agregues algunas características nuevas e interesantes.</span></span></dd> +</dl> + +<h2 id="Vea_también">Vea también</h2> + +<dl> + <dt><a href="https://learnjavascript.online/">Aprender JavaScript</a></dt> + <dd>Un excelente recurso para los aspirantes a desarrolladores web —prenda JavaScript en un entorno interactivo, con lecciones cortas y pruebas interactivas, guiado por una evaluación automatizada. Las primeras 40 lecciones son gratuitas, y el curso completo está disponible por un pequeño pago único.</dd> +</dl> diff --git a/files/es/learn/javascript/objects/inheritance/index.html b/files/es/learn/javascript/objects/inheritance/index.html new file mode 100644 index 0000000000..e1cbba42da --- /dev/null +++ b/files/es/learn/javascript/objects/inheritance/index.html @@ -0,0 +1,400 @@ +--- +title: Herencia en JavaScript +slug: Learn/JavaScript/Objects/Inheritance +translation_of: Learn/JavaScript/Objects/Inheritance +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Con la mayoría de los detalles internos de OOJS (<em>JavaScript Orientado a Objetos) </em>explicados, este artículo muestra cómo crear clases "hijo" (constructores) que heredan características de sus clases "padre". Además, presentamos algunos consejos sobre cuándo y dónde puedes usar OOJS y cómo se crean las clases con la sintaxis moderna de ECMAScript.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td>Conocimientos básicos de informática, una comprensión básica de HTML y CSS, familiaridad con los principios básicos de JavaScript (ver <a href="/en-US/docs/Learn/JavaScript/First_steps">Primeros pasos</a> y <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Construyendo bloques</a>) y conceptos básicos de OOJS (ver <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduccion a objetos</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender cómo es posible implementar la herencia en JavaScript.</td> + </tr> + </tbody> +</table> + +<h2 id="Herencia_prototípica">Herencia prototípica</h2> + +<p>Hasta ahora hemos visto algo de herencia en acción — hemos visto cómo funcionan las cadenas de prototipos, y cómo los miembros son heredados subiendo una cadena. Pero principalmente esto ha involucrado funciones integradas del navegador. ¿Cómo creamos un objeto en JavaScript que hereda de otro objeto?</p> + +<p>Exploremos cómo hacer esto con un ejemplo concreto.</p> + +<h2 id="Primeros_pasos">Primeros pasos</h2> + +<p>Primero que nada, hazte una copia local de nuestro archivo <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-start.html">oojs-class-inheritance-start.html</a> (míralo <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-start.html">corriendo en vivo</a> también). Dentro de aquí encontrarás el mismo ejemplo de constructor de <code>Persona()</code> que hemos estado usando a través del módulo, con una ligera diferencia — hemos definido solo las propiedades dentro del constructor:</p> + +<pre class="brush: js notranslate">function Persona(nombrePila, apellido, edad, genero, intereses) { + this.nombre = { + nombrePila, + apellido + }; + this.edad = edad; + this.genero = genero; + this.intereses = intereses; +};</pre> + +<p><em>Todos</em> los métodos están definidos en el prototipo del constructor. Por ejemplo:</p> + +<pre class="brush: js notranslate">Persona.prototype.saludo = function() { + alert('¡Hola! soy ' + this.nombre.nombrePila + '.'); +};</pre> + +<div class="note"> +<p><strong>Nota</strong>: En el código fuente, también verá los métodos <code>bio()</code> y <code>despedida()</code> definidos. Más tarde verá cómo estos pueden ser heredados por otros constructores.</p> +</div> + +<p>Digamos que quisieramos crear una clase de <code>Profesor</code>, como la que describimos en nuestra definición inicial orientada a objetos, que hereda todos los miembros de <code>Persona</code>, pero también incluye:</p> + +<ol> + <li>Una nueva propiedad, <font face="consolas, Liberation Mono, courier, monospace"><span>materia</span></font> — esto contendrá la materia que el profesor enseña.</li> + <li>Un método actualizado de <code>saludo()</code>, que suena un poco más formal que el método estándar de <code>saludo()</code> — más adecuado para un profesor que se dirige a algunos estudiantes en la escuela.</li> +</ol> + +<h2 id="Definiendo_un_constructor_Profesor">Definiendo un constructor Profesor()</h2> + +<p>Lo primero que tenemos que hacer es crear el constructor Profesor<code>()</code> — añadimos lo siguiente tras el código existente:</p> + +<pre class="brush: js notranslate">function Profesor(nombrePila, apellido, edad, genero, intereses, materia) { + Person.call(this, nombrePila, apellido, edad, genero, intereses); + + this.materia = materia; +}</pre> + +<p>Esto es similar al constructor de Persona en muchos aspectos, pero hay algo extraño aquí que no hemos visto antes: la función call (). Esta función básicamente le permite llamar a una función definida en otro lugar, pero en el contexto actual.<br> + El primer parámetro especifica el valor de this que desea utilizar al ejecutar la función, y los otros parámetros son aquellos que deben pasarse a la función cuando se invoca.</p> + +<p>Queremos que el constructor Profesor() tome los mismos parámetros que el constructor Persona() del que está heredando, por lo que los especificamos todos como parámetros en la invocación call().</p> + +<p>La última línea dentro del constructor simplemente define la nueva propiedad subject que los profesores tendrán y que las personas genéricas no tienen.</p> + +<p>Como nota, podríamos haber simplemente hecho esto:</p> + +<pre class="brush: js notranslate">function Profesor(nombrePila, apellido, edad, genero, intereses, materia) { + this.nombre = { + nombrePila, + apellido + }; + this.edad = edad; + this.genero = genero; + this.intereses = intereses; + this.materia = materia; +}</pre> + +<p>Pero esto es solo definir las propiedades de nuevo, no heredarlas de Persona(), por lo que anula el punto de lo que estamos tratando de hacer. También lleva más líneas de código.</p> + +<h3 id="Heredando_de_un_constructor_sin_parámetros">Heredando de un constructor sin parámetros</h3> + +<p>Nótese que si el constructor del cual se está heredando no toma los valores de sus propiedades de parámetros, no se necesita especificarlos como argumentos adicionales en <code>call()</code>. Por ejemplo, si se tuviera algo muy simple como esto:</p> + +<pre class="brush: js notranslate">function Brick() { + this.width = 10; + this.height = 20; +}</pre> + +<p>Se podrían heredar las propiedades <code>width</code> y <code>height</code> haciendo esto (así como los otros pasos descritos a continuación, por supuesto):</p> + +<pre class="brush: js notranslate">function BlueGlassBrick() { + Brick.call(this); + + this.opacity = 0.5; + this.color = 'blue'; +}</pre> + +<p>Nótese que solo especificamos <code>this</code> dentro de <code>call()</code> — no se requieren otros parámetros ya que no estamos heredando ninguna propiedad del padre que sea establecida por parámetros.</p> + +<h2 id="Estableciendo_el_prototipo_de_Profesor_y_su_referencia_al_constructor">Estableciendo el prototipo de Profesor() y su referencia al constructor</h2> + +<p>Todo va bien hasta ahora, pero tenemos un problema. Definimos un nuevo constructor, y tiene una propiedad <code>prototype</code>, la cual por defecto solo contiene una referencia a la función constructor en sí misma. No contiene los métodos de la propiedad <code>prototype</code> del constructor <code>Persona</code>. Para ver esto, introduzca <code>Object.getOwnPropertyNames(Profesor.prototype)</code> ya sea en el campo de texto o en la consola de Javascript . Introdúzcalo nuevamente, reemplazando <code>Profesor</code> con <code>Persona</code>. El nuevo constructor tampoco hereda esos métodos. Para ver esto, compare los resultados de <code>Persona.prototype.saludo</code> and <code>Profesor.prototype.saludo</code>. Necesitamos obtener <code>Profesor()</code> para obtener los métodos definidos en el prototipo de <code>Persona()</code>. ¿Cómo lo hacemos?</p> + +<ol> + <li>Añade la siguiente línea debajo de tu adición anterior: + <pre class="brush: js notranslate">Profesor.prototype = Object.create(Persona.prototype);</pre> + Aquí es cuando nuestro amigo <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> sale al rescate de nuevo. En este caso lo estamos usando para crear un nuevo objeto y hacerlo el valor de <code>Profesor.prototype.</code> El nuevo objeto tiene <code>Persona.prototype</code> como su prototipo y por lo tanto heredará, si y cuando lo necesite, todos los métodos disponibles en <code>Persona.prototype</code>.</li> + <li>Necesitamos hacer una cosa más antes de proseguir. Después de agregar la última línea, la propiedad <code>constructor </code>de <code>Profesor.prototype</code> es ahora igual a <code>Persona()</code>, debido a que acabamos de asignar <code>Profesor.prototype</code> para que haga referencia a un objeto que hereda sus propiedades de <code>Persona.prototype</code>! Ahora prueba guardando tu código, carga la página en un explorador e intenta verificar en la consola el valor de <code>Profesor.prototype.constructor</code>.</li> + <li>Esto puede volverse un problema, así que necesitamos corregirlo. Puedes hacerlo regresando a tu código y agregando la siguiente línea al final: + <pre class="brush: js notranslate">Profesor.prototype.constructor = Profesor;</pre> + </li> + <li>Ahora, si guardas y actualizas, el valor de <code>Profesor.prototype.constructor</code> debe regresar <code>Profesor()</code>, como se espera, además de que ahora estamos heredando de <code>Persona()</code>!</li> +</ol> + +<h2 id="Dándole_a_Profesor_un_nuevo_método_saludo">Dándole a Profesor() un nuevo método saludo()</h2> + +<p>Para finalizar nuestro código, necesitamos definir un nuevo método <code>saludo()</code> en el constructor de <code>Profesor()</code>.</p> + +<p>La manera más fácil es definirlo en el prototipo de <code>Profesor()</code> — agrega lo siguiente al final de tu código:</p> + +<pre class="brush: js notranslate">Profesor.prototype.saludo = function() { + var prefijo; + + if (this.genero === 'masculino' || this.genero === 'Masculino' || this.genero === 'm' || this.genero === 'M') { + prefijo = 'Sr.'; + } else if (this.genero === 'female' || this.genero === 'Femenino' || this.genero === 'f' || this.genero === 'F') { + prefijo = 'Sra.'; + } else { + prefijo = 'Sx.'; + } + + alert('Hola. Mi nombre es ' + prefijo + ' ' + this.nombre.apellido + ', y enseño ' + this.materia + '.'); +};</pre> + +<p>Esto muestra el saludo del profesor, el cual además utiliza un prefijo apropiado para su género, resuelto utilizando un bloque else-if.</p> + +<h2 id="Probando_el_ejemplo">Probando el ejemplo</h2> + +<p>Ahora que ha ingresado todo el código, intente creando una instancia de objeto desde <code>Profesor()</code> poniendo lo que sigue al final de su archivo (o algo similar a su elección):</p> + +<pre class="brush: js notranslate">var teacher1 = new Teacher('Dave', 'Griffiths', 31, 'male', ['football', 'cookery'], 'mathematics');</pre> + +<p>Ahora guarde y actualice, e intente accediendo a las propiedades y metodos de su nuevo<code> teacher1</code> objecto, por ejemplo:</p> + +<pre class="brush: js notranslate">teacher1.name.first; +teacher1.interests[0]; +teacher1.bio(); +teacher1.subject; +teacher1.greeting(); +teacher1.farewell();</pre> + +<p>Esto deberia trabajar bien. Las consultas de las líneas 1, 2, 3, y 6 acceden a miembros heredados del genérico<code> Person()</code> constructor (clase). La consulta de la línea 4 accede un miembro que es disponible solamente en el mas especializado<code> Teacher()</code> constructor (clase). La consulta de la línea 5 accedería a un miembro desde<code> Person()</code>, excepto por el hecho que <code>Teacher()</code> tiene sus propios miembros con el mismo nombre, entonces la consulta accede a ese miembro.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si tiene problemas con el funcionamiento, compare su código con nuestra <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-finished.html">versión final</a> (vea <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-finished.html">corriendo en vivo</a> también).</p> +</div> + +<p>La técnica que mostramos aquí no es la única para crear herencia de clases en JavaScript, pero funciona OK, y le dá una buena idea acerca de cómo implementar herencia en JavaScript.</p> + +<p>También estará interesado en verificar algo de las nuevas características de {{glossary("ECMAScript")}} que nos permiten hacer herencia mas claramente en JavaScript (véase <a href="/en-US/docs/Web/JavaScript/Reference/Classes">Classes</a>). No se cubrió todo aquí, como tampoco es soportado aún por todos los navegadores. Todo el otro código de constructores que se discutió aquí en estos artículos son soportados por IE9 o superior, y hay caminos para lograr superiores soportes que estos.</p> + +<p>Un simple camino es usar una librería de JavaScript — la mayoría de las opciones mas populares tienen un facil ajuste de funcionalidad disponible para hacer herencia mas facil y rápido. <a href="http://coffeescript.org/#classes">CoffeeScript</a> por ejemplo provee<code> class</code>, <code>extends</code>, etc.</p> + +<h2 id="Un_ejercicio_mas_allá">Un ejercicio mas allá</h2> + +<p>En nuestra <a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS#Object-oriented_programming_from_10000_meters">Sección teórica de POO</a>, también incluimos una clase <code>Student</code> como un concepto, el cual hereda todas las características de <code>Person</code>, y también tiene un método diferende de <code>greeting()</code> que <code>Person</code> que es mas informal que el saludo de los profesores <code>Teacher</code>. Dele una mirada al saludo de los estudiantes, y trate de implementar su propio constructor de saludo <code>Student()</code> que herede todas las características de <code>Person()</code>, e implemente las diferentes funciones de saludo <code>greeting()</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si tiene problemas resolviendo esto, dele una mirada a nuestra<a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-inheritance-student.html"> versión final</a> (véala tambien <a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-inheritance-student.html">funcionando</a> ).</p> +</div> + +<h2 id="Resúmen_de_miembros_objeto">Resúmen de miembros objeto</h2> + +<p>To summarize, you've basically got three types of property/method to worry about:</p> + +<ol> + <li>Those defined inside a constructor function that are given to object instances. These are fairly easy to spot — in your own custom code, they are the members defined inside a constructor using the <code>this.x = x</code> type lines; in built in browser code, they are the members only available to object instances (usually created by calling a constructor using the <code>new</code> keyword, e.g. <code>var myInstance = new myConstructor()</code>).</li> + <li>Those defined directly on the constructor themselves, that are available only on the constructor. These are commonly only available on built-in browser objects, and are recognized by being chained directly onto a constructor, <em>not</em> an instance. For example, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys">Object.keys()</a></code>.</li> + <li>Those defined on a constructor's prototype, which are inherited by all instances and inheriting object classes. These include any member defined on a Constructor's prototype property, e.g. <code>myConstructor.prototype.x()</code>.</li> +</ol> + +<p>If you are not sure which is which, don't worry about it just yet — you are still learning, and familiarity will come with practice.</p> + +<h2 id="ECMAScript_2015_Classes">ECMAScript 2015 Classes</h2> + +<p>ECMAScript 2015 introduces <a href="/en-US/docs/Web/JavaScript/Reference/Classes">class syntax</a> to JavaScript as a way to write reusable classes using easier, cleaner syntax, which is more similar to classes in C++ or Java. In this section we'll convert the Person and Teacher examples from prototypal inheritance to classes, to show you how it's done.</p> + +<div class="note"> +<p><strong>Note</strong>: This modern way of writing classes is supported in all modern browsers, but it is still worth knowing about how the underlying prototypal inheritance in case you work on a project that requires supporting a browser that doesn't support this syntax (most notably Internet Explorer).</p> +</div> + +<p>Let's look at a rewritten version of the Person example, class-style:</p> + +<pre class="brush: js notranslate">class Person { + constructor(first, last, age, gender, interests) { + this.name = { + first, + last + }; + this.age = age; + this.gender = gender; + this.interests = interests; + } + + greeting() { + console.log(`Hi! I'm ${this.name.first}`); + }; + + farewell() { + console.log(`${this.name.first} has left the building. Bye for now!`); + }; +} +</pre> + +<p>The <a href="/en-US/docs/Web/JavaScript/Reference/Statements/class">class</a> statement indicates that we are creating a new class. Inside this block, we define all the features of the class:</p> + +<ul> + <li>The <code><a href="/en-US/docs/Web/JavaScript/Reference/Classes/constructor">constructor()</a></code> method defines the constructor function that represents our <code>Person</code> class.</li> + <li><code>greeting()</code> and <code>farewell()</code> are class methods. Any methods you want associated with the class are defined inside it, after the contructor. In this example, we've used <a href="/en-US/docs/Web/JavaScript/Reference/Template_literals">template literals</a> rather than string concatenation to make the code easier to read.</li> +</ul> + +<p>We can now instantiate object instances using the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/new"><code>new</code> operator</a>, in just the same way as we did before:</p> + +<pre class="brush: js notranslate">let han = new Person('Han', 'Solo', 25, 'male', ['Smuggling']); +han.greeting(); +// Hi! I'm Han + +let leia = new Person('Leia', 'Organa', 19, 'female' ['Government']]); +leia.farewell(); +// Leia has left the building. Bye for now +</pre> + +<div class="note"> +<p><strong>Note</strong>: Under the hood, your classes are being converted into prototypal Inheritance models — this is just syntactic sugar. But I'm sure you'll agree that it's easier to write.</p> +</div> + +<h3 id="Inheritance_with_class_syntax">Inheritance with class syntax</h3> + +<p>Above we created a class to represent a person. They have a series of attributes that are common to all people; in this section we'll create our specialized <code>Teacher</code> class, making it inherit from <code>Person</code> using modern class syntax. This is called creating a subclass or subclassing.</p> + +<p>To create a subclass we use the <a href="/en-US/docs/Web/JavaScript/Reference/Classes/extends">extends keyword</a> to tell JavaScript the class we want to base our class on.</p> + +<pre class="brush: js notranslate">class Teacher extends Person { + constructor(first, last, age, gender, interests, subject, grade) { + this.name = { + first, + last + }; + + this.age = age; + this.gender = gender; + this.interests = interests; + // subject and grade are specific to Teacher + this.subject = subject; + this.grade = grade; + } +}</pre> + +<p>We can make the code more readable by defining the <a href="/en-US/docs/Web/JavaScript/Reference/Operators/super"><code>super()</code> operator</a> as the first item inside the <code>constructor()</code>. This will call the parent class' constructor, and inherit the members we specify as parameters of <code>super()</code>, as long as they are defined there:</p> + +<pre class="brush: js notranslate">class Teacher extends Person { + constructor(first, last, age, gender, interests, subject, grade) { + super(first, last, age, gender, interests); + + // subject and grade are specific to Teacher + this.subject = subject; + this.grade = grade; + } +} +</pre> + +<p>When we instantiate <code>Teacher</code> object instances, we can now call methods and properties defined on both <code>Teacher</code> and <code>Person</code>, as we'd expect:</p> + +<pre class="brush: js notranslate">let snape = new Teacher('Severus', 'Snape', 58, 'male', ['Potions'], 'Dark arts', 5); +snape.greeting(); // Hi! I'm Severus. +snape.farewell(); // Severus has left the building. Bye for now. +snape.age // 58 +snape.subject; // Dark arts +</pre> + +<p>Like we did with Teachers, we could create other subclasses of <code>Person</code> to make them more specialized without modifying the base class.</p> + +<div class="note"> +<p><strong>Note</strong>: You can find this example on GitHub as <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/es2015-class-inheritance.html">es2015-class-inheritance.html</a> (<a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/es2015-class-inheritance.html">see it live also</a>).</p> +</div> + +<h2 id="Getters_and_Setters">Getters and Setters</h2> + +<p>There may be times when we want to change the values of an attribute in the classes we create or we don't know what the final value of an attribute will be. Using the <code>Teacher</code> example, we may not know what subject the teacher will teach before we create them, or their subject may change between terms.</p> + +<p>We can handle such situations with getters and setters.</p> + +<p>Let's enhance the Teacher class with getters and setters. The class starts the same as it was the last time we looked at it.</p> + +<p>Getters and setters work in pairs. A getter returns the current value of the variable and its corresponding setter changes the value of the variable to the one it defines.</p> + +<p>The modified <code>Teacher</code> class looks like this:</p> + +<pre class="brush: js notranslate">class Teacher extends Person { + constructor(first, last, age, gender, interests, subject, grade) { + super(first, last, age, gender, interests); + // subject and grade are specific to Teacher + this._subject = subject; + this.grade = grade; + } + + get subject() { + return this._subject; + } + + set subject(newSubject) { + this._subject = newSubject; + } +} +</pre> + +<p>In our class above we have a getter and setter for the <code>subject</code> property. We use <strong><code>_</code> </strong> to create a separate value in which to store our name property. Without using this convention, we would get errors every time we called get or set. At this point:</p> + +<ul> + <li>To show the current value of the <code>_subject</code> property of the <code>snape</code> object we can use the <code>snape.subject</code> getter method.</li> + <li>To assign a new value to the <code>_subject</code> property we can use the <code>snape.subject="new value"</code> setter method.</li> +</ul> + +<p>The example below shows the two features in action:</p> + +<pre class="brush: js notranslate">// Check the default value +console.log(snape.subject) // Returns "Dark arts" + +// Change the value +snape.subject="Balloon animals" // Sets _subject to "Balloon animals" + +// Check it again and see if it matches the new value +console.log(snape.subject) // Returns "Balloon animals" +</pre> + +<div class="note"> +<p><strong>Note</strong>: You can find this example on GitHub as <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/es2015-getters-setters.html">es2015-getters-setters.html</a> (<a href="https://mdn.github.io/learning-area/javascript/oojs/advanced/es2015-getters-setters.html">see it live also</a>).</p> +</div> + +<h2 id="When_would_you_use_inheritance_in_JavaScript">When would you use inheritance in JavaScript?</h2> + +<p>Particularly after this last article, you might be thinking "woo, this is complicated". Well, you are right. Prototypes and inheritance represent some of the most complex aspects of JavaScript, but a lot of JavaScript's power and flexibility comes from its object structure and inheritance, and it is worth understanding how it works.</p> + +<p>In a way, you use inheritance all the time. Whenever you use various features of a Web API , or methods/properties defined on a built-in browser object that you call on your strings, arrays, etc., you are implicitly using inheritance.</p> + +<p>In terms of using inheritance in your own code, you probably won't use it often, especially to begin with, and in small projects. It is a waste of time to use objects and inheritance just for the sake of it when you don't need them. But as your code bases get larger, you are more likely to find a need for it. If you find yourself starting to create a number of objects that have similar features, then creating a generic object type to contain all the shared functionality and inheriting those features in more specialized object types can be convenient and useful.</p> + +<div class="note"> +<p><strong>Note</strong>: Because of the way JavaScript works, with the prototype chain, etc., the sharing of functionality between objects is often called <strong>delegation</strong>. Specialized objects delegate functionality to a generic object type.</p> +</div> + +<p>When using inheritance, you are advised to not have too many levels of inheritance, and to keep careful track of where you define your methods and properties. It is possible to start writing code that temporarily modifies the prototypes of built-in browser objects, but you should not do this unless you have a really good reason. Too much inheritance can lead to endless confusion, and endless pain when you try to debug such code.</p> + +<p>Ultimately, objects are just another form of code reuse, like functions or loops, with their own specific roles and advantages. If you find yourself creating a bunch of related variables and functions and want to track them all together and package them neatly, an object is a good idea. Objects are also very useful when you want to pass a collection of data from one place to another. Both of these things can be achieved without use of constructors or inheritance. If you only need a single instance of an object, then you are probably better off just using an object literal, and you certainly don't need inheritance.</p> + +<h2 id="Alternativas_para_extender_la_cadena_del_prototipos">Alternativas para extender la cadena del prototipos</h2> + +<p>En JavaScript, hay varias maneras diferentes de extender el prototipo de un objeto aparte de lo que hemos mostrado anteriormente. Para saber más sobre las otras formas, visite nuestro artículo <a href="/es/docs/Web/JavaScript/Herencia_y_la_cadena_de_protipos">Herencia y la cadena de prototipos</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Este artículo ha cubierto el resto de la teoría y sintaxis central de OOJS que creemos que debería conocer ahora. En este punto debe entender los conceptos básicos de objetos JavaScript y POO, prototipos y herencia de prototipos, cómo crear clases (constructores) e instancias de objetos, añadir características a las clases y crear subclases que heredan de otras clases.</p> + +<p>En el siguiente artículo veremos cómo trabajar con JavaScript Object Notation (JSON), un formato común de intercambio de datos escrito con objetos JavaScript.</p> + +<h2 id="Véase_también">Véase también</h2> + +<ul> + <li><a href="http://www.objectplayground.com/">ObjectPlayground.com</a> — A really useful interactive learning site for learning about objects.</li> + <li><a href="https://www.amazon.com/gp/product/193398869X/">Secrets of the JavaScript Ninja</a>, Chapter 6 — A good book on advanced JavaScript concepts and techniques, by John Resig and Bear Bibeault. Chapter 6 covers aspects of prototypes and inheritance really well; you can probably track down a print or online copy fairly easily.</li> + <li><a href="https://github.com/getify/You-Dont-Know-JS/blob/master/this%20&%20object%20prototypes/README.md#you-dont-know-js-this--object-prototypes">You Don't Know JS: this & Object Prototypes</a> — Part of Kyle Simpson's excellent series of JavaScript manuals, Chapter 5 in particular looks at prototypes in much more detail than we do here. We've presented a simplified view in this series of articles aimed at beginners, whereas Kyle goes into great depth and provides a more complex but more accurate picture.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects/JSON", "Learn/JavaScript/Objects")}}</p> + +<h2 id="En_éste_módulo">En éste módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> diff --git a/files/es/learn/javascript/objects/json/index.html b/files/es/learn/javascript/objects/json/index.html new file mode 100644 index 0000000000..09009165cf --- /dev/null +++ b/files/es/learn/javascript/objects/json/index.html @@ -0,0 +1,339 @@ +--- +title: Trabajando con JSON +slug: Learn/JavaScript/Objects/JSON +tags: + - Arreglos + - Artículo + - Guía + - JSON + - Objetos + - Parsing + - Principiante + - Stringifying + - Tutorial +translation_of: Learn/JavaScript/Objects/JSON +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">JavaScript Object Notation (JSON) es un formato basado en texto estándar para representar datos estructurados en la sintaxis de objetos de JavaScript. Es comúnmente utilizado para transmitir datos en aplicaciones web (por ejemplo: enviar algunos datos desde el servidor al cliente, así estos datos pueden ser mostrados en páginas web, o vice versa). Se enfrentará a menudo con él, así que este artículo le entrega todo lo que necesita saber para trabajar con JSON utilizando JavaScript, incluyendo el análisis JSON para acceder a los datos en su interior, y cómo crear JSON.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Alfabetismo computacional básico, una comprensión básica de HTML y CSS, familiaridad con los temas básicos de JavaScript (vea <a href="/en-US/docs/Learn/JavaScript/First_steps">First steps</a> y <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Building blocks</a>) y OOJS básico (vea <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introduction to objects</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender cómo trabajar con datos almacenados en JSON, y crear objetos JSON propios.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_realmente_JSON">¿Qué es realmente JSON?</h2> + +<p>{{glossary("JSON")}} es un formato de datos basado en texto que sigue la sintaxis de objeto de JavaScript, popularizado por <a href="https://en.wikipedia.org/wiki/Douglas_Crockford">Douglas Crockford</a>. Aunque es muy parecido a la sintaxis de objeto literal de JavaScript, puede ser utilizado independientemente de JavaScript, y muchos entornos de programación poseen la capacidad de leer (convertir; <em>parsear</em>) y generar JSON.</p> + +<p>Los JSON son cadenas - útiles cuando se quiere transmitir datos a través de una red. Debe ser convertido a un objeto nativo de JavaScript cuando se requiera acceder a sus datos. Ésto no es un problema, dado que JavaScript posee un objeto global <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON</a> que tiene los métodos disponibles para convertir entre ellos.</p> + +<div class="note"> +<p><strong>Nota</strong>: Convertir una cadena a un objeto nativo se denomina <em>parsing</em>, mientras que convertir un objeto nativo a una cadena para que pueda ser transferido a través de la red se denomina <em>stringification</em>.</p> +</div> + +<p>Un objeto JSON puede ser almacenado en su propio archivo, que es básicamente sólo un archivo de texto con una extension <code>.json</code>, y una {{glossary("MIME type")}} de <code>application/json</code>.</p> + +<h3 id="Estructura_del_JSON">Estructura del JSON</h3> + +<p>Como se describió previamente, un JSON es una cadena cuyo formato recuerda al de los objetos literales JavaScript. Es posible incluir los mismos tipos de datos básicos dentro de un JSON que en un objeto estándar de JavaScript - cadenas, números, arreglos, booleanos, y otros literales de objeto. Esto permite construir una jerarquía de datos, como ésta:</p> + +<pre class="brush: json">{ + "squadName": "Super hero squad", + "homeTown": "Metro City", + "formed": 2016, + "secretBase": "Super tower", + "active": true, + "members": [ + { + "name": "Molecule Man", + "age": 29, + "secretIdentity": "Dan Jukes", + "powers": [ + "Radiation resistance", + "Turning tiny", + "Radiation blast" + ] + }, + { + "name": "Madame Uppercut", + "age": 39, + "secretIdentity": "Jane Wilson", + "powers": [ + "Million tonne punch", + "Damage resistance", + "Superhuman reflexes" + ] + }, + { + "name": "Eternal Flame", + "age": 1000000, + "secretIdentity": "Unknown", + "powers": [ + "Immortality", + "Heat Immunity", + "Inferno", + "Teleportation", + "Interdimensional travel" + ] + } + ] +}</pre> + +<p>Si se carga este objeto en un programa de JavaScript, convertido (<em>parseado</em>) en una variable llamada <code>superHeroes</code> por ejemplo, se podría acceder a los datos que contiene utilizando la misma notación de punto/corchete que se revisó en el artículo <a href="/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript object basics</a>. Por ejemplo:</p> + +<pre class="brush: js">superHeroes.homeTown +superHeroes['active']</pre> + +<p>Para acceder a los datos que se encuentran más abajo en la jerarquía, simplemente se debe concatenar los nombres de las propiedades y los índices de arreglo requeridos. Por ejemplo, para acceder al tercer superpoder del segundo héroe registrado en la lista de miembros, se debería hacer esto: </p> + +<pre class="brush: js">superHeroes['members'][1]['powers'][2]</pre> + +<ol> + <li>Primero el nombre de la variable — <code>superHeroes</code>.</li> + <li>Dentro de esta variable para acceder a la propiedad <code>members</code> utilizamos <code>["members"]</code>.</li> + <li><code>members</code> contiene un arreglo poblado por objetos. Para acceder al segundo objeto dentro de este arreglo se utiliza <code>[1]</code>.</li> + <li>Dentro de este objeto, para acceder a la propiedad <code>powers</code> utilizamos <code>["powers"]</code>.</li> + <li>Dentro de la propiedad <code>powers</code> existe un arreglo que contiene los superpoderes del héroe seleccionado. Para acceder al tercer superpoder se utiliza <code>[2]</code>.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: El JSON previamente visto se encuentra disponible dentro de una variable en el ejemplo <a href="http://mdn.github.io/learning-area/javascript/oojs/json/JSONTest.html">JSONTest.html</a> (vea el <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/JSONTest.html">código fuente</a>). Intente cargarlo y luego acceder a los datos contenidos en la variable por medio de la consola JavaScript de su navegador.</p> +</div> + +<h3 id="Arreglos_como_JSON">Arreglos como JSON</h3> + +<p>Anteriormente se mencionó que el texto JSON básicamente se parece a un objeto JavaScript, y esto es en gran parte cierto. La razón de esto es que un arreglo es también un JSON válido, por ejemplo:</p> + +<pre class="brush: json">[ + { + "name": "Molecule Man", + "age": 29, + "secretIdentity": "Dan Jukes", + "powers": [ + "Radiation resistance", + "Turning tiny", + "Radiation blast" + ] + }, + { + "name": "Madame Uppercut", + "age": 39, + "secretIdentity": "Jane Wilson", + "powers": [ + "Million tonne punch", + "Damage resistance", + "Superhuman reflexes" + ] + } +]</pre> + +<p>Éste es un JSON perfectamente válido. Para acceder a esta version convertida se debe comenzar con un índice de arreglo, por ejemplo<code>[0]["powers"][0]</code>.</p> + +<h3 id="Otras_notas">Otras notas</h3> + +<ul> + <li>JSON es sólo un formato de datos — contiene sólo propiedades, no métodos.</li> + <li>JSON requiere usar comillas dobles para las cadenas y los nombres de propiedades. Las comillas simples no son válidas.</li> + <li>Una coma o dos puntos mal ubicados pueden producir que un archivo JSON no funcione. Se debe ser cuidadoso para validar cualquier dato que se quiera utilizar (aunque los JSON generados por computador tienen menos probabilidades de tener errores, mientras el programa generador trabaje adecuadamente). Es posible validar JSON utilizando una aplicación como <a href="http://jsonlint.com/">JSONLint</a>.</li> + <li>JSON puede tomar la forma de cualquier tipo de datos que sea válido para ser incluido en un JSON, no sólo arreglos u objetos. Así, por ejemplo, una cadena o un número único podrían ser objetos JSON válidos.</li> + <li>A diferencia del código JavaScript en que las propiedades del objeto pueden no estar entre comillas, en JSON, sólo las cadenas entre comillas pueden ser utilizadas como propiedades.</li> +</ul> + +<h2 id="Aprendizaje_activo_Trabajando_a_través_de_un_ejemplo_de_JSON">Aprendizaje activo: Trabajando a través de un ejemplo de JSON</h2> + +<p>A continuación se muestra un ejemplo de cómo podemos utilizar algunos datos JSON en un sitio web.</p> + +<h3 id="Para_comenzar">Para comenzar</h3> + +<p>Haga una copia local de los archivos <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes.html">heroes.html</a> y <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/style.css">style.css</a>. El último contiene un CSS simple para dar estilo a la página, mientras el primero contiene un HTML muy sencillo:</p> + +<pre class="brush: html"><header> +</header> + +<section> +</section></pre> + +<p>Además de un elemento {{HTMLElement("script")}} que contiene el código JavaScript que se escribirá en este ejercicio. En este momento sólo contiene dos líneas, que hacen referencia a los elementos {{HTMLElement("header")}} y {{HTMLElement("section")}} y los almacena en variables:</p> + +<pre class="brush: js">const header = document.querySelector('header'); +const section = document.querySelector('section');</pre> + +<p>Los datos JSON se encuentran disponibles en GitHub en el siguiente enlace: <a href="https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json</a>.</p> + +<p>Los datos se cargarán en esta página y se desplegarán a través de la manipulación del DOM de esta forma:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13857/json-superheroes.png" style="display: block; margin: 0 auto;"></p> + +<h3 id="Obteniendo_el_JSON">Obteniendo el JSON</h3> + +<p>Para obtener el JSON se utilizará un API llamado {{domxref("XMLHttpRequest")}} (a menudo llamado <strong>XHR</strong>). Éste en un objeto JavaScript muy útil que permite realizar solicitudes de red para recuperar recursos desde un servidor vía JavaScript (por ejemplo: imágenes, texto, JSON, incluso código HTML), con lo que es posible actualizar pequeñas secciones de contenido sin tener que volver a cargar la página entera. Con ello se obtienen páginas web más interactivas, pero está fuera del alcance de este artículo entrar en detalle.</p> + +<ol> + <li>Para empezar, se debe almacenar la URL del JSON que se quiere recuperar en una variable. Agregue lo siguiente al final del código JavaScript: + <pre class="brush: js">const requestURL = 'https://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json';</pre> + </li> + <li>Para crear una solicitud, se necesita crear una nueva instancia de objeto de solicitud desde el constructor<code>XMLHttpRequest</code>, utilizando la palabra clave <code>new</code>. Agregue lo siguiente a continuación de la última línea: + <pre class="brush: js">const request = new XMLHttpRequest();</pre> + </li> + <li>Ahora es necesario abrir una nueva solicitud utilizando el método <code><a href="/en-US/docs/Web/API/XMLHttpRequest/open">open()</a></code>. Agregue la siguiente línea: + <pre class="brush: js">request.open('GET', requestURL);</pre> + + <p>Esto requiere al menos dos parámetros — Existen otros parámetros opcionales disponibles. Sólo se requieren los dos obligatorios para este ejemplo:</p> + + <ul> + <li>El método HTTP a usar cuando se hace una solicitud en red. En este caso <code>GET</code> es adecuado, dado que sólo se estan recuperando algunos datos simples.</li> + <li>La URL a la que se realiza la solicitud — esta es la URL del archivo que se almacenó antes.</li> + </ul> + </li> + <li>Luego, agregue las siguientes dos lineas — establecemos el <code><a href="/en-US/docs/Web/API/XMLHttpRequest/responseType">responseType</a></code> a JSON, de esta forma ese XHR sabe que el servidor estará retornando JSON y que esto debería ser convertido en segundo plano en un objeto JavaScript. Entonces se envía la solicitud con el método <code><a href="/en-US/docs/Web/API/XMLHttpRequest/send">send()</a></code>: + <pre class="brush: js">request.responseType = 'json'; +request.send();</pre> + </li> + <li>La última parte de esta sección comprende la espera por la respuesta a retornar desde el servidor y luego, manejarla. Agregue el siguiente código bajo el código previo: + <pre class="brush: js">request.onload = function() { + const superHeroes = request.response; + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + </li> +</ol> + +<p>En este punto se está almacenando la respuesta a la solicitud (disponible en la propiedad <code><a href="/en-US/docs/Web/API/XMLHttpRequest/response">response</a></code>) en una variable llamada <code>superHeroes</code>; esta variable ahora contendrá el objeto JavaScript basado en el JSON. Luego se pasa el objeto como argumento a dos funciones — la primera llenará el <<code>header></code> con los datos correctos, mientras la segunda creará una tarjeta de información para cada héroe en el equipo y la insertará en <code><section></code>.</p> + +<p>Se ha contenido el código en un manejador de eventos que se activa cuando se dispara el evento de carga (ver <code><a href="/en-US/docs/Web/API/XMLHttpRequestEventTarget/onload">onload</a></code>) — esto es porque el evento de carga se dispara cuando la respuesta ha sido retornada de forma exitosa; de esta manera se garantiza que <code>request.response</code> estará disponible cuando se intente hacer algo con ella.</p> + +<h3 id="Poblando_el_encabezado">Poblando el encabezado</h3> + +<p>Se han obtenido los datos desde el JSON y convertidos en un objeto de JavaScript. Ahora, se utilizarán estos datos escribiendo las dos funciones que fueron referenciadas previamente. Antes que todo, agregue la siguiente definición de función a continuación del código previo:</p> + +<pre class="brush: js">function populateHeader(jsonObj) { + const myH1 = document.createElement('h1'); + myH1.textContent = jsonObj['squadName']; + header.appendChild(myH1); + + const myPara = document.createElement('p'); + myPara.textContent = 'Hometown: ' + jsonObj['homeTown'] + ' // Formed: ' + jsonObj['formed']; + header.appendChild(myPara); +}</pre> + +<p>Se ha llamado al parámetro <code>jsonObj</code>, para recordar que este es un objeto JavaScript originado desde un JSON. Primero se crea un elemento {{HTMLElement("h1")}} con <code><a href="/en-US/docs/Web/API/Document/createElement">createElement()</a></code>, se asigna su <code><a href="/en-US/docs/Web/API/Node/textContent">textContent</a></code> igual a la propiedad <code>squadName</code> del objeto, luego se agrega al encabezado utilizando<code><a href="/en-US/docs/Web/API/Node/appendChild">appendChild()</a></code>. A continuación se realiza una operación muy parecida en un párrafo: se crea, se asigna su contenido de texto y se agrega al encabezado. La única diferencia es que su texto se asigna a una cadena concatenada que contiene las propiedades <code>homeTown</code> y <code>formed</code> del objeto.</p> + +<h3 id="Creación_de_las_tarjetas_de_información_del_héroe">Creación de las tarjetas de información del héroe</h3> + +<p>Luego, agregue la siguiente función al final del código, que crea y muestra las tarjetas de los superhéroes:</p> + +<pre class="brush: js">function showHeroes(jsonObj) { + const heroes = jsonObj['members']; + + for (var i = 0; i < heroes.length; i++) { + const myArticle = document.createElement('article'); + const myH2 = document.createElement('h2'); + const myPara1 = document.createElement('p'); + const myPara2 = document.createElement('p'); + const myPara3 = document.createElement('p'); + const myList = document.createElement('ul'); + + myH2.textContent = heroes[i].name; + myPara1.textContent = 'Secret identity: ' + heroes[i].secretIdentity; + myPara2.textContent = 'Age: ' + heroes[i].age; + myPara3.textContent = 'Superpowers:'; + + const superPowers = heroes[i].powers; + for (var j = 0; j < superPowers.length; j++) { + const listItem = document.createElement('li'); + listItem.textContent = superPowers[j]; + myList.appendChild(listItem); + } + + myArticle.appendChild(myH2); + myArticle.appendChild(myPara1); + myArticle.appendChild(myPara2); + myArticle.appendChild(myPara3); + myArticle.appendChild(myList); + + section.appendChild(myArticle); + } +}</pre> + +<p>Para empezar, se almacena la propiedad <code>members</code> del objeto JavaScript en una nueva variable. Este arreglo contiene múltiples objetos que contienen la información para cada héroe.</p> + +<p>A continuación, se utiliza un ciclo <a href="/en-US/docs/Learn/JavaScript/Building_blocks/Looping_code#The_standard_for_loop">for</a> para recorrer cada objeto en el arreglo. Para cada uno:</p> + +<ol> + <li>Se crean varios elementos nuevos: un<code><article></code>, un <code><h2></code>, tres <code><p></code>s, y una <code><ul></code>.</li> + <li>Se asigna al <code><h2></code> para que muestre el <code>name</code> del héroe.</li> + <li>Se completan los tres párrafos con su <code>secretIdentity</code>, <code>age</code>, y una línea que diga "Superpowers:" para introducir la información de la lista.</li> + <li>Se almacena la propiedad <code>powers</code> en otra variable nueva llamada <code>superPowers</code> — que contiene un arreglo que lista los superpoderes del héroe actual.</li> + <li>Para recorrer los superpoderes del héroe, se utiliza otro ciclo <code>for</code> — para cada uno se crea un elemento <code><li></code>, se asigna el superpoder a él y luego se pone el <code>listItem</code> dentro del elemento <code><ul></code> (<code>myList</code>) utilizando <code>appendChild()</code>.</li> + <li>Lo último es agregar los <code><h2></code>, <code><p></code>s, y <code><ul></code> dentro del <code><article></code> (<code>myArticle</code>), luego se agrega <code><article></code> dentro de <code><section></code>. El orden en que las cosas son agregadas es importante, dado que este es el orden en el que aparecerán dentro del HTML.</li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: Si tiene problemas en lograr que el ejemplo funcione, intente con el código fuente <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished.html">heroes-finished.html</a> (vea también <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished.html">running live</a>.)</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: Si encuentra dificultades en seguir la notacion de punto/corchete que se utiliza para acceder a los objetos de JavaScript, puede ser útil tener el archivo <a href="http://mdn.github.io/learning-area/javascript/oojs/json/superheroes.json">superheroes.json</a> abierto en otra pestaña o en su editor de texto, y revisarlo mientras observa el código JavaScript. También puede referirse al artículo <a href="/en-US/docs/Learn/JavaScript/Objects/Basics">JavaScript object basics</a> para mayor información sobre la notación de punto y corchete.</p> +</div> + +<h2 id="Conversiones_entre_objetos_y_texto">Conversiones entre objetos y texto</h2> + +<p>El ejemplo anterior era simple en términos de acceder al objeto JavaScript, porque se programó la solicitud XHR para convertir el JSON de respuesta directamente en un objeto de JavaScript utilizando:</p> + +<pre class="brush: js">request.responseType = 'json';</pre> + +<p>En algunas ocasiones, se recibirá una cadena JSON sin procesar, y será necesario convertirla en un objeto. Y cuando sea necesario enviar un objeto Javascript a través de la red, será necesario convertirlo a un JSON (una cadena) antes de ser enviado. Afortunadamente, estos dos problemas son muy comunes en el desarrollo web por lo que un objeto JSON integrado está disponible en los navegadores, que contiene los siguientes dos métodos:</p> + +<ul> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/parse">parse()</a></code>: Acepta una cadena JSON como parámetro, y devuelve el objeto JavaScript correspondiente.</li> + <li><code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON/stringify">stringify()</a></code>: Acepta un objeto como parámetro, y devuelve la forma de cadena JSON equivalente.</li> +</ul> + +<p>El primer método se puede observar en el ejemplo <a href="http://mdn.github.io/learning-area/javascript/oojs/json/heroes-finished-json-parse.html">heroes-finished-json-parse.html</a> (vea el <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/json/heroes-finished-json-parse.html">código fuente</a>) — que realiza exactamente lo mismo que el ejemplo que se construyó previamente, excepto porque se determinó que el XHR devolviera el texto JSON sin procesar, luego se utiliza <code>parse()</code> para convertirlo en un objeto JavaScript. El extracto del código es el siguiente:</p> + +<pre class="brush: js">request.open('GET', requestURL); +request.responseType = 'text'; // recibimos una cadena de tipo "string" +request.send(); + +request.onload = function() { + const superHeroesText = request.response; // cogemos la cadena de response + const superHeroes = JSON.parse(superHeroesText); // la convertimos a objeto + populateHeader(superHeroes); + showHeroes(superHeroes); +}</pre> + +<p>Como es de suponer, <code>stringify()</code> trabaja de la forma opuesta. Intente ingresar las siguientes líneas en la consola de JavaScript de su navegador para verlo en acción:</p> + +<pre class="brush: js">const myJSON = { "name": "Chris", "age": "38" }; +myJSON +const myString = JSON.stringify(myJSON); +myString</pre> + +<p>En este caso, se ha creado un objeto JavaScript, luego se comprueba lo que contiene, y entonces se convierte en una cadena JSON utilizando <code>stringify()</code> — guardando el valor retornado en una variable nueva — y comprobándolo nuevamente.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>En este artículo se ha entregado una guía simple para utilizar JSON en sus programas, incluyendo cómo crear y leer JSON, y cómo acceder a los datos almacenados en él. En el artículo siguiente se verá JavaScript orientado a objetos.</p> + +<h2 id="Vea_también">Vea también</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON">JSON object reference page</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest">XMLHttpRequest object reference page</a></li> + <li><a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest">Using XMLHttpRequest</a></li> + <li><a href="/en-US/docs/Web/HTTP/Methods">HTTP request methods</a></li> + <li><a href="http://json.org">Official JSON web site with link to ECMA standard</a></li> +</ul> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects/Object_building_practice", "Learn/JavaScript/Objects")}}</p> diff --git a/files/es/learn/javascript/objects/object-oriented_js/index.html b/files/es/learn/javascript/objects/object-oriented_js/index.html new file mode 100644 index 0000000000..5eb023c685 --- /dev/null +++ b/files/es/learn/javascript/objects/object-oriented_js/index.html @@ -0,0 +1,307 @@ +--- +title: JavaScript orientado a objetos para principiantes +slug: Learn/JavaScript/Objects/Object-oriented_JS +tags: + - Aprender + - Artículo + - Constructor + - Crear + - Create + - JSOO + - JavaScript + - OOJS + - OOP + - Object + - Objeto + - Orientado a Objeto + - Principiante + - Programación orientada a objetos + - instance + - instanciar + - 'l10n:priority' +translation_of: Learn/JavaScript/Objects/Object-oriented_JS +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Con lo básico fuera del camino, nos enfocaremos en Javascript Orientado a Objetos (JSOO) — este artículo presenta una descripción básica de la teoría de la Programación Orientada a Objetos (POO), luego explora cómo Javascript emula classes de objetos via funciones constructoras, y cómo crea instancias de objetos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de computación, entendimiento básico de HTML y CSS, familiaridad con las bases de Javascript (ver <a href="/es/docs/Learn/JavaScript/First_steps">Primeros pasos con JavaScript</a> y <a href="/es/docs/Learn/JavaScript/Building_blocks">Bloques de construcción JavaScript</a>) y las bases de JSOO (ver <a href="/es/docs/Learn/JavaScript/Objects/Basics">Introducción a objetos</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Entender la teoría base de la programación orientada a objetos, como se relaciona esta con JavaScript ("todo es un objeto"), y como crear constructores e instacias de objetos.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Programacion_Orientada_a_Objetos—_lo_básico">Programacion Orientada a Objetos— lo básico</h2> + +<p>Para empezar, daremos una descripción simple y de alto nivel acerca de lo que es la Programación Orientada a Objetos (POO). Decimos simple, porque la POO puede volverse complicada rápidamente, y darte un tratamiento completo ahora, probablemente podría confundirte más que ayudar. La idea básica de la POO es que usamos objetos para modelar cosas del mundo real que queremos representar en nuestros programas, y/o proveemos una simple manera para acceder a la funcionalidad que, de otra manera, sería difícil o imposible de usar.</p> + +<p>Los objetos pueden contener información y código relacionados, los cuales representan información acerca de lo que estás tratando de modelar, y la funcionalidad o comportamiento que deseas que tenga. Los datos de un Objeto (y frecuentemente, también las funciones) se pueden almacenar ordenadamente (la palabra oficial es <strong>encapsular</strong>) dentro del paquete de un objeto (al que se puede asignar un nombre específico, llamado a veces <strong>espacio de nombres</strong>), haciéndolo fácil de estructurar y acceder; los objetos también se usan comúnmente como almacenes de datos que se pueden enviar fácilmente a través de la red.</p> + +<h3 id="Definiendo_una_plantilla_de_objeto">Definiendo una plantilla de objeto</h3> + +<p>Vamos a considerar un sencillo programa que muestra información sobre estudiantes y profesores en una escuela. Aquí daremos un vistazo a la POO (Programación Orientada a Objetos) en general, no en el contexto de algún lenguaje de programación específico.</p> + +<p>Para empezar, podríamos volver a ver al objeto <code>Persona</code> de nuestro <a href="/es/docs/Learn/JavaScript/Objects/Basics">artículo de primeros objetos</a>, que define los datos generales y funcionalidades de una persona. Hay muchas cosas que podrías saber acerca de una persona (su dirección, estatura, tamaño de calzado, perfil de ADN, número de pasaporte, rasgos significativos de su personalidad...), pero, en este caso, solo estamos interesados en mostrar su nombre, edad, género e intereses, además de una pequeña introducción sobre este individuo basada en los datos anteriores. También queremos que sea capaz de saludar. </p> + +<p>Esto es conocido como <strong>abstracción</strong> — crear un modelo simple de algo complejo que represente sus aspectos más importantes y que sea fácil de manipular para el propósito de nuestro programa.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13889/person-diagram.png" style="display: block; height: 219px; margin: 0px auto; width: 610px;"></p> + +<p>En algunos lenguajes de POO, esta definición de tipo de objeto se la llama <strong>class </strong>(JavaScript utiliza diferentes mecanismos y terminologías, como verás a continuación) — esto no es en realidad un objeto, en vez de esto es un modelo que define las características que un objeto debería tener.</p> + +<h3 id="Creando_objetos">Creando objetos</h3> + +<p>Partiendo de nuestra clase, podemos crear <strong>instancias de objetos</strong> — objetos que contienen los datos y funcionalidades definidas en la clase original. Teniendo a nuestra clase <code>Persona</code>, ahora podemos crear gente con características más específicas: </p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/15163/MDN-Graphics-instantiation-2-fixed.png" style="display: block; height: 702px; margin: 0px auto; width: 695px;"></p> + +<p>Cuando una instancia del objeto es creada a partir de una clase, se ejecuta <strong>la función constructora </strong>(constructor en inglés) de la clase para crearla. El proceso de crear una instancia del objeto desde una clase se llama <strong>instanciación</strong>.</p> + +<h3 id="Clases_especializadas">Clases especializadas</h3> + +<p>En este caso nosotros no queremos personas genericas — queremos docentes y estudiantes, que son los dos tipos más específicos de personas. En POO, podemos crear nuevas clases basadas en otras clases, estas nuevas <strong>clases secundarias</strong> se pueden hacer para <strong>heredar</strong> los datos y código de su <strong>clase primaria</strong>, de modo que pueden reutilizar la funcionalidad común a todos los tipos de objetos en lugar de tener que duplicarla. Cuando la funcionalidad difiere entre clases, puedes definir funciones especializadas directamente en ellas según sea necesario.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13881/MDN-Graphics-inherited-3.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p> + +<p>Esto es realmente útil, los profesores y los estudiantes comparten muchas características comunes como el nombre, el género y la edad, por lo que es conveniente tener que definir esas características solo una vez. También puedes definir la misma característica por separado en diferentes clases, ya que cada definición de esa característica estará en un espacio de nombres diferente. Por ejemplo, el saludo de un estudiante puede tener la forma "Yo, soy [Nombre]" (por ejemplo, Yo, soy Sam), mientras que un profesor puede usar algo más formal, como "Hola, mi nombre es [Prefix] [lastName], y enseño [Asunto] ". (Por ejemplo, Hola, mi nombre es Sr. Griffiths, y yo enseño Química).</p> + +<div class="note"> +<p><strong>Nota: </strong>la palabra elegante para la capacidad de múltiples tipos de objetos de implementar la misma funcionalidad es <strong>polimorfismo. </strong>Por si acaso te preguntabas.</p> +</div> + +<p>Ahora puedes crear instancias de objetos de las clases "hijo". Por ejemplo:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13885/MDN-Graphics-instantiation-teacher-3.png" style="display: block; height: 743px; margin: 0px auto; width: 700px;"></p> + +<p>En el resto del articulo, comenzaremos a ver como podemos practicar la teoría de POO en JavaScript.</p> + +<h2 id="Constructores_e_instancias_de_objetos">Constructores e instancias de objetos</h2> + +<p>Algunas personas sostienen que JavaScript no es un verdadero lenguaje orientado a objetos — por ejemplo, su enunciado <code><a href="/es/docs/Web/JavaScript/Reference/Statements/class">class</a></code> es sólo azúcar sintáctica sobre la herencia prototípica existente y no es una <code>class</code> en el sentido tradicional. JavaScript, utiliza funciones especiales llamadas funciones constructoras para definir objetos y sus características. Son útiles porque a menudo te encontrarás con situaciones en las que no sabes cuántos objetos crearás; los constructores proporcionan los medios para crear tantos objetos como necesites de una manera efectiva, adjuntando datos y funciones a ellos según sea necesario.</p> + +<p>Cuando se crea una nueva instancia del objeto a partir de una función constructora, su funcionalidad central (tal como se define en su prototipo, que exploraremos en el <a href="/es/docs/Learn/JavaScript/Objects/Object_prototypes">artículo Prototipos</a> de objetos) no se copia en el nuevo objeto como lenguajes OO "clásicos", sino que la funcionalidad está vinculada a través de una cadena de referencia llamada cadena prototipo. Así que esto no es una verdadera instanciación, estrictamente hablando, JavaScript usa un mecanismo diferente para compartir funcionalidad entre objetos.</p> + +<div class="note"> +<p><strong>Nota: </strong>no ser "POO clásica" no es necesariamente algo malo; Como se mencionó anteriormente, la POO puede ser muy compleja muy rápidamente, y JavaScript tiene algunas agradables formas de aprovechar las características de la OO sin tener que profundizar demasiado en ello.</p> +</div> + +<p>Exploremos la creación de clases a través de constructores y la creación de instancias de objetos a partir de ellas en JavaScript. En primer lugar, nos gustaría que hicieras una nueva copia local del archivo <code>oojs.html</code> que vimos en nuestro primer artículo de Objetos.</p> + +<h3 id="Un_ejemplo_simple">Un ejemplo simple</h3> + +<ol> + <li>Comencemos por ver cómo puedes definir una persona con una funcion normal. Agrega esta funcion dentro del elemento <code>script</code>: + + <pre class="brush: js notranslate">function createNewPerson(name) { + var obj = {}; + obj.name = name; + obj.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; + return obj; +}</pre> + </li> + <li>Ahora puedes crear una nueva persona llamando a esta funcion — prueba con las siguientes lineas en la consola Javascript de tu navegador: + <pre class="brush: js notranslate">var salva = createNewPerson('Salva'); +salva.name; +salva.greeting();</pre> + Esto funciona bastante bien, pero es un poco largo; si sabemos que queremos crear un objeto, ¿por qué necesitamos crear explícitamente un nuevo objeto vacío y devolverlo? Afortunadamente, JavaScript nos proporciona un práctico acceso directo, en forma de funciones constructoras — ¡hagamos una ahora!</li> + <li>Reemplaza tu función anterior por la siguiente: + <pre class="brush: js notranslate">function Person(name) { + this.name = name; + this.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; +}</pre> + </li> +</ol> + +<p>La función constructora es la versión de JavaScript de una clase. Notarás que tiene todas las características que esperas en una función, aunque no devuelve nada o crea explícitamente un objeto — básicamente sólo define propiedades y métodos. Verás que la palabra clave <code>this</code> se está usando aquí también — es básicamente decir que cuando se crea una de estas instancias de objeto, la propiedad <code>name</code> del objeto será igual al valor del nombre pasado a la llamada del constructor, y el método <code>greeting()</code> usará también el valor del nombre pasado a la llamada del constructor.</p> + +<div class="note"> +<p><strong>Nota</strong>: Un nombre de función constructora generalmente comienza con una letra mayúscula — esta convención se utiliza para hacer que las funciones constructoras sean más fáciles de reconocer en el código.</p> +</div> + +<p>Entonces, ¿cómo llamamos a un constructor para crear algunos objetos?</p> + +<ol> + <li>Agrega las siguientes líneas debajo de tu código anterior: + <pre class="brush: js notranslate">var person1 = new Person('Bob'); +var person2 = new Person('Sarah');</pre> + </li> + <li>Guarda el código y vuelve a cargarlo en el navegador, e intenta ingresar las siguientes líneas en la consola Javascript : + <pre class="brush: js notranslate">person1.name +person1.greeting() +person2.name +person2.greeting()</pre> + </li> +</ol> + +<p>¡Guaw! Ahora veras que tenemos dos nuevos objetos, cada uno de los cuales está almacenado en un espacio de nombres diferente: para acceder a sus propiedades y métodos, debes llamarlos como <code>person1</code> o <code>person2</code>; están cuidadosamente empaquetados para que no entren en conflicto con otras funciones. Sin embargo, tienen disponible la misma propiedad name y el método <code>greeting()</code>. Ten en cuenta que están utilizando su propio <code>name</code> que se les asignó cuando se crearon; esta es una razón por la cual es muy importante usar <code>this</code>, para que usen sus propios valores, y no algún otro valor.</p> + +<p>Veamos nuevamente las llamadas del constructor:</p> + +<pre class="brush: js notranslate">var person1 = new Person('Bob'); +var person2 = new Person('Sarah');</pre> + +<p>En cada caso, la palabra clave <code>new</code> se usa para indicarle al navegador que queremos crear una nueva instancia del objeto, seguida del nombre de la función con sus parámetros requeridos entre paréntesis, y el resultado se almacena en una variable — muy similar a cómo se llama a una función estándar. Cada instancia se crea de acuerdo con esta definición:</p> + +<pre class="brush: js notranslate">function Person(name) { + this.name = name; + this.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); + }; +}</pre> + +<p>Una vez creados los nuevos objetos, las variables <code>person1</code> y <code>person2</code> contienen los siguientes objetos:</p> + +<pre class="brush: js notranslate">{ + name: 'Bob', + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +} + +{ + name: 'Sarah', + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +}</pre> + +<p>Ten en cuenta que cuando llamamos a nuestra función constructora, estamos definiendo <code>greeting()</code> cada vez, lo cual no es lo ideal. Para evitar esto, podemos definir funciones en el prototipo, que veremos más adelante.</p> + +<h3 id="Creando_nuestro_constructor_final">Creando nuestro constructor final</h3> + +<p>El ejercicio que vimos anteriormente fue solo un ejemplo simple para comenzar. Ahora crearemos nuestra función <code>constructor Person()</code> final.</p> + +<ol> + <li>Elimina el código que insertaste hasta ahora y agrega este constructor de reemplazo; este es exactamente el mismo que el ejemplo simple del principio, con un poco más de complejidad: + <pre class="brush: js notranslate">function Person(first, last, age, gender, interests) { + this.name = { + 'first': first, + 'last' : last + }; + this.age = age; + this.gender = gender; + this.interests = interests; + this.bio = function() { + alert(this.name.first + ' ' + this.name.last + ' is ' + this.age + ' years old. He likes ' + this.interests[0] + ' and ' + this.interests[1] + '.'); + }; + this.greeting = function() { + alert('Hi! I\'m ' + this.name.first + '.'); + }; +}</pre> + </li> + <li>Ahora, agrega la siguiente línea para crear una instancia del objeto: + <pre class="brush: js notranslate">var person1 = new Person('Bob', 'Smith', 32, 'male', ['music', 'skiing']);</pre> + </li> +</ol> + +<p>Ahora verás que puedes acceder a las propiedades y métodos justo como lo hiciste anteriormente — intenta esto en tu consola JS:</p> + +<pre class="brush: js notranslate">person1['age'] +person1.interests[1] +person1.bio() +// etc.</pre> + +<div class="note"> +<p><strong>Nota</strong>: Si tienes problemas para lograr que funcione, puedes comparar tu código con nuestra versión — ve <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-finished.html">oojs-class-finished.html</a> (también lo puedes ver <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-finished.html">corriendo en vivo</a>).</p> +</div> + +<h3 id="Ejercicios_adicionales">Ejercicios adicionales</h3> + +<p>Para empezar, intenta añadir un par de líneas de creación de objetos propias, y trata de obtener y asignar valores a los miembros de las instancias del objeto.</p> + +<p>Además, hay un par de problemas con nuestro método <code>bio()</code> — la salida siempre incluye el pronombre "He", incluso para personas de otros géneros. Y <code>bio</code> solamente incluye dos intereses, sin importar la cantidad que hay en el arreglo <code>interests</code>. ¿Podrías corregir esto en la definición de la clase (constructor)? Puedes poner cualquier código dentro de un constructor (probablemente necesites algunos condicionales y un bucle). Piensa como se deben estructurar las declaraciones dependiendo del género, y de la cantidad de intereses.</p> + +<div class="note"> +<p><strong>Note</strong>: Si estás atascado, hay una <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">respuesta en nuestro repositorio de GitHub</a> (<a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">see it live</a>) — igualmente ¡intentea resolverla primero!</p> +</div> + +<h2 id="Otras_formas_de_crear_instancias_de_objetos">Otras formas de crear instancias de objetos</h2> + +<p>Hasta ahora hemos visto dos diferentes formas de crear una instancia de objeto — <a href="/es/docs/Learn/JavaScript/Objects/Basics#Object_basics">declarando un objeto literal</a>, y usando una función constructora (ver arriba).</p> + +<p>Esto tiene sentido, pero hay otras formas — se muestran aquí para que te vayas familiarizando en caso de encontrarte con ellas.</p> + +<h3 id="El_constructor_Object">El constructor Object()</h3> + +<p>Antes que nada, puedes usar el constructor <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object">Object()</a></code> para crear un nuevo objeto. Si, incluso objetos genéricos tienen un constructor que genera un objeto vacío.</p> + +<ol> + <li>Intenta ingresar este código en la consola JavaScript de tu navegador: + <pre class="brush: js notranslate">var person1 = new Object();</pre> + </li> + <li>Esto guarda un objeto vacío en la variable <code>person1</code>. Luego pueded agregar propiedades y métodos a este objeto usando la notación de punto (.) o de corchetes (['']); prueba estos ejemplos en tu consola: + <pre class="brush: js notranslate">person1.name = 'Chris'; +person1['age'] = 38; +person1.greeting = function() { + alert('Hi! I\'m ' + this.name + '.'); +};</pre> + </li> + <li>También puedes pasar un objeto literal como parámetro al constructor <code>Object()</code>, para precargarlo con propiedades/métodos. Prueba esto en tu consola: + <pre class="brush: js notranslate">var person1 = new Object({ + name: 'Chris', + age: 38, + greeting: function() { + alert('Hi! I\'m ' + this.name + '.'); + } +});</pre> + </li> +</ol> + +<h3 id="Usando_el_método_create">Usando el método create()</h3> + +<p>Los constructores te pueden ayudar a ordenar tu código — puedes crear constructores en un lugar, y luego crear instancias cuando sean necesarias.</p> + +<p>Sin embargo, algunas personas prefieren crear instancias de objetos sin crear antes constructores, especialmente si van a crear solamente pocas instancias de un objeto.</p> + +<p>JavaScript tiene un método llamado <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">create()</a></code> que permite hacer esto. Con este método puedes crear un nuevo objeto basado en cualquier otro objeto existente.</p> + +<ol> + <li>Con tu ejercicio de la sección anterior cargado en el navegador, prueba esto en tu consola JavaScript + <pre class="brush: js notranslate">var person2 = Object.create(person1);</pre> + </li> + <li>Y ahora prueba esto: + <pre class="brush: js notranslate">person2.name +person2.greeting()</pre> + </li> +</ol> + +<p>Verás que <code>person2</code> fue creado basado en <code>person1 </code>— tiene las mismas propiedades y métodos.</p> + +<p>Una limitación del método <code>create()</code> es que no está soportado por el navegador IE8. Por lo que los constructores serán más efectivos sin necesitas soportar navegadores antiguos.</p> + +<p>Más tarde, exploraremos en detalle los efectos de <code>create()</code>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Este artículo provee una visión simplificada de la teoría de la orientación a objetos — esta no es toda la historia, pero te da una idea de con que estamos lidiando aquí. Adicionalmente, empezamos a ver como JavaScript está relacionado y difiere de la orientación a objetos "clásica", cómo usamos funciones constructoras para implementar clases en JavaScript, y diferentes formas de generar instancias de objetos.</p> + +<p>En el próximo artículo, exploraremos los prototipos de objeto JavaScript.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Basics", "Learn/JavaScript/Objects/Object_prototypes", "Learn/JavaScript/Objects")}}</p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="/es/docs/Learn/JavaScript/Objects/Basics">Objetos básicos</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Object-oriented_JS">JavaScript orientedo a objetos para principiantes</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Object_prototypes">Prototipos de Objetos</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Inheritance">Herencia en JavaScript</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/JSON">Trabajando con datos JSON</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Object_building_practice">Práctica de construcción de objetos</a></li> + <li><a href="/es/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Agregar funciones a nuestro demo de pelotas que rebotan</a></li> +</ul> diff --git a/files/es/learn/javascript/objects/object_prototypes/index.html b/files/es/learn/javascript/objects/object_prototypes/index.html new file mode 100644 index 0000000000..852dd5e70e --- /dev/null +++ b/files/es/learn/javascript/objects/object_prototypes/index.html @@ -0,0 +1,282 @@ +--- +title: Prototipos de objetos +slug: Learn/JavaScript/Objects/Object_prototypes +tags: + - Aprender + - Artículo + - Cadena de Prototipos + - Constructor + - JavaScript + - Objetos + - Principiante + - Prototipo + - create() +translation_of: Learn/JavaScript/Objects/Object_prototypes +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</div> + +<p class="summary">Los prototipos son un mecanismo mediante el cual los objetos en JavaScript heredan características entre sí. En este artículo, explicaremos como funcionan los prototipos y también cómo se pueden usar las propiedades de estos para añadir métodos a los contructores existentes.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitios:</th> + <td>Conocer las funciones en Javascript, conocimientos básicos de Javascript (ver <a href="/en-US/docs/Learn/JavaScript/First_steps">Primeros Pasos</a> y <a href="/en-US/docs/Learn/JavaScript/Building_blocks">Building blocks</a>) y Javascript orientado a Objetos (ver <a href="/en-US/docs/Learn/JavaScript/Object-oriented/Introduction">Introducción a Objetos</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender los prototipos de objectos de Javascript, cómo funciona la cadena de prototype, y cómo añadir nuevos métodos a la propiedad prototype.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Un_lenguaje_basado_en_prototipos">¿Un lenguaje basado en prototipos?</h2> + +<p>JavaScript es a menudo descrito como un <strong>lenguaje basado en prototipos - </strong>para proporcionar mecanismos de herencia, los objetos pueden tener un <strong>objeto prototipo</strong>, el cual actúa como un objeto plantilla que hereda métodos y propiedades.</p> + +<p>Un objeto prototipo del objeto puede tener a su vez otro objeto prototipo, el cual hereda métodos y propiedades, y así sucesivamente. Esto es conocido con frecuencia como la <strong>cadena de prototipos</strong>, y explica por qué objetos diferentes pueden tener disponibles propiedades y métodos definidos en otros objetos.</p> + +<p>Bien, para ser exactos, los métodos y propiedades son definidos en la propiedad <code>prototype</code>, que reside en la función constructora del objeto, no en la instancia misma del objeto.</p> + +<p>En JavaScript, se establece un enlace entre la instancia del objeto y su prototipo (su propiedad <code>__proto__,</code> la cual es derivada de la propiedad <code>prototype</code> sobre el constructor), y las propiedades y metodos son encontrados recorriendo la cadena de prototipos.</p> + +<p><strong>Nota:</strong> Es importante entender que, tanto el prototipo de la instancia de un objeto (al cual se accede mediante <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf">Object.getPrototypeOf(obj)</a></code>, o a través de la propiedad <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/proto">__proto__</a></code>) como el prototipo que contiene el constructor (que se encuentra en la propiedad <code>prototype</code> del constructor) hacen referencia al mismo objeto.</p> + +<p>Vamos a echar un vistazo a algunos ejemplos para intentar aclarar estos conceptos.</p> + +<h2 id="Entendiendo_objectos_prototipos">Entendiendo objectos prototipos</h2> + +<p>Volvamos al ejemplo anterior en el que acabamos definiendo nuestro constructor <code>Person()</code> — cargue el ejemplo en su navegador. Si aún no lo tienes luego de haber trabajado el último artículo, usa nuestro ejemplo oojs-class-further-exercises.html (vea también el <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">código fuente</a>).</p> + +<p>En este ejemplo, hemos definido una función constructor, así:</p> + +<pre class="brush: js notranslate">function Persona(nombre, apellido, edad, genero, intereses) { + + // definiendo de propiedades y métodos + this.first = first; + this.last = last; +//... +} +</pre> + +<p>Entonces hemos creado una instancia de un objeto como este:</p> + +<pre class="brush: js notranslate">var person1 = new Persona('Bob', 'Smith', 32, 'hombre', ['music', 'skiing']);</pre> + +<p>Si escribe "person1." en su consola JavaScript, debería ver que el navegador intenta completarlo automáticamente con los nombres de miembro disponibles en este objeto:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13853/object-available-members.png" style="display: block; margin: 0 auto;"></p> + +<p>En esta lista, podra ver los miembros definidos en el objeto prototipo de person1, que es la Persona() (Persona() es el constructor) - nombre, edad, género, intereses, biografía y saludos. Sin embargo, también verá algunos otros miembros - watch, valueOf, etc - que están definidos en el objeto prototipo de Persona() 's, que es un Objeto (Object). Esto demuestra que el prototipo cadena funciona.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13891/MDN-Graphics-person-person-object-2.png" style="display: block; height: 150px; margin: 0px auto; width: 700px;"></p> + +<p>Entonces, ¿qué sucede si llama a un método en <code>person1</code>, que está definido en <code>Object</code>? Por ejemplo:</p> + +<pre class="brush: js notranslate">person1.valueOf()</pre> + +<p>Este método <a href="https://wiki.developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/valueOf">valueOf()</a> simplemente retornará el valor del objeto sobre el que se llama - ¡pruébalo y verás! En este caso, lo que pasa es que:</p> + +<ul> + <li>El navegador comprueba inicialmente si el objeto person1 tiene un método valueOf() disponible en él.</li> + <li>Si no lo hace, entonces el navegador comprueba si el objeto prototipo del objeto person1 (el prototipo del constructor de Persona()) tiene un método valueOf() disponible en él.</li> + <li>Si tampoco lo hace, entonces el navegador comprueba si el objeto prototipo del objeto prototipo del constructor Persona() (Objeto() prototipo del objeto prototipo del constructor) tiene un método valueOf() disponible en él. Lo hace, así que es llamado, y todo funciona!</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Queremos reiterar que los métodos y propiedades no se copian de un objeto a otro en la cadena del prototipo. Ellos son accedidos subiendo por la cadena como se ha descrito anteriormente.</p> +</div> + +<div class="note"> +<p><strong>Nota</strong>: No existe oficialmente una forma de acceder directamente al objeto prototipo de un objeto - los "enlaces" entre los elementos de la cadena están definidos en una propiedad interna, denominada [[prototipo]] en la especificación del lenguaje JavaScript (ver {{glossary("ECMAScript")}}).</p> + +<p>La mayoría de los navegadores modernos, sin embargo, ofrecen una propiedad disponible llamada __proto__ (es decir, 2 subrayados en cada lado), que contiene el objeto prototipo del constructor del objeto. Por ejemplo, pruebe person1.__proto__ y person1.__proto__.__proto__ para ver cómo se ve la cadena en código!</p> + +<p>Desde ECMAScript 2015 se puede acceder indirectamente al objeto prototipo de un objeto mediante Object.getPrototypeOf(obj).</p> +</div> + +<h2 id="La_propiedad_prototype_Donde_se_definen_los_miembros_hereditarios">La propiedad prototype: Donde se definen los miembros hereditarios</h2> + +<p>Entonces, ¿dónde se definen las propiedades y métodos heredados? Si miras la página de referencia de <code>Object</code>, verás en la parte izquierda un gran número de propiedades y métodos - muchos más que el número de miembros heredados que vimos disponibles en el objeto <code>person1</code>. Algunos son heredados y otros no, ¿por qué?</p> + +<p>La respuesta es que los heredados son los que están definidos en la propiedad <code>prototype</code> (podría llamarse subespacio de nombres), es decir, los que empiezan con <code>Object.prototype</code>, y no los que empiezan sólo con <code>Object</code>. El valor de la propiedad del prototipo es un objeto, que es básicamente un repositorio(bucket) para almacenar propiedades y métodos que queremos que sean heredados por los objetos más abajo en la cadena del prototipo.</p> + +<p>Así que <code>Object.prototype.watch()</code>, <code>Object.prototype.valueOf()</code>, etc., están disponibles para cualquier tipo de objeto que herede de <code>Object.prototype</code>, incluyendo nuevas instancias de objeto creadas desde el constructor.</p> + +<p><code><a href="https://wiki.developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/is">Object.is()</a></code>, <code><a href="https://wiki.developer.mozilla.org/es/docs/Web/JavaScript/Referencia/Objetos_globales/Object/keys">Object.keys()</a></code>, y otros miembros no definidos dentro del prototipo del repositorio(bucket) no son heredados por instancias de objeto o tipos de objeto que heredan de Object.prototype. Sino que son métodos/propiedades disponibles sólo en el propio constructor Object().</p> + +<div class="note"> +<p><strong>Nota</strong>: Esto parece extraño - ¿cómo se puede tener un método definido en un constructor, que en sí mismo es una función? Bueno, una función es también un tipo de objeto - vea la referencia del constructor de Function() si no nos cree.</p> +</div> + +<ol> + <li>Puede comprobar las propiedades de los prototipos existentes - vuelva a nuestro ejemplo anterior e intente introducir lo siguiente en la consola JavaScript: + <pre class="brush: js notranslate">Person.prototype</pre> + </li> + <li>El resultado no le mostrará mucho - después de todo, no hemos definido nada en el prototipo de nuestro constructor personalizado! Por defecto, el prototipo de un constructor siempre comienza vacío. Ahora intente lo siguiente: + <pre class="brush: js notranslate">Object.prototype</pre> + </li> +</ol> + +<p>Verá un gran número de métodos definidos en la propiedad Prototype de Object, que están disponibles en los objetos que heredan de Object, como se ha mostrado anteriormente.</p> + +<p>Verá otros ejemplos de herencia de cadena de prototipos en todo JavaScript - intente buscar los métodos y propiedades definidas en el prototipo de los objetos globales String, Date, Number y Array, por ejemplo. Todos ellos tienen un número de miembros definidos en su prototipo, por lo que, por ejemplo, cuando se crea una cadena, como ésta:</p> + +<pre class="brush: js notranslate">var myString = 'Esto es mi String.';</pre> + +<p><code>myString</code> inmediatamente tiene una serie de métodos útiles disponibles en él, como <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/split">split()</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/indexOf">indexOf()</a></code>, <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace">replace()</a></code>, etc.</p> + +<div class="warning"> +<p><strong>Importante</strong>: La propiedad <code>prototype </code>es una de las partes más confusamente nombradas de JavaScript - podría pensarse que <code>this </code>apunta al objeto prototipo del objeto actual, pero no lo hace (es un objeto interno al que puede accederse mediante <code>__proto__</code>, ¿recuerda?). en su lugar, <code>prototype </code>es una propiedad que contiene un objeto en el que se definen los miembros que se desea que se hereden.</p> +</div> + +<h2 id="Revisando_create">Revisando create()</h2> + +<p>Anteriormente mostramos cómo <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create">Object.create()</a></code> crea una nueva instancia de objeto.</p> + +<ol> + <li>Por ejemplo, pruebe esto en la consola JavaScript de su ejemplo anterior: + <pre class="brush: js notranslate">var person2 = Object.create(person1);</pre> + </li> + <li>Lo que hace create() es crear un nuevo objeto a partir de un objeto prototipo específico. Aquí, la person2 se crea utilizando la person1 como objeto prototipo. Puede comprobarlo introduciendo lo siguiente en la consola: + <pre class="brush: js notranslate">person2.__proto__</pre> + </li> +</ol> + +<p>Esto devolverá el objeto Persona.</p> + +<h2 id="La_propiedad_constructor">La propiedad constructor</h2> + +<p>Cada función de constructor tiene una propiedad <code>prototype</code> cuyo valor es un objeto que contiene una propiedad <code>constructor</code>. Esta propiedad <code>constructor </code>apunta a la función constructor original.</p> + +<p>Como verá en la siguiente sección, las propiedades definidas en la propiedad Person.prototype (o en general en la propiedad <code>prototype</code> de una función de constructor, que es un objeto, como se mencionó en la sección anterior) se hacen disponibles a todas las instancias de objetos creadas utilizando el constructor <code>Person()</code>. Por lo tanto, la propiedad del constructor también está disponible tanto para los objetos <code>person1 </code>como para los objetos <code>person2</code>.</p> + +<ol> + <li>Por ejemplo, pruebe estos comandos en la consola: + <pre class="brush: js notranslate">person1.constructor +person2.constructor</pre> + + <p>Ambos deberían devolver el constructor <code>Person()</code>, ya que contienen la definición original de esas instancias.</p> + + <p>Un truco interesante es que se puede añadir paréntesis al final de la propiedad <code>constructor</code> (añadiendo todos los parámetros requeridos) para crear otra instancia desde ese constructor. Después de todo, el constructor es una función, por lo que puede ser invocada usando paréntesis; solamente se necesita incluir la palabra clave <code>new</code> para especificar que se quiere usar la función como un constructor.</p> + </li> + <li>Inténtese esto en la consola: + <pre class="brush: js notranslate">let person3 = new person1.constructor('Karen', 'Stephenson', 26, 'female', ['playing drums', 'mountain climbing']);</pre> + </li> + <li>Ahora intente acceder a las características del nuevo objeto, como: + <pre class="brush: js notranslate">person3.name.first +person3.age +person3.bio()</pre> + </li> +</ol> + +<p>Esto funciona. No se necesita usarlo con frecuencia, pero puede ser realmente útil cuando se quiera crear una instancia nueva y por alguna razón no se tenga disponible fácilmente una referencia al constructor original.</p> + +<p>La propiedad <code><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/constructor">constructor</a></code> tiene otros usos. Por ejemplo, si se tiene una instancia y se quiere devolver el nombre del que el constructor es una instancia, se puede usar lo siguiente:</p> + +<pre class="brush: js notranslate">instanceName.constructor.name</pre> + +<p>Intente esto, por ejemplo:</p> + +<pre class="brush: js notranslate">person1.constructor.name +</pre> + +<div class="note"> +<p><strong>Nota</strong>: El valor de <code>constructor.name</code> puede cambiar (debido a herencia de prototipos, binding, preprocesores, transpiladores, etc.), por lo que para ejemplos más complejos es preferible usar el operador <code><a href="/en-US/docs/Web/JavaScript/Reference/Operators/instanceof">instanceof</a></code> en su lugar. </p> +</div> + +<ol> +</ol> + +<h2 id="Modificando_prototipos">Modificando prototipos</h2> + +<p>Vamos a echar un vistzo a un ejemplo para modificar la propiedad <code>prototype</code> de una función constructor (los métodos añadidos a la propiedad prototipo están disponibles en todas las instancias de los objetos creados a partir del constructor).</p> + +<ol> + <li>Regresemos a nuestro ejemplo <a href="http://mdn.github.io/learning-area/javascript/oojs/introduction/oojs-class-further-exercises.html">oojs-class-further-exercises.html</a> y creemos una copia local del <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/introduction/oojs-class-further-exercises.html">código fuente</a>. Debajo del código JavaScript existente, agrega el siguiente código, el cuál añade un nuevo método a la propiedad <code>prototype</code> del constructor: + + <pre class="brush: js notranslate">Person.prototype.farewell = function() { + alert(this.name.first + ' has left the building. Bye for now!'); +};</pre> + </li> + <li>Guarda el código y abre la página en el navegador, e ingresa lo siguiente en la entrada de texto. + <pre class="brush: js notranslate">person1.farewell();</pre> + </li> +</ol> + +<p>Deberías obtener un mensaje de alerta mostrando el nombre de la persona como se define dentro del constructor. Esto es realmente útil, pero lo que es más útil es que toda la cadena de herencia se ha actualizado dinámicamente; automáticamente hace que este nuevo método esté disponible en todas las instancias del objeto creadas desde el constructor</p> + +<p>Piensa sobre esto por un momento. En nuestro código definimos el constructor, luego creamos una insancia del objeto desde el constructor, después agregamos un nuevo método a el prototipo del constructor.</p> + +<pre class="brush: js notranslate">function Person(first, last, age, gender, interests) { + + // property and method definitions + +} + +var person1 = new Person('Tammi', 'Smith', 32, 'neutral', ['music', 'skiing', 'kickboxing']); + +Person.prototype.farewell = function() { + alert(this.name.first + ' has left the building. Bye for now!'); +};.</pre> + +<p>Pero el método <code>farewell()</code> aún se encuentra disponible en la instancia <code>person1</code>, su funcionalidad disponible ha sido automáticamente actualizada incluído en método recién definido <code>farewell()</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Si estás teniendo problemas haciendo funcionar este ejemplo, echa un vistazo en nuestro ejemplo <a href="https://github.com/mdn/learning-area/blob/master/javascript/oojs/advanced/oojs-class-prototype.html">oojs-class-prototype.html</a> (<a href="http://mdn.github.io/learning-area/javascript/oojs/advanced/oojs-class-prototype.html">míralo ejecutarse en tiempo real</a>).</p> +</div> + +<p>Raramente verás propiedades definidas en la propiedad <code>prototype</code>, ya no son muy flexibles cuando son definidas de esta forma. Por ejemplo, puedes añadir una propiedad como esta:</p> + +<pre class="brush: js notranslate">Person.prototype.fullName = 'Bob Smith'; +</pre> + +<p>Esto no es muy flexible, ya que la persona podría no llamarse así. Sería mucho mejor construir <code>fullname</code> desde <code>name.first</code> y <code>name.last</code>.</p> + +<pre class="brush: js notranslate">Person.prototype.fullName = this.name.first + ' ' + this.name.last; +</pre> + +<p>Sin embargo esto no funciona, ya que <code>this</code> estará referenciando al scope global en este caso, no al scope de la función. Llamar esta propiedad retornaría <code>undefined undefined</code>. Esto funcionó bien en el método que declaramos anteriormente dentro del prototipo, porque se encuentra dentro del scope de la función, que se transferirá con éxito al scope de la instancia del objeto.Así que deberías definir propiedades constantes en el prototipo (p.e. una que nunca necesite cambiar), pero generalmente funciona mejor definir propiedades dentro del constructor.</p> + +<p>De hecho, un patrón bastante común para la mayoría de definiciones de objetos es declarar las propiedades dentro del constructor, y los métodos en el prototipo. Esto hace el código más fácil de leer, ya que el constructor sólo contiene las definiciones de propiedades, y los métodos están en bloques separados. Por ejemplo:</p> + +<pre class="brush: js notranslate">// Constructor with property definitions + +function Test(a, b, c, d) { + // property definitions +} + +// First method definition + +Test.prototype.x = function() { ... }; + +// Second method definition + +Test.prototype.y = function() { ... }; + +// etc. +</pre> + +<p>Este patrón puede verse en acción en el ejemplo de la <a href="https://github.com/zalun/school-plan-app/blob/master/stage9/js/index.js">aplicación de planificador escolar</a> de Piotr Zalewa.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Este articulo ha cubierto prototipos de objeto JavaScript, incluyendo como las cadenas de objeto prototipo permiten a los objetos heredar caracteristicas de una a otra, la propiedad prototipo y como puede ser usado para agregar metodos a los constructores, y otros temas relacionados.</p> + +<p>En el proximos articulo vamos a ver como puedes implementar la herencia de funcionalidades entre dos de tus propios objetos personalizados.</p> + +<p>{{PreviousMenuNext("Learn/JavaScript/Objects/Object-oriented_JS", "Learn/JavaScript/Objects/Inheritance", "Learn/JavaScript/Objects")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Basics">Object basics</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object-oriented_JS">Object-oriented JavaScript for beginners</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_prototypes">Object prototypes</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Inheritance">Inheritance in JavaScript</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/JSON">Working with JSON data</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Object_building_practice">Object building practice</a></li> + <li><a href="/en-US/docs/Learn/JavaScript/Objects/Adding_bouncing_balls_features">Adding features to our bouncing balls demo</a></li> +</ul> diff --git a/files/es/learn/performance/index.html b/files/es/learn/performance/index.html new file mode 100644 index 0000000000..ebe81969aa --- /dev/null +++ b/files/es/learn/performance/index.html @@ -0,0 +1,113 @@ +--- +title: Rendimiento web +slug: Learn/Performance +translation_of: Learn/Performance +--- +<p>{{LearnSidebar}}{{draft}}</p> + +<p class="summary">La construcción de sitios web requiere HTML, CSS y JavaScript. Para crear sitios web y aplicaciones que la gente quiera usar, que atraigan y retengan a los usuarios, debe crear una buena experiencia de usuario. Parte de la buena experiencia del usuario es garantizar que el contenido se cargue rápidamente y responda a la interacción del usuario. Esto se conoce como rendimiento web, y en este módulo aprenderá todo lo que necesita para crear sitios web de rendimiento.</p> + +<p> </p> + +<p>El rendimiento web es la medición objetiva y la experiencia percibida por el usuario del tiempo de carga y el tiempo de ejecución. El rendimiento web es el tiempo que tarda un sitio en cargarse, en ser interactivo y receptivo, y en el grado de fluidez del contenido durante las interacciones del usuario. ¿Es el desplazamiento suave? ¿Se puede hacer clic en los botones? ¿Las ventanas emergentes se abren rápidamente y se animan sin problemas al hacerlo? El rendimiento web incluye mediciones objetivas como el tiempo de carga, cuadros por segundo y tiempo para experiencias interactivas y subjetivas de cuánto tiempo tardó en cargarse el contenido.</p> + +<p>Muchas características afectan el rendimiento, incluida la latencia, el tamaño de la aplicación, la cantidad de nodos DOM, la cantidad de solicitudes de recursos realizadas, el rendimiento de JavaScript, la carga de la CPU y más. Es importante minimizar los tiempos de carga y respuesta, y agregar funciones adicionales para ocultar la latencia al hacer que la experiencia sea lo más accesible e interactiva posible, tan pronto como sea posible, mientras se carga de forma asíncrona en las partes más largas de la experiencia.</p> + +<p>Existen herramientas, API y mejores prácticas que nos ayudan a medir y mejorar el rendimiento web. Los veremos también en el curso de este módulo.</p> + +<p> </p> + +<h2 id="Camino_de_aprendizaje">Camino de aprendizaje</h2> + +<p> </p> + +<p>Si bien es necesario conocer HTML, CSS y JavaScript para implementar muchas recomendaciones de mejora del rendimiento web, saber cómo crear aplicaciones no es una condición previa necesaria para comprender y medir el rendimiento web.</p> + +<p>Varios de los módulos introductorios a continuación no requieren conocimientos de programación, aunque se necesita una comprensión de HTML para el módulo de rendimiento y HTML, se necesita una comprensión de CSS para el módulo de rendimiento y CSS, etc. Recomendamos que trabaje con nuestros módulos introductorios. primero, comenzando con <a href="/en-US/docs/Learn/Performance/What_is_Performance">qué es el rendimiento web </a>primero. Los módulos introductorios proporcionan una visión general del rendimiento web. Los tres primeros deben considerarse como lectura obligatoria si usted es un desarrollador o gerente de proyectos. Los módulos enfocados en temas de tecnología son más apropiados para los desarrolladores que utilizan estas tecnologías.</p> + +<p> </p> + +<p>Los módulos avanzados profundizan en los temas que se resumen en los módulos introductorios y proporcionan una visión general de las API de rendimiento, las herramientas de análisis y prueba y los problemas de cuellos de botella en el rendimiento.</p> + +<p>Se recomienda que trabajes a través de <a href="/en-US/docs/Learn/Getting_started_with_the_web">Empezando con la web </a>antes de proceder con este tema. Sin embargo, hacerlo no es absolutamente necesario.</p> + +<h2 id="Modulos_de_introducción">Modulos de introducción</h2> + +<p>Este tema contiene los siguientes módulos, en un orden sugerido para trabajar a través de ellos. Definitivamente debes comenzar con el primero.</p> + +<dl> + <dt><a href="/en-US/docs/Learn/Performance/What_is_performance">¿Qué es el rendimiento web?</a></dt> + <dd>Este artículo inicia el módulo con una buena visión de lo que realmente es el rendimiento: esto incluye las herramientas, métricas, API, redes y grupos de personas que debemos considerar al pensar en el rendimiento y cómo podemos hacer que el rendimiento sea parte de nuestra web. flujo de trabajo de desarrollo.</dd> + <dt><a href="/en-US/docs/Learn/Performance/Perceived_performance">¿Cómo perciben los usuarios el rendimiento?</a></dt> + <dd> + <p>Más importante que la rapidez de su sitio web en milisegundos, es la rapidez con la que los usuarios perciben su sitio. Estas percepciones se ven afectadas por el tiempo real de carga de la página, el ralentí, la capacidad de respuesta a la interacción del usuario y la suavidad del desplazamiento y otras animaciones. En este artículo, analizamos las diversas métricas de carga, animación y métricas de capacidad de respuesta, junto con las mejores prácticas para mejorar la percepción del usuario, si no los tiempos reales.</p> + </dd> + <dt><a href="/en-US/docs/Learn/Performance/Basics">Rendimiento web básico</a></dt> + <dd>Además de los componentes frontales de HTML, CSS, JavaScript y archivos multimedia, hay características que pueden hacer que las aplicaciones sean más lentas y características que pueden hacer que las aplicaciones sean subjetivamente y objetivamente más rápidas. Existen muchas API, herramientas de desarrollo, mejores prácticas y malas prácticas relacionadas con el rendimiento web. Aquí presentaremos muchas de estas funciones al nivel básico y proporcionaremos enlaces a inmersiones más profundas para mejorar el rendimiento de cada tema.</dd> + <dt><a href="/en-US/docs/Learn/Performance/HTML">Herramientas de rendimiento HTML </a></dt> + <dd>Algunos atributos y el orden de origen de su marcado pueden afectar el rendimiento o su sitio web. Al minimizar el número de nodos DOM, asegurándose de que se utilicen el mejor orden y los atributos para incluir contenido como estilos, scripts, medios y scripts de terceros, puede mejorar drásticamente la experiencia del usuario. Este artículo analiza en detalle cómo se puede usar HTML para garantizar el máximo rendimiento.</dd> + <dt><a href="/en-US/docs/Learn/Performance/Multimedia">Multimedia: imágenes y vídeo</a></dt> + <dd>El fruto más bajo del rendimiento web es a menudo la optimización de medios. Es posible servir diferentes archivos multimedia según la capacidad, el tamaño y la densidad de píxeles de cada agente de usuario. Sugerencias adicionales como eliminar pistas de audio de videos de fondo pueden mejorar aún más el rendimiento. En este artículo, analizamos el impacto que el video, el audio y el contenido de la imagen tienen en el rendimiento y los métodos para garantizar que el impacto sea lo más mínimo posible.</dd> + <dt>Imágenes responsivas</dt> + <dd>Si bien la optimización de imágenes es vital para las experiencias de usuario ricas en medios de alto rendimiento, es especialmente importante garantizar que las imágenes tengan el tamaño adecuado para los dispositivos que las descargan. En este artículo, analizaremos la función de las características del navegador nativo, como el elemento <picture> y el atributo srcset en la entrega eficiente de imágenes, y cómo puede usarlas con confianza.</dd> + <dt>Formatos de medios alternativos</dt> + <dd>Cuando se trata de imágenes y videos, hay más formatos de los que probablemente conozca. Algunos de estos formatos pueden llevar sus páginas multimedia altamente optimizadas aún más lejos al ofrecer reducciones adicionales en el tamaño del archivo. En esta guía, analizaremos algunos formatos de medios alternativos, cómo usarlos de manera responsable para que los navegadores no compatibles no se queden al margen, y algunos consejos avanzados sobre la transcodificación de sus activos existentes.</dd> + <dt><a href="/en-US/docs/Learn/Performance/CSS">Características de rendimiento en CSS</a></dt> + <dd>CSS puede ser un enfoque de optimización menos importante para mejorar el rendimiento, pero hay algunas características de CSS que afectan el rendimiento más que otras. En este artículo analizamos algunas propiedades CSS que afectan el rendimiento y sugerimos formas de manejar los estilos para garantizar que el rendimiento no se vea afectado negativamente.</dd> + <dt><a href="/en-US/docs/Learn/Performance/JavaScript">Mejores prácticas de rendimiento en JavaScript </a></dt> + <dd>JavaScript, cuando se usa correctamente, puede permitir experiencias web interactivas e inmersivas, o puede dañar significativamente el tiempo de descarga, el tiempo de procesamiento, el rendimiento dentro de la aplicación, la duración de la batería y la experiencia del usuario. Este artículo describe algunas de las mejores prácticas de JavaScript que deben tenerse en cuenta para garantizar que incluso el contenido complejo tenga el mayor rendimiento posible.</dd> + <dt>Rendimiento de fuentes web</dt> + <dd>Un aspecto que a menudo se pasa por alto en el panorama del rendimiento son las fuentes web. Las fuentes web son más prominentes que nunca en el diseño web, sin embargo, muchos desarrolladores simplemente las incorporan desde un servicio de terceros y no piensan en ello. En este artículo, cubriremos métodos para obtener sus archivos de fuentes lo más pequeños posible con una configuración y sub configuración de archivos eficientes. A partir de ahí, continuaremos hablando sobre cómo los navegadores envían mensajes de texto y cómo puede usar las funciones de CSS y JavaScript para garantizar que sus fuentes se representen rápidamente y con una interrupción mínima de la experiencia del usuario.</dd> +</dl> + +<dl> + <dt><a href="/en-US/docs/Learn/Performance/Mobile">Rendimiento móvil</a></dt> + <dd>Dado que el acceso a la web en dispositivos móviles es tan popular, y que todas las plataformas móviles tienen navegadores web completos, pero es posible que el ancho de banda, la CPU y la vida útil de la batería sean limitados, es importante considerar el rendimiento de su contenido web en estas plataformas. Este artículo analiza las consideraciones de rendimiento específicas para dispositivos móviles.</dd> +</dl> + +<h2 id="Módulos_avanzados">Módulos avanzados</h2> + +<dl> + <dt>Poblando la pagina</dt> + <dd>Se realiza una solicitud HTTP y, con suerte, unos segundos más tarde, aparece el sitio. Mostrar el contenido implica ejecutar JavaScript, posiblemente modificar el DOM, calcular estilos, calcular el diseño y, finalmente, representar el contenido, lo que implica pintar y componer, y puede involucrar la aceleración de la GPU en un hilo separado.</dd> + <dt><a href="/en-US/docs/Learn/Performance/Latency">Entendiendo la latencia</a></dt> + <dd> + <p>La latencia es la cantidad de tiempo que tarda entre el navegador que realiza una solicitud de un recurso y el que recibe el primer byte del recurso solicitado. Este artículo explica qué es la latencia, cómo afecta el rendimiento y cómo medir y mejorar la latencia.</p> + </dd> + <dt>Entendiendo el ancho de banda</dt> + <dd> + <p>Bandwidth is the amount of data (measured in Mbps or Kbps) that can be sent per second. This article explains the role of bandwidth in media-rich internet applications, how it can be measured, and how you can optimize applications to make the best use of available bandwidth.</p> + </dd> + <dt>HTTP/2 y tú</dt> + <dd> + <p>La capa de transporte, es decir, HTTP, es absolutamente esencial para el funcionamiento de la web, y solo recientemente se ha visto una actualización importante en la forma de HTTP / 2. Fuera de la caja, HTTP / 2 proporciona muchas mejoras de rendimiento y ventajas sobre su predecesor, pero también cambia el panorama. En este artículo, aprenderá lo que HTTP / 2 hace por usted, y cómo ajustar su aplicación para que vaya más allá.</p> + </dd> + <dt>El rol de TLS en el rendimiento</dt> + <dd> + <p>TLS, o HTTPS, como solemos llamar, es crucial para crear experiencias de usuario seguras. Si bien el hardware ha reducido los impactos negativos que TLS ha tenido en el rendimiento del servidor, aún representa una porción sustancial del tiempo que pasamos esperando que los navegadores se conecten a los servidores. Este artículo explica el proceso de intercambio de TLS y ofrece algunos consejos para reducir este tiempo, como el grapado OCSP, los encabezados de precarga de HSTS y el posible papel de las sugerencias de recursos en el enmascaramiento de la latencia TLS para terceros.</p> + </dd> + <dt><a href="/en-US/docs/Performance/Profiling_with_the_Built-in_Profiler">Perfilando con el perfilador incorporado</a></dt> + <dd>Aprenda cómo perfilar el rendimiento de la aplicación con el generador de perfiles integrado de Firefox.</dd> + <dt>Gráficos de rendimiento de lectura</dt> + <dd>Las herramientas del desarrollador proporcionan información sobre el rendimiento, la memoria y las solicitudes de red. Saber leer <a href="https://developer.mozilla.org/en-US/docs/Tools/Performance/Waterfall">tablas de cascada</a>, <a href="https://developer.mozilla.org/en-US/docs/Tools/Performance/Call_Tree">árboles de llamadas, </a>Las herramientas del desarrollador proporcionan información sobre el rendimiento, la memoria y las solicitudes de red. Saber leer, <a href="https://developer.mozilla.org/en-US/docs/Tools/Performance/Flame_Chart">tablas de llamas</a>, y <a href="https://developer.mozilla.org/en-US/docs/Tools/Performance/Allocations">localizaciones</a> en su navegador, las herramientas de desarrollo lo ayudarán a comprender los gráficos de cascada y llama en otras herramientas de rendimiento.</dd> + <dt><a href="/en-US/Apps/Build/Performance/CSS_JavaScript_animation_performance">Rendimiento de animaciones en CSS y JavaScript </a></dt> + <dd>Las animaciones son críticas para una experiencia de usuario placentera. Este artículo analiza las diferencias de rendimiento entre CSS y animaciones basadas en JavaScript.</dd> + <dt>Analizando paquetes de JavaScript</dt> + <dd>Sin duda, JavaScript es una gran parte del desarrollo web moderno. Si bien siempre debe esforzarse por reducir la cantidad de JavaScript que utiliza en sus aplicaciones, puede ser difícil saber dónde comenzar. En esta guía, le mostraremos cómo analizar los paquetes de scripts de su aplicación, para que sepa qué está utilizando y cómo detectar si hay scripts duplicados entre paquetes en su aplicación.</dd> + <dt>Lazy-loading JavaScript con importaciones dinámicas</dt> + <dd>Cuando los desarrolladores escuchan el término "carga perezosa", inmediatamente piensan en imágenes que se cargan por la mitad inferior de la página cuando se desplaza hacia la ventana gráfica. ¿Pero sabías que también puedes cargar JavaScript de forma perezosa? En esta guía hablaremos sobre la declaración dinámica de importación (), que es una característica de los navegadores modernos que carga un módulo de JavaScript a pedido. Por supuesto, ya que esta función no está disponible en todas partes, también le mostraremos cómo puede configurar sus herramientas para usar esta función de una manera ampliamente compatible.</dd> +</dl> + +<dl> + <dt>Controlar la entrega de recursos con sugerencias de recursos</dt> + <dd>Los navegadores a menudo saben mejor que nosotros cuando se trata de la priorización y la entrega de recursos, pero están lejos de ser clarividentes. Las características nativas del navegador nos permiten sugerirle al navegador cuándo debe conectarse a otro servidor, o precargar un recurso antes de que el navegador sepa que lo necesita. Cuando se usa juiciosamente, esto puede hacer que la experiencia rápida parezca aún más rápida. En este artículo, cubrimos las características nativas del navegador como rel = preconnect, rel = dns-prefetch, rel = prefetch, y rel = precarga, y cómo usarlas para su ventaja.</dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="/en-US/docs/Web/Performance/Mobile_performance_checklist">Mobile performance checklist</a></li> + <li><a href="/en-US/docs/Web/Apps/Fundamentals/Performance/Optimizing_startup_performance">Optimizing Startup Performance</a><a href="/en-US/docs/Web/Apps/Fundamentals/Performance/Optimizing_startup_performance"> </a></li> +</ul> + +<p>{{LandingPageListSubpages}}</p> diff --git a/files/es/learn/server-side/django/admin_site/index.html b/files/es/learn/server-side/django/admin_site/index.html new file mode 100644 index 0000000000..486d277003 --- /dev/null +++ b/files/es/learn/server-side/django/admin_site/index.html @@ -0,0 +1,372 @@ +--- +title: 'Tutorial Django Parte 4: Sitio de Administración de Django' +slug: Learn/Server-side/Django/Admin_site +tags: + - Aplicación web + - Artículo + - Codificación + - Django Admin + - Principiante + - Python + - Tutorial + - django + - django_admin + - programacion +translation_of: Learn/Server-side/Django/Admin_site +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Models", "Learn/Server-side/Django/Home_page", "Learn/Server-side/Django")}}</div> + +<p class="summary">Ahora que hemos creado modelos para el sitio web de la <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">BibliotecaLocal</a>, usaremos el sitio de administración de Django para añadir algunos datos de libros "reales". Primero mostraremos cómo registrar los modelos en el sitio de administración y luego te mostraremos cómo iniciar sesión y crear algunos datos. Al final del artículo mostraremos algunas formas en las que puedes mejorar más adelante la presentación del sitio de Administración.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td>Primero completa: <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Models">Tutorial Django Parte 3: Uso de modelos</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Entender los beneficios y las limitaciones del sitio de administración de Django, y usarlo para crear algunos registros para nuestros modelos.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Introducción">Introducción</h2> + +<p>La <em>aplicación</em> de administración de Django puede usar tus modelos para construir automáticamente un área dentro del sitio que puedes usar para crear, consultar, actualizar y borrar registros. Esto puede ahorrarte mucho tiempo de desarrollo, haciendo muy fácil probar tus modelos y darte una idea de si tus datos son correctos. La aplicación de administración también puede ser útil para manejar datos en producción, dependiendo del estilo del sitio web. Desde el proyecto Django solo se recomienda para gestión de datos internos (por ejemplo, solo para uso de administradores o personas internas de tu organización), ya que como enfoque centrado en el modelo no es necesariamente la mejor interfaz posible para todos los usuarios, exponiendo una gran cantidad de detalles innecesarios de los modelos.</p> + +<p>Toda la configuración requerida para incluir la aplicación admin en tu sitio Web fue hecha automaticamente cuando <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">creaste el esqueleto del proyecto</a> (para información sobre dependencias reales necesarias, vea los <a href="https://docs.djangoproject.com/en/1.10/ref/contrib/admin/">documentos de Django aquí</a>). Como resultado, todo lo que <strong>debes</strong> hacer para agregar tus modelos a la aplicación admin es <em>registrarlos.</em> Al final de este artículo entregaremos una breve demostración sobre como puedes configurar aún más el área de administración para mejorar la visualización de nuestros modelos de datos.</p> + +<p>Después de registrar los modelos te mostraremos como crear un nuevo "administrador", iniciar sesión en el sitio, y crear algunos libros, autores, instancias de libros, y géneros. Esto será útil para probar las vistas y plantillas que empezaremos a crear en el siguiente tutorial.</p> + +<h2 id="Registrando_los_modelos">Registrando los modelos </h2> + +<p>Primero, abre <strong>admin.py</strong> en la aplicación catálogo (<strong>/locallibrary/catalog/admin.py</strong>). Actualmente se ve como esto — notar que ya importa <code>django.contrib.admin</code>:</p> + +<pre class="brush: python">from django.contrib import admin + +# Register your models here. +</pre> + +<p>Registra los modelos copiando el texto siguiente al final del archivo. Este simple código esta importando los modelos y después llama a <code>admin.site.register</code> para registrar a cada uno de ellos.</p> + +<pre class="brush: python">from .models import Author, Genre, Book, BookInstance + +admin.site.register(Book) +admin.site.register(Author) +admin.site.register(Genre) +admin.site.register(BookInstance) +</pre> + +<div class="note"><strong>Nota</strong>: Si tu aceptaste el desafío de crear un modelo que represente el Lenguaje natural de un libro (<a href="/en-US/docs/Learn/Server-side/Django/Models">ver el artículo tutorial de modelos</a>), importalo y registralo también!</div> + +<p>Esta es la forma más simple de registrar un modelo, o modelos, con el sitio. El sitio de administración es altamente personalizable, y hablaremos más sobre otras formas de registrar tus modelos más abajo.</p> + +<h2 id="Creando_un_administrador">Creando un administrador</h2> + +<p>Para iniciar sesión en el sitio de administración, necesitamos una cuenta de usuario con estado de <em>Personal</em> habilitado. Para ver y crear registros tambien necesitamos que este usuario tenga permisos para administrar todos nuestros objetos. Puedes crear una cuenta "administrador" que tenga acceso total al sitio y a todos los permisios necesarios usando <strong>manage.py</strong>.</p> + +<p>Usa el siguiente comando, en el mismo directorio de <strong>manage.py</strong>, para crear al administrador. Deberás ingresar un nombre de usuario, dirección email, y una contraseña <em>fuerte</em>.</p> + +<pre class="brush: bash">python3 manage.py createsuperuser +</pre> + +<p>Una vez el comando termine un nuevo administrador será agregado a la base de datos. Ahora reinicia el servidor de desarrollo para que podamos probrar el inicio de sesión:</p> + +<pre class="brush: bash">python3 manage.py runserver + +</pre> + +<h2 id="Iniciar_sesión_y_usar_el_sitio">Iniciar sesión y usar el sitio</h2> + +<p>Para iniciar sesión en el sitio, ve a la URL <em>/admin</em> (e.j. <a href="http://127.0.0.1:8000/admin/">http://127.0.0.1:8000/admin</a>) e ingresa tus credenciales de id usuario y contraseña de administrador (serás redirigido a la página <em>login</em>, y entonces volverás a la URL de <em>/admin</em> después de haber ingresado tus datos).</p> + +<p>Esta parte del sitio muestra todos tus modelos, agrupados por aplicación instalada. Puedes hacer click en un nombre de modelo para ir a una pantalla que lista todos los registros asociados, y además puedes hacer click sobre esos registros para editarlos. También puedes hacer click directamente sobre el vínculo <strong>Añadir</strong> a continuación de cada modelo para comenzar a crear un registro de ese tipo.</p> + +<p><img alt="Admin Site - Home page" src="https://mdn.mozillademos.org/files/13975/admin_home.png" style="display: block; height: 634px; margin: 0px auto; width: 998px;"></p> + +<p>Haz click sobre el vínculo <strong>Añadir</strong> a la derecha de <em>Books</em> para crear un nuevo libro, esto mostrará un diálogo parecido al de abajo). Nota como los títulos de cada campo, el tipo de widget usado, y el <code>help_text</code> (si existe) corresponde con el valor que especificaste en el modelo. </p> + +<p>Ingresa valores para los campos. Puede crear nuevos autores o géneros presionandoel botón <strong>+</strong> a continuación del campo respectivo ( o seleccionar un valor existente de las listas si ya las tenías creadas). Cuando termines puedes presionar <strong>Grabar</strong>, <strong>Grabar y añadir otro</strong>, o <strong>Grabar y continuar editando</strong> para guardar el registro.</p> + +<p><img alt="Admin Site - Book Add" src="https://mdn.mozillademos.org/files/13979/admin_book_add.png" style="border-style: solid; border-width: 1px; display: block; height: 780px; margin: 0px auto; width: 841px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: En este punto nos gustaría que pasaras algún tiempo añadiendo unos pocos libros, autores, y géneros (ej. Fantasía) a tu aplicación. Asegúrate de que cada autor y género incluye un par de libros diferentes (esto hará tus vistas de lista y detalle más interesantes cuando las implementemos más tarde en la serie de artículos).</p> +</div> + +<p>Cuando hayas terminado de añadir libros, haz click en el enlace <strong>Home </strong>en el separador de arriba para regresar a la página principal de administración. Luego haz click en el enlace <strong>Books </strong>para desplegar la lista actual de libros (o en alguno de los otros enlaces para ver las listas de otros modelos). Ahora que haz añadido unos cuantos libros, la lista debería lucir similar a la captura de pantalla de abajo. Se muestra el título de cada libro; que es el valor devuelto por el método <code>__str__()</code> del modelo Book que especificamos en el artículo anterior.</p> + +<p><img alt="Admin Site - List of book objects" src="https://mdn.mozillademos.org/files/13935/admin_book_list.png" style="border-style: solid; border-width: 1px; display: block; height: 407px; margin: 0px auto; width: 1000px;"></p> + +<p>Desde esta lista puedes eliminar libros marcando la casilla de verificación junto al libro que no deseas y seleccionando la acción <em>delete... </em>en la lista de selección <em>Action</em>, y luego presionando el botón <strong>Go</strong>. Puedes también añadir nuevos libros presionando el botón <strong>ADD BOOK</strong>.</p> + +<p>Puedes editar un libro haciendo click en su nombre en la lista. La página de edición para un libro, como se muestra abajo, es casi idéntica a la página "Add". Las principales diferencias son el título de la página (<em>Change book</em>) y la adición de los botones <strong>Delete</strong>, <strong>HISTORY </strong>y <strong>VIEW ON SITE </strong>(este último aparece porque definimos el método <code>get_absolute_url()</code> en nuestro modelo).</p> + +<p><img alt="Admin Site - Book Edit" src="https://mdn.mozillademos.org/files/13977/admin_book_modify.png" style="border-style: solid; border-width: 1px; display: block; height: 780px; margin: 0px auto; width: 841px;"></p> + +<p>Ahora regresa a la página <strong>Home </strong>(usando el enlace <em>Home </em>de la barra superior) y observa las listas <strong>Author </strong>y <strong>Genre </strong>-- ya deberías tener algunos registros creados de cuando añadiste los nuevos libros, pero puedes crear algunos más.</p> + +<p>Lo que no vas a tener es <em>BookInstances</em>, porque estas no se crean de los libros (si bien puedes crear un <code>Book</code> desde una <code>BookInstance</code> -- esta es la naturaleza de los campos <code>ForeignKey</code>). Regresa a la página <em>Home </em>y presiona el botón <strong>Add </strong>relacionado para desplegar la pantalla <em>Add book instance</em>, como se muestra abajo. Nota el largo y globalmente único Id, que puede ser usado para identificar inequívocamente una única copia de un libro dentro de la biblioteca.</p> + +<p><img alt="Admin Site - BookInstance Add" src="https://mdn.mozillademos.org/files/13981/admin_bookinstance_add.png" style="border-style: solid; border-width: 1px; display: block; height: 514px; margin: 0px auto; width: 863px;"></p> + +<p>Crea algunos de estos registros para cada uno de tus libros. Establece el status en <em>Available </em>para al menos algunos registros y en <em>On loan</em> para otros. Si el status es <strong>diferente </strong>de <em>Available</em>, especifica también una fecha de <em>Due back</em> (devolución).</p> + +<p>¡Eso es todo! Has aprendido a configurar y usar el sitio de administración. También has creado registros para <code>Book</code>, <code>BookInstance</code>, <code>Genre</code> y <code>Author</code> que podremos usar una vez que creemos nuestras propias views (vistas) y templates (plantillas).</p> + +<h2 id="Configuración_avanzada">Configuración avanzada</h2> + +<p>Django hace un gran trabajo al crear un sitio de administración básico usando la información de los modelos registrados:</p> + +<ul> + <li>Cada modelo tiene una lista de registros individuales, identificados por la cadena creada por el método <code>__str__()</code> del modelo, y enlazados a vistas/formularios de detalle para edición. Por defecto, esta vista de lista tiene un menú de acción en la parte superior que puedes usar para realizar operaciones de eliminación masiva de los registros.</li> + <li>Los formularios de detalle de registro del modelo para edición y adición de registros contienen todos los campos del modelo, organizados verticalmente en su orden de declaración. </li> +</ul> + +<p>Posteriormente puedes personalizar la interfaz para hacerla incluso más fácil de usar. Algunas de las cosas que puedes hacer son:</p> + +<ul> + <li>Vistas de lista: + <ul> + <li>Añadir campos e información adicional desplegada para cada registro. </li> + <li>Añadir filtros para seleccionar qué registros se listan, basados en fechas u otros tipos de valores (ej. estado de préstamo del libro).</li> + <li>Añadir opciones adicionales al menú <em>Action </em>en las vistas de lista y elegir en qué lugar del formulario se despliega este menú.</li> + </ul> + </li> + <li>Vistas de detalle: + <ul> + <li>Elegir qué campos desplegar (o excluir), junto con su orden, agrupamiento, si son editables, el tipo de control a usarse, orientación, etc.</li> + <li>Añadir campos relacionados a un registro para permitir la edición en cadena (ej. proveer la capacidad de añadir y editar registros de libros mientras estás creando su registro de autor).</li> + </ul> + </li> +</ul> + +<p>En esta sección observaremos unos cuantos cambios que mejorarán la interfaz de nuestra <em>LocalLibrary</em>, incluyendo la adición de más información a las listas de los modelos <code>Book</code> y <code>Author</code>, y mejorando el diseño de sus vistas de edición. No cambiaremos la presentación de los modelos <code>Language</code> y <code>Genre</code> debido a que solo tienen un campo cada uno, ¡por lo que no hay ningún beneficio real de hacerlo!</p> + +<p>Puedes encontrar una referencia completa de todas las opciones de personalización del sitio de administración en <a href="https://docs.djangoproject.com/en/1.10/ref/contrib/admin/">The Django Admin site</a> (Django Docs).</p> + +<h3 id="Registrar_una_clase_ModelAdmin">Registrar una clase ModelAdmin</h3> + +<p>Para cambiar la forma en la que un modelo se despliega en la interfaz de administración debes definir una clase <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#modeladmin-objects">ModelAdmin</a> (que describe el diseño) y registrarla con el modelo.</p> + +<p>Comencemos con el modelo Author. Abre <strong>admin.py</strong> en la aplicación catalog (<strong>/locallibrary/catalog/admin.py</strong>). Comenta tu registro original para el modelo <code>Author</code> (colocando el prefijo # en la línea):</p> + +<pre class="brush: js"># admin.site.register(Author)</pre> + +<p>Ahora añade una nueva clase <code>AuthorAdmin</code> y regístrala como se muestra abajo.</p> + +<pre class="brush: python"># Define the admin class +class AuthorAdmin(admin.ModelAdmin): + pass + +# Register the admin class with the associated model +admin.site.register(Author, AuthorAdmin) +</pre> + +<p>Ahora añadiremos clases <code>ModelAdmin </code>para <code>Book</code>, y <code>BookInstance</code>. De nuevo, debemos comentar nuestros registros originales:</p> + +<pre class="brush: python">#admin.site.register(Book) +#admin.site.register(BookInstance)</pre> + +<p>Ahora, para crear y registar los nuevos modelos usaremos, para propósitos de esta demostración, la expresión <code>@register </code>para registrar los modelos (hace exactamente lo mismo que <code>admin.site.register()</code>):</p> + +<pre class="brush: python"># Register the Admin classes for Book using the decorator + +@admin.register(Book) +class BookAdmin(admin.ModelAdmin): + pass + +# Register the Admin classes for BookInstance using the decorator + +@admin.register(BookInstance) +class BookInstanceAdmin(admin.ModelAdmin): + pass +</pre> + +<p>Al momento todas nuestras clases de administración estás vacías (observa "pass"), así que el comportamiento de administración ¡no cambiará! Ahora podemos extenderlas para definir nuestro comportamiento de administración específico para cada modelo.</p> + +<h3 id="Configurar_las_vistas_de_lista">Configurar las vistas de lista</h3> + +<p>La <em>LocalLibrary</em> actualmente lista todos los autores usando el nombre generado por el método <code>__str__()</code> del modelo. Esto funciona bien cuando solo tienes unos pocos autores, pero una vez que tienes muchos puedes terminar teniendo duplicados. Para diferenciarlos, o simplemente para mostrar información más interesante sobre cada autor, puedes usar <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.list_display">list_display</a> para añadir otros campos a la vista.</p> + +<p>Reemplaza tu clase <code>AuthorAdmin </code>con el código de abajo. Los nombres de campos a ser desplegados en la lista están declarados en una tupla en el orden requerido, como se muestra (estos son los mismos nombres especificados en tu modelo original).</p> + +<pre class="brush: python">class AuthorAdmin(admin.ModelAdmin): + list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death') +</pre> + +<p>Recarga el sitio y navega hacia la lista de autores. Ahora deberían desplegarse los campos de arriba, así:</p> + +<p><img alt="Admin Site - Improved Author List" src="https://mdn.mozillademos.org/files/14023/admin_improved_author_list.png" style="border-style: solid; border-width: 1px; display: block; height: 302px; margin: 0px auto; width: 941px;"></p> + +<p>Para nuestro modelo <code>Book</code> desplegaremos adicionalmente el <code>author</code> y <code>genre</code>. El <code>author</code> es un campo de relación tipo <code>ForeignKey</code> (uno a uno), y por tanto estará representado por el valor <code>__str__()</code> del registro asociado. Reemplaza la clase BookAdmin con la versión de abajo.</p> + +<pre>class BookAdmin(admin.ModelAdmin): + list_display = ('title', 'author', 'display_genre')</pre> + +<p>Desafortunadamente, no podemos especificar directamente el campo <code>genre</code> en <code>list_display</code> porque es un campo <code>ManyToManyField</code> (Django previene esto porque habría un alto "costo" de acceso a base de datos si lo hiciera). En lugar de eso, definiremos una función <code>display_genre</code> para obtener la información como una cadena (esta es la función que hemos llamado arriba; la definiremos más abajo).</p> + +<div class="note"> +<p><strong>Nota</strong>: Obtener el <code>genre </code>podría no ser una buena idea aquí, debido al "costo" de la operación en la base de datos. Te mostramos cómo hacerlo porque llamar funciones desde tus modelos puede ser muy útil por otras razones -- por ejemplo para añadir un enlace <em><strong>Delete</strong></em> junto a cada ítem en la lista.</p> +</div> + +<p>Añade el siguiente código en tu modelo <code>Book</code> (<strong>models.py</strong>). Esto crea una cadena con los tres primeros valores del campo <code>genre</code> (si existen) y crea una <code>short_description</code> (descripción corta) que puede ser usada en el sitio de administración por este método.</p> + +<pre class="brush: python"> def display_genre(self): + """ + Creates a string for the Genre. This is required to display genre in Admin. + """ + return ', '.join([ genre.name for genre in self.genre.all()[:3] ]) + display_genre.short_description = 'Genre' +</pre> + +<p>Después de guardar el modelo y actualizar admin, recarga el sitio y ve a la página de lista de <em>Books</em> (libros), deberías ver una lista de libros como la de abajo:</p> + +<p><img alt="Admin Site - Improved Book List" src="https://mdn.mozillademos.org/files/14025/admin_improved_book_list.png" style="border-style: solid; border-width: 1px; display: block; height: 337px; margin: 0px auto; width: 947px;"></p> + +<p>El modelo <code>Genre</code> (y el modelo <code>Language</code>, si lo definiste) tiene un solo campo, por lo que no tiene sentido crear un modelo adicional para el mismo para desplegar campos adicionales.</p> + +<div class="note"> +<p><strong>Nota</strong>: Vale la pena actualizar el modelo <code>BookInstance</code> para mostrar al menos el estado y fecha de devolución esperada. ¡Lo hemos añadido como un reto al final de este artículo!</p> +</div> + +<h3 id="Añadir_filtros_de_lista">Añadir filtros de lista</h3> + +<p>Una vez que tienes muchos ítems en una lista, puede ser útil filtrar los ítems que se despliegan. Esto se hace listando campos en el atributo <code>list_filter</code>. Reemplaza tu clase <code>BookInstanceAdmin</code> actual con el fragmento de código de abajo.</p> + +<pre class="brush: python">class BookInstanceAdmin(admin.ModelAdmin): +<strong> list_filter = ('status', 'due_back')</strong> +</pre> + +<p>La vista de lista incluirá ahora un cuadro de filtrado a la derecha. Nota como puedes elegir fechas y estados para filtrar los valores:</p> + +<p><img alt="Admin Site - BookInstance List Filters" src="https://mdn.mozillademos.org/files/14037/admin_improved_bookinstance_list_filters.png" style="height: 528px; width: 960px;"></p> + +<h3 id="Organizar_el_diseño_de_vista_detallada">Organizar el diseño de vista detallada</h3> + +<p>Por defecto, las vistas detalladas organizan todos los campos verticalmente, en su órden de declaración en el modelo. Puedes cambiar el orden de declaración, qué campos se despliegan (o excluyen), si se usa secciones para organizar la información, si los campos se despliegan en horizontal o vertical, e incluso qué controles de edición se usan en los formularios de administración.</p> + +<div class="note"> +<p><strong>Nota</strong>: Los modelos de la <em><strong>LocalLibrary </strong></em>son relativamente simples, por lo que no tenemos una gran necesidad de cambiar el diseño; sin embargo haremos algunos cambios solo para mostrarte cómo.</p> +</div> + +<h4 id="Controlando_qué_campos_son_desplegados_y_ordenados">Controlando qué campos son desplegados y ordenados</h4> + +<p>Actualiza tu clase <code>AuthorAdmin </code>para añadir la línea <code>fields</code>, como se muestra abajo (en negrita):</p> + +<pre class="brush: python">class AuthorAdmin(admin.ModelAdmin): + list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death') +<strong> fields = ['first_name', 'last_name', ('date_of_birth', 'date_of_death')]</strong> +</pre> + +<p>El atributo <code>fields</code> lista solo los campos que se van a desplegar en el formulario, en orden. Los campos se despliegan en vertical por defecto, pero se desplegarán en horizontal si los agrupas en una tupla (como se muestra en los campos "date" arriba).</p> + +<p>Reinicia tu aplicación y ve a la vista de detalle de autor -- ahora debería aparecer como se muestra abajo:</p> + +<p><img alt="Admin Site - Improved Author Detail" src="https://mdn.mozillademos.org/files/14027/admin_improved_author_detail.png" style="border-style: solid; border-width: 1px; display: block; height: 282px; margin: 0px auto; width: 928px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes también usar el atributo <code>exclude</code> para declarar una lista de atributos que se excluirán del formulario (todos los demás atributos en el modelo se desplegarán).</p> +</div> + +<h4 id="Seccionando_la_vista_de_detalle">Seccionando la vista de detalle</h4> + +<p>Puedes añadir "secciones" para agrupar información relacionada del modelo dentro del formulario de detalle, usando el atributo <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.fieldsets">fieldsets.</a></p> + +<p>En el modelo BookInstance tenemos información relacionada a cuál es el libro (ej. <code>name</code>, <code>imprint</code> e <code>id</code>) y a cuándo estará disponible (<code>status</code>, <code>due_back</code>). Podemos configurarlas en diferentes secciones añadiendo el texto en negrita a nuestra clase <code>BookInstanceAdmin</code>.</p> + +<pre class="brush: python">@admin.register(BookInstance) +class BookInstanceAdmin(admin.ModelAdmin): + list_filter = ('status', 'due_back') + +<strong> fieldsets = ( + (None, { + 'fields': ('book', 'imprint', 'id') + }), + ('Availability', { + 'fields': ('status', 'due_back') + }), + )</strong></pre> + +<p>Cada sección tiene su propio título (o <code>None</code>, si no quieres un título) y una tupla de campos asociada en un diccionario -- el formato es complicado de describir pero bastante fácil de entender si observas el fragmento de código que se encuentra justo arriba.</p> + +<p>Reinicia y navega a una vista de instancia de libro (book instance); el formulario debería aparecer como se muestra abajo:</p> + +<p><img alt="Admin Site - Improved BookInstance Detail with sections" src="https://mdn.mozillademos.org/files/14029/admin_improved_bookinstance_detail_sections.png" style="border-style: solid; border-width: 1px; display: block; height: 580px; margin: 0px auto; width: 947px;"></p> + +<h3 id="Edición_en_cadena_de_registros_asociados">Edición en cadena de registros asociados</h3> + +<p>A veces puede tener sentido el añadir registros asociados al mismo tiempo. Por ejemplo, puede tener sentido el tener información tanto de un libro como de las copias específicas que has adquirido del mismo, en la misma página de detalle.</p> + +<p>Puedes hacerlo declarando <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.ModelAdmin.inlines">inlines</a>, de tipo <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.TabularInline">TabularInline</a> (diseño horizontal) o <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.StackedInline">StackedInline</a> (diseño vertical, tal como el diseño de modelo por defecto). Puedes añadir la información de <code>BookInstance</code> dentro de nuestro detalle de <code>Book</code> añadiendo las líneas de abajo en negrita cerca de tu <code>BookAdmin</code>:</p> + +<pre class="brush: python"><strong>class BooksInstanceInline(admin.TabularInline): + model = BookInstance</strong> + +@admin.register(Book) +class BookAdmin(admin.ModelAdmin): + list_display = ('title', 'author', 'display_genre') +<strong> inlines = [BooksInstanceInline]</strong> +</pre> + +<p>Prueba recargando tu aplicación y observando la vista para un libro -- ahora deberías ver al final las instancias relacionadas a este libro (inmediatamente debajo de los campos de género del libro):</p> + +<p><img alt="Admin Site - Book with Inlines" src="https://mdn.mozillademos.org/files/14033/admin_improved_book_detail_inlines.png" style="border-style: solid; border-width: 1px; display: block; height: 889px; margin: 0px auto; width: 937px;"></p> + +<p>En este caso, todo lo que hemos hecho es declarar nuestra clase encadenada tabular, que simplemente añade todos los campos del modelo <em>encadenado</em>. Puedes especificar toda clase de información adicional para el diseño incluyendo los campos a mostrar, su órden, si son solo de lectura o no, etc. (ve <a href="https://docs.djangoproject.com/en/dev/ref/contrib/admin/#django.contrib.admin.TabularInline">TabularInline</a> para más información).</p> + +<div class="note"> +<p><strong>Nota</strong>: ¡hay algunas lamentables limitaciones a esta funcionalidad! En la captura de pantalla de arriba tenemos tres instancias del libro existentes, seguidas de tres lugares para nuevas instancias del libro (¡que se ven muy similares!). Sería mejor NO tener instancias extras por defecto del libro y simplemente añadirlas mediante el enlace <strong>Add another Book instance</strong>, o poder simplemente listar las <code>BookInstances</code> como enlaces no legibles desde aquí. La primera opción puede hacerse estableciendo el atributo <code>extra</code> a 0 en el modelo <code>BookInstanceInline</code>, inténtalo tú mismo.</p> +</div> + +<h2 id="Rétate_a_tí_mismo">Rétate a tí mismo</h2> + +<p>Hemos aprendido mucho en esta sección, así que es hora de que intentes algunas cosas.</p> + +<ol> + <li>Para la vista de lista de <code>BookInstance</code>, añade código para desplegar el libro, estado, fecha de devolución e id (en lugar del texto por defecto de <code>__str__()</code>).</li> + <li>Añade una lista encadenada de ítems <code>Book</code> (libros) a la vista detallada de <code>Author</code> usando el mismo método que usamos para <code>Book</code>/<code>BookInstance</code>.</li> +</ol> + +<ul> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>¡Eso es todo! Ahora has aprendido cómo configurar el sito de administración tanto en su forma más simple como la mejorada, cómo crear un super usuario, y cómo navegar en el sitio de administración y ver, borrar y actualizar registros. Durante el proceso has creado un grupo de libros, instancias de libros, géneros y autores que seremos capaces de listar y desplegar una vez que creemos nuestras propias vistas y plantillas.</p> + +<h2 id="Siguientes_lecturas">Siguientes lecturas</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/intro/tutorial02/#introducing-the-django-admin">Escribiendo tu primera aplicación Django, parte 2: Introducción a Django Admin</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/contrib/admin/">El sitio de administración de Django </a>(Django Docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Models", "Learn/Server-side/Django/Home_page", "Learn/Server-side/Django")}}</p> + +<p> </p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/authentication/index.html b/files/es/learn/server-side/django/authentication/index.html new file mode 100644 index 0000000000..af07915ad9 --- /dev/null +++ b/files/es/learn/server-side/django/authentication/index.html @@ -0,0 +1,714 @@ +--- +title: 'Tutorial de Django Parte 8: Autenticación y permisos de Usuario' +slug: Learn/Server-side/Django/Authentication +tags: + - Aprender + - Artículo + - Autenticacion de Django + - Autenticación + - Principiante + - Python + - Sesiones + - Tutorial + - django autenticación + - permisos +translation_of: Learn/Server-side/Django/Authentication +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}</div> + +<p class="summary">En este tutorial mostraremos cómo permitir a los usuarios iniciar sesión en tu sitio con sus propias cuentas, y cómo controlar lo que pueden hacer basándose en si han iniciado sesión o no y sus <em>permisos</em>. Como parte de esta demostración extenderemos el sitio web de la <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website" style="font-size: 1.25rem;">BibliotecaLocal</a>, añadiendo páginas de inicio y cierre de sesión, y páginas específicas de usuarios y personal de la biblioteca para ver libros que han sido prestados.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Completa todos los temas del tutorial anterior, incluyendo: <a href="/en-US/docs/Learn/Server-side/Django/Sessions">Django Tutorial Part 7: Sessions framework</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender como configurar y usar la autenticación de usuario y los permisos.</td> + </tr> + </tbody> +</table> + +<h2 id="Introducción">Introducción</h2> + +<p>Django proporciona un sistema de autenticación y autorización ("permisos"), construido sobre el framework de sesión discutido en el <a href="/en-US/docs/Learn/Server-side/Django/Sessions">tutorial anterior</a>, que le permite verificar credenciales de usuario y definir que acciones puede realizar cada usuario. El framework incluye modelos para <code>Users</code> y <code>Groups</code> (una forma genérica de aplicar permisos a más de un usuario a la vez), permisos/indicadores (permissions/flags) que designan si un usuario puede realizar una tarea, formularios y vistas para iniciar sesión en los usuarios, y view tools para restringir el contenido.</p> + +<div class="note"> +<p><strong>Nota</strong>: Según Django el sistema de autenticación pretende ser muy genérico, y, por lo tanto, no proporciona algunas características proporcinadas en otros sistemas de autenticación web. Las soluciones para algunos problemas están disponibles como paquetes de terceros. Por ejemplo, regulación de intentos de inicio de sesión y autenticación frente a terceros (por ej. OAuth).</p> +</div> + +<p>En este tutorial mostraremos cómo habilitar la autenticación de usuarios en el sitio web <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">BibliotecaLocal</a>, crear tus propias páginas de login y logout, añadir permisos a tus modelos, y controlar el acceso a las páginas. Usaremos la autenticación/permisos para desplegar listas de libros que han sido solicitados tanto por los usuarios como por los bibliotecarios.</p> + +<p>El sistema de autenticación es muy flexible, y puedes crear tus URLs, formularios, vistas y plantillas desde el inicio si quieres, simplemente llamando a la API provista para loguear al usuario. Sin embargo, en este artículo vamos a usar las vistas y formularios de autenticación "en stock" de Django para nuestras páginas de login y logout. De todos modos necesitaremos crear algunas plantillas, pero eso es bastante fácil.</p> + +<p>Te mostraremos también cómo crear permisos, y revisar el estado de login y permisos tanto en vistas como en plantillas.</p> + +<h2 id="Habilitanto_la_autenticación">Habilitanto la autenticación</h2> + +<p>La autenticación fue habilitada automáticamente cuando <a href="/es/docs/Learn/Server-side/Django/skeleton_website">creamos el sitio web esqueleto</a> (en el tutorial 2), así que no necesitas hacer nada más en este punto.</p> + +<div class="note"> +<p><strong>Nota</strong>: Toda la configuración necesaria fue hecha por nosotros cuando creamos la aplicación usando el comando <code>django-admin startproject</code>. Las tablas de base de datos para los usuarios y permisos de modelo fueron creados la primera vez que ejecutamos <code>python manage.py migrate</code>.</p> +</div> + +<p>La configuración se establece en las secciones <code>INSTALLED_APPS</code> y <code>MIDDLEWARE</code> del archivo del proyecto (<strong>locallibrary/locallibrary/settings.py</strong>), como se muestra abajo:</p> + +<pre class="brush: python notranslate">INSTALLED_APPS = [ + ... +<strong> 'django.contrib.auth', </strong>#Core authentication framework and its default models. +<strong> 'django.contrib.contenttypes', #</strong>Django content type system (allows permissions to be associated with models). + .... + +MIDDLEWARE = [ + ... +<strong> 'django.contrib.sessions.middleware.SessionMiddleware',</strong> #Manages sessions across requests + ... +<strong> 'django.contrib.auth.middleware.AuthenticationMiddleware',</strong> #Associates users with requests using sessions. + .... +</pre> + +<h2 id="Creando_usuarios_y_grupos">Creando usuarios y grupos</h2> + +<p>Ya creaste tu primer usuario cuando revisamos el <a href="/es/docs/Learn/Server-side/Django/Admin_site">sitio de administración de Django</a> en el tutorial 4 (fue un superusuario, creado con el comando <code>python manage.py createsuperuser</code>). Nuestro superusuario ya está autenticado y tiene todos los permisos, así que necesitaremos crear un usuario de prueba que represente un usuario normal del sitio. Estaremos usando el sitio de administración para crear los grupos y logins de nuestro sitio web <em>BibliotecaLocal</em>, ya que es una de las formas más rápidas de hacerlo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Puedes también crear usuarios mediante programación, como se muestra abajo. Tendrías que hacerlo, por ejemplo, si estuvieras desarrollando una interfaz para permitir a los usuarios crear sus propios logins (no deberías dar a los usuarios acceso al sito de administración).</p> + +<pre class="brush: python notranslate">from django.contrib.auth.models import User + +# Create user and save to the database +user = User.objects.create_user('myusername', 'myemail@crazymail.com', 'mypassword') + +# Update fields and then save again +user.first_name = 'John' +user.last_name = 'Citizen' +user.save() + +</pre> +</div> + +<p>A continuación, primero crearemos un grupo y luego un usuario. Aunque no tengamos ningún permiso aún para otorgar a los miembros de nuestra biblioteca, si lo necesitamos para más adelante, será mucho más fácil otorgarlo una vez al grupo que individualmente a cada miembro.</p> + +<p>Inicia el servidor de desarrollo y navega hasta el sitio de administracion en tu navegador web local (<a href="http://127.0.0.1:8000/admin/">http://127.0.0.1:8000/admin/</a>). Ingresa al sitio usando las credenciales de la cuenta de tu superusuario. El nivel superior del sitio de administracion "Admin site" muestra todos tus modelos, ordenados por la aplicacion por defecto de Django "django application". Desde la seccion de <strong>Autenticación y Autorización </strong>puedes dar click en los enlaces de <strong>Usuarios </strong>"Users" y <strong>Grupos </strong>"Groups" para ver todos sus registros existentes.</p> + +<p><img alt="Admin site - add groups or users" src="https://mdn.mozillademos.org/files/14091/admin_authentication_add.png" style="border-style: solid; border-width: 1px; display: block; height: 364px; margin: 0px auto; width: 661px;"></p> + +<p>Primero vamos a crear un nuevo grupo para los miembros de nuestra biblioteca.</p> + +<ol> + <li>Da click en el boton <strong>Add </strong>"Añadir" (Enseguida de Group) para crear un nuevo grupo ; ingresa el <strong>Nombre </strong>"Name" para el grupo de "Library Members".<img alt="Admin site - add group" src="https://mdn.mozillademos.org/files/14093/admin_authentication_add_group.png" style="border-style: solid; border-width: 1px; display: block; height: 561px; margin: 0px auto; width: 800px;"></li> + <li>No necesitamos de ningun permiso para el grupo , entonces solo presiona Save (Seras redirigido a una lista de los grupos disponibles).</li> +</ol> + +<p>Ahora vamos a crear un usuario:</p> + +<ol> + <li>Navega de vuelta a la pagina de inicio "home" del sitio de administracion "Admin site".</li> + <li>Da click en el boton <strong>Add </strong>"Añadir" que queda enseguida de Users "Usuarios" para abrir el cuadro de dialogo de Usuario <strong>Add </strong>"Añadir usuario".<img alt="Admin site - add user pt1" src="https://mdn.mozillademos.org/files/14095/admin_authentication_add_user_prt1.png" style="border-style: solid; border-width: 1px; display: block; height: 409px; margin: 0px auto; width: 800px;"></li> + <li>Ingresa un <strong>Nombre de Usuario </strong>"Username", <strong>Contraseña </strong>"Password" y <strong>Confirmacion de Contraseña</strong> "Password confirmation" apropiado para tu usuario de prueba.</li> + <li>Presiona <strong>Save </strong>"Guardar" para crear el usuario.<br> + <br> + El sitio de administrador creara el nuevo usuario e inmediatamente te llevara a la pantalla de <em>Change user </em>"Cambios del usuario" donde puedes cambiar tu <strong>nombre de usuario</strong> "Username" y agregar informacion para los campos opcionales del modelo de Usuario "User". Estos campos incluyen el primer nombre "first name", el apellido "last name", la direcion de correo electronico "email adress", los estados de los usuarios y sus permisos "users status and permissions" (solo el indicador <strong>Active </strong>"Activo" deberia ser activado). Mas abajo puedes especificar los grupos y permisos del usuario, y ver datos importantes relacionados a el usuario (ej: la fecha en que se agrego y la fecha del ultimo inicio de sesion)</li> + <li><img alt="Admin site - add user pt2" src="https://mdn.mozillademos.org/files/14097/admin_authentication_add_user_prt2.png" style="border-style: solid; border-width: 1px; display: block; height: 635px; margin: 0px auto; width: 800px;"></li> + <li>En la seccion <em>Groups</em> "Grupos", selecciona el grupo <strong>Library Member</strong> de la lista de grupos disponibles, y entonces presiona la <strong>la flecha apuntando a la derecha </strong>entre las dos cajas para moverlo dentro de la caja de <em>Chosen groups </em>"Grupos seleccionados".<img alt="Admin site - add user to group" src="https://mdn.mozillademos.org/files/14099/admin_authentication_user_add_group.png" style="border-style: solid; border-width: 1px; display: block; height: 414px; margin: 0px auto; width: 933px;"></li> + <li>Aqui no necesitamos hacer nada adicional, entonces de nuevo solo seleciona <strong>SAVE</strong> "Guardar", para ir a la lista de usuarios.</li> +</ol> + +<p>¡Esta hecho! Ahora tienes la cuenta de un miembro normal de la libreria, el cual estara disponible para ser usado en tus pruebas (una vez que hayamos implementado las paginas para permitirles iniciar sesion).</p> + +<div class="note"> +<p><strong>Nota</strong>: Deberias intentar crear otro usuario miembro de <em>library. </em>Al igual que un grupo para los bibliotecarios <em>"Librarians", </em>¡y agregar usuarios a este tambien! </p> +</div> + +<h2 id="Configurando_nuestras_vistas_de_autenticación">Configurando nuestras vistas de autenticación</h2> + +<p>Django provee todo lo necesario para crear las páginas de autenticación para manejar inicio y cierre de sesión y gestión de contraseñas "fuera de la caja". Esto incluye un mapeador de URL, vistas "views" y formularios "forms", pero no incluye las plantillas "templates", ¡Tenemos que crear las nuestras!</p> + +<p>En esta sección, mostramos cómo integrar el sistema por defecto en el sitio web de <em>BibliotecaLocal </em>y crear plantillas "templates". Las incluiremos en las URLs principales del proyecto.</p> + +<div class="note"> +<p><strong>Nota</strong>: No tienes que usar nada de este código, pero es probable que quieras hacerlo porque hace las cosas mucho más fáciles. Seguramente necesitará cambiar el código de manejo de formularios si cambia su modelo de usuario (¡un tema avanzado!) pero aun asi, todavía podrá usar las funciones de vista de stock.</p> +</div> + +<div class="note"> +<p><strong>Nota: </strong>En este caso podríamos razonablemente poner las páginas de autenticación, incluyendo las direcciones URL y plantillas, dentro de nuestra aplicación de catálogo. Sin embargo, si tuviéramos varias aplicaciones, sería mejor separar este comportamiento de inicio de sesión compartido y tenerlo disponible en todo el sitio, ¡así que eso es lo que hemos mostrado aquí!</p> +</div> + +<h3 id="URLs_del_proyecto">URL's del proyecto</h3> + +<p>Añade el siguiente codigo al final del archivo url.py del proyecto (<strong>locallibrary/locallibrary/urls.py</strong>) :</p> + +<pre class="brush: python notranslate">#Add Django site authentication urls (for login, logout, password management) +urlpatterns += [ + path('accounts/', include('django.contrib.auth.urls')), +] +</pre> + +<p>Navega hasta la URL <a href="http://127.0.0.1:8000/accounts/">http://127.0.0.1:8000/accounts/</a> (¡Nota la barra inclinada hacia adelante!) y Django mostrara un error, diciendo que no puede encontrar esta URL, y listando todas las URL's que ha intentado. Aqui puedes ver las URL's que funcionaran, por ejemplo:</p> + +<div class="note"> +<p><strong>Nota: </strong>Usando el metodo anterior, añade las siguientes URL's con sus respectivos nombres entre corchetes, los cuales pueden ser usados para revertir "reverse" el mapeado de las URL's. No necesitas implementar nada mas, el anterior mapeado de URL's asigna automaticamente las mencionadas URL's.</p> +</div> + +<div class="note"> +<pre class="brush: python notranslate">^accounts/login/$ [name='login'] +^accounts/logout/$ [name='logout'] +^accounts/password_change/$ [name='password_change'] +^accounts/password_change/done/$ [name='password_change_done'] +^accounts/password_reset/$ [name='password_reset'] +^accounts/password_reset/done/$ [name='password_reset_done'] +^accounts/reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$ [name='password_reset_confirm'] +^accounts/reset/done/$ [name='password_reset_complete']</pre> +</div> + +<p>Ahora intenta navegar a la URL de inicio de sesion "login"(<a href="http://127.0.0.1:8000/accounts/login/">http://127.0.0.1:8000/accounts/login/</a>). Esto fallara de nuevo, pero ahora con un error diciendote que no encuentra la plantilla "template" requerida (<strong>registration/login.html</strong>) por el buscador de directorios de plantillas . Veras el las siguientes lineas en la seccion amarilla en la parte superior:</p> + +<pre class="brush: python notranslate">Exception Type: TemplateDoesNotExist +Exception Value: <strong>registration/login.html</strong></pre> + +<p>El siguiente paso es crear un directorio de registro en la busqueda de directorios y entonces agregar el archivo <strong>login.html.</strong></p> + +<h3 id="Directorio_de_plantilla_template">Directorio de plantilla "template"</h3> + +<p>Las URL's (y vistas "views" implicitas) que recien hemos añadido esperan encontrar sus plantillas "templates" asociadas en un directorio "<strong>/registration/"</strong> en algún lugar de la ruta de búsqueda de plantillas</p> + +<p>Para este sitio pondremos nuestra pagina HTML en el directorio <strong>"templates/registration/". </strong>Este directorio debera estar en el directorio raiz de tu proyecto, es decir, el mismo directorio de las carpetas donde estan <strong>catalog </strong>y <strong>locallibrary</strong>. Por favor ahora crea las carpetas "templates" y dentro de esta "registration".</p> + +<div class="note"> +<p><strong>Note:</strong> Your folder structure should now look like the below:<br> + locallibrary (django project folder)<br> + |_catalog<br> + |_locallibrary<br> + |_templates <strong>(new)</strong><br> + |_registration</p> +</div> + +<p>Para hacer estos directorios visibles al cargador de plantillas (es decir introducir este directorio en el buscador de directorios de plantillas) abre el archivo de configuracion del proyecto setting.py (<strong>/locallibrary/locallibrary/settings.py)</strong>, y actualiza la seccion de <strong>TEMPLATES </strong>con la linea <strong>'DIRS'</strong> como se muestra a continuacion.</p> + +<pre class="brush: python notranslate">TEMPLATES = [ + { + ... +<strong> 'DIRS': ['./templates',],</strong> + 'APP_DIRS': True, + ... +</pre> + +<h3 id="Plantilla_inicio_de_sesión_login">Plantilla inicio de sesión "login"</h3> + +<div class="warning"> +<p><strong>Importante</strong>: Las plantillas de autenticacion provista en este articulo son versiones muy basicas y ligeramete modificadas de las plantillas de inicio de sesion de demostracion de Django. ¡Necesitas personalizarlos para tus propios usos!</p> +</div> + +<p>Crea un nuevo archivo HTML llamado /<strong>locallibrary/templates/registration/login.html</strong>. suministrado en el siguiente contenido :</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + +{% if form.errors %} +<p>Your username and password didn't match. Please try again.</p> +{% endif %} + +{% if next %} + {% if user.is_authenticated %} + <p>Your account doesn't have access to this page. To proceed, + please login with an account that has access.</p> + {% else %} + <p>Please login to see this page.</p> + {% endif %} +{% endif %} + +<form method="post" action="{% url 'login' %}"> +{% csrf_token %} + +<div> + <td>\{{ form.username.label_tag }}</td> + <td>\{{ form.username }}</td> +</div> +<div> + <td>\{{ form.password.label_tag }}</td> + <td>\{{ form.password }}</td> +</div> + +<div> + <input type="submit" value="login" /> + <input type="hidden" name="next" value="\{{ next }}" /> +</div> +</form> + +{# Assumes you setup the password_reset view in your URLconf #} +<p><a href="{% url 'password_reset' %}">Lost password?</a></p> + +{% endblock %}</pre> + +<p id="sect1">Estas plantillas comparten algunas similitudes con algunas que hemos visto antes — extiende nuestra plantilla base y sobreescribe el bloque <code>content</code>. El resto del código es un código de manejo de formularios bastante estándar, que trataremos en un tutorial posterior. Todo lo que necesitas saber por ahora es que esto mostrará un formulario en el que puedes introducir tu usuario y contraseña, y que si introduces valores inválidos se te pedirá que ingreses los valores correctos cuando la página refresque.</p> + +<p>Navega de vuelta a la página de inicio sesión (<a href="http://127.0.0.1:8000/accounts/login/">http://127.0.0.1:8000/accounts/login/</a>) una vez que hayas guardado tu plantilla, y deberías ver algo como esto:</p> + +<p><img alt="Library login page v1" src="https://mdn.mozillademos.org/files/14101/library_login.png" style="border-style: solid; border-width: 1px; display: block; height: 173px; margin: 0px auto; width: 441px;"></p> + +<p>Si intentas iniciar sesión tendrá éxito y serás redirigido a otra página (por defecto será <a href="http://127.0.0.1:8000/accounts/profile/">http://127.0.0.1:8000/accounts/profile/</a>). El problema aquí es que, por defecto, Django espera que después de iniciar sesión seas llevado a una página de perfil (que podrá ser el caso o no). Como no has definido esta página todavía, ¡obtendrás otro error!</p> + +<p>Abre la configuración del proyecto (<strong>/locallibrary/locallibrary/settings.py</strong>) y añade al final el texto de abajo. Ahora cuando inicies sesión deberías ser redirigido a la página de inicio por defecto.</p> + +<pre class="brush: python notranslate"># Redirect to home URL after login (Default redirects to /accounts/profile/) +LOGIN_REDIRECT_URL = '/' +</pre> + +<h3 id="Plantilla_cierre_de_sesión_logout">Plantilla cierre de sesión "logout"</h3> + +<p>Si navegas a la url de cierre de sesión (<a href="http://127.0.0.1:8000/accounts/logout/">http://127.0.0.1:8000/accounts/logout/</a>) verás un extraño comportamiento — tu usuario cerrará la sesión, pero serás llevado a la página de cierre de sesión del <strong>Administrador</strong>. Eso no es lo que quieres, aunque sólo sea porque el enlace de inicio de sesión de esa página te lleva a la pantalla del inicio de sesión del Administrador (y eso sólo está disponible a los usuarios que tienen el permiso <code>is_staff</code>).</p> + +<p>Crea y abre el fichero /<strong>locallibrary/templates/registration/logged_out.html</strong>. Copia en él el siguiente texto:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} +<p>Logged out!</p> + +<a href="{% url 'login'%}">Click here to login again.</a> +{% endblock %}</pre> + +<p>Esta plantilla es muy simple. Tan sólo muestra un mensaje informándote que has cerrado sesión, y provee un enlace que puedes pulsar para volver a la página de inicio de sesión. Si vas a la url de cierre de sesión otra vez, deberías ver esta página:</p> + +<p><img alt="Library logout page v1" src="https://mdn.mozillademos.org/files/14103/library_logout.png" style="border-style: solid; border-width: 1px; display: block; height: 169px; margin: 0px auto; width: 385px;"></p> + +<h3 id="Plantillas_de_reinicio_de_contraseña_Password_reset">Plantillas de reinicio de contraseña "Password reset"</h3> + +<p>El sistema de reinicio de contraseña usa el correo electrónico para enviar al usuario un enlace de reinicio. Necesitas crear formularios para obtener la dirección de correo electrónico del usuario, enviar el correo, permitirle introducir una nueva contraseña y tenerla en cuenta cuando todo el proceso se haya completado.</p> + +<p>Las siguientes plantillas pueden usarse como un punto de partida.</p> + +<h4 id="Formulario_de_reinicio_de_contraseña">Formulario de reinicio de contraseña</h4> + +<p>Este es el formulario para obtener la dirección del correo electrónico del usuario (para enviar el correo de reinicio de contraseña). Crea <strong>/locallibrary/templates/registration/password_reset_form.html</strong>, y establece el siguiente contenido:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} +{% block content %} + +<form action="" method="post">{% csrf_token %} + {% if form.email.errors %} \{{ form.email.errors }} {% endif %} + <p>\{{ form.email }}</p> + <input type="submit" class="btn btn-default btn-lg" value="Reset password" /> +</form> + +{% endblock %} +</pre> + +<h4 id="Reinicio_de_contraseña_hecho">Reinicio de contraseña hecho</h4> + +<p>Este formulario es mostrado después de que tu dirección de correo electrónico haya sido recogida. Crea <strong>/locallibrary/templates/registration/password_reset_done.html</strong>, y establece el siguiente contenido:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} +{% block content %} +<p>We've emailed you instructions for setting your password. If they haven't arrived in a few minutes, check your spam folder.</p> +{% endblock %} +</pre> + +<h4 id="Correo_electrónico_de_reinicio_de_contraseña">Correo electrónico de reinicio de contraseña</h4> + +<p>Esta plantilla suministra el texto HTML del correo electrónico, y contiene el enlace de reseteo que enviaremos a los usuarios. Crea <strong>/locallibrary/templates/registration/password_reset_email.html</strong>, y establece el siguiente contenido:</p> + +<pre class="brush: html notranslate">Someone asked for password reset for email \{{ email }}. Follow the link below: +\{{ protocol}}://\{{ domain }}{% url 'password_reset_confirm' uidb64=uid token=token %} +</pre> + +<h4 id="Confirmación_de_reinicio_de_contraseña">Confirmación de reinicio de contraseña</h4> + +<p>Esta página es donde introduces una nueva contraseña después de pinchar el enlace en el correo electrónico de reinicio de contraseña. Crea <strong>/locallibrary/templates/registration/password_reset_confirm.html</strong>, y establece el siguiente contenido:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + + {% if validlink %} + <p>Please enter (and confirm) your new password.</p> + <form action="" method="post"> + <div style="display:none"> + <input type="hidden" value="\{{ csrf_token }}" name="csrfmiddlewaretoken"> + </div> + <table> + <tr> + <td>\{{ form.new_password1.errors }} + <label for="id_new_password1">New password:</label></td> + <td>\{{ form.new_password1 }}</td> + </tr> + <tr> + <td>\{{ form.new_password2.errors }} + <label for="id_new_password2">Confirm password:</label></td> + <td>\{{ form.new_password2 }}</td> + </tr> + <tr> + <td></td> + <td><input type="submit" value="Change my password" /></td> + </tr> + </table> + </form> + {% else %} + <h1>Password reset failed</h1> + <p>The password reset link was invalid, possibly because it has already been used. Please request a new password reset.</p> + {% endif %} + +{% endblock %} +</pre> + +<h4 id="Reinicio_de_contraseña_completado">Reinicio de contraseña completado</h4> + +<p>Este es el último paso de la plantilla de reinicio de contraseña, que es mostrada para notificarte cuando el reinicio de contraseña ha tenido éxito. Crea <strong>/locallibrary/templates/registration/password_reset_complete.html</strong>, y establece el siguiente contenido:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} +{% block content %} + +<h1>The password has been changed!</h1> +<p><a href="{% url 'login' %}">log in again?</a></p> + +{% endblock %}</pre> + +<h3 id="Probando_las_nuevas_páginas_de_autenticación">Probando las nuevas páginas de autenticación</h3> + +<p>Ahora que has añadido la configuración URL y creado todas estas plantillas, ¡las páginas de autenticación ahora deberían funcionar!</p> + +<p>Puedes probar las nuevas páginas de autenticación intentando iniciar sesión y entonces cerrar sesión con tu cuenta de super administrador usando estas URLs:</p> + +<ul> + <li><a href="http://127.0.0.1:8000/accounts/login/">http://127.0.0.1:8000/accounts/login/</a></li> + <li><a href="http://127.0.0.1:8000/accounts/logout/">http://127.0.0.1:8000/accounts/logout/</a></li> +</ul> + +<p>Serás capaz de probar la funcionalidad de reinicio de contraseña desde el enlace de la página de inicio de sesión. <strong>¡Ten cuidado con el hecho de que Django solamente enviará correos de reinicio a las direcciones (usuarios) que ya están almacenadas en la base de datos!</strong></p> + +<div class="note"> +<p><strong>Nota</strong>: El sistema de reinicio de contraseña requiere que tu sitio web soporte envío de correo, que está más allá del ámbito de este artículo, por lo que esta parte <strong>no funcionará todavía</strong>. Para permitir el testeo, establece la siguiente línea al final de tu fichero settings.py. Esto registra en la consola cualquier envío de correo electrónico (y así puedes copiar el enlace de reinicio de contraseña desde dicha consola).</p> + +<pre class="brush: python notranslate">EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend' +</pre> + +<p>Para más información, ver <a href="https://docs.djangoproject.com/en/1.10/topics/email/">Sending email</a> (Django docs).</p> +</div> + +<h2 id="Probando_contra_usuarios_autenticados">Probando contra usuarios autenticados</h2> + +<p>Esta sección mira a lo que podemos hacer para controlar selectivamente el contenido que el usuario ve basado en si ha iniciado sesión o no.</p> + +<h3 id="Probando_en_plantillas">Probando en plantillas</h3> + +<p>Puedes obtener información en las plantillas sobre el usuario que actualmente ha iniciado sesión con la variable de plantillas <code>\{{ user }}</code> (esto se añade por defecto al contexto de la plantilla cuando configuras el proyecto como hicimos en nuestro esqueleto).</p> + +<p>Es típico que primero pruebes con la variable de plantilla <code>\{{ user.is_authenticated }}</code> para determinar si el usuario puede ver el contenido específico. Para demostrar esto, lo siguiente que haremos será actualizar nuestra barra lateral "sidebar" para mostrar un enlace de inicio de sesión "Login" si el usuario no ha iniciado sesión, y un cierre de sesión "Logout" en el caso de que sí la haya iniciado.</p> + +<p>Abre la plantilla base (<strong>/locallibrary/catalog/templates/base_generic.html</strong>) y copia el siguiente texto en el bloque <code>sidebar</code>, justamente antes de la etiqueta de plantilla <code>endblock</code> .</p> + +<pre class="brush: html notranslate"> <ul class="sidebar-nav"> + + ... + + <strong>{% if user.is_authenticated %}</strong> + <li>User: <strong>\{{ user.get_username }}</strong></li> + <li><a href="{% url 'logout'%}?next=\{{request.path}}">Logout</a></li> + <strong>{% else %}</strong> + <li><a href="{% url 'login'%}?next=\{{request.path}}">Login</a></li> + <strong>{% endif %} </strong> + </ul></pre> + +<p>Como puedes ver, usamos las etiquetas de plantilla <code>if</code>-<code>else</code>-<code>endif</code> para condicionar el texto mostrado basado en si <code>\{{ user.is_authenticated }}</code> es cierto o no. Si el usuario está autenticado, sabemos que tenemos un usuario válido, por lo que llamamos a <strong>\{{ user.get_username }} </strong>para mostrar su nombre.</p> + +<p>Creamos los enlaces URLs del inicio y del cierre de sesión usando la etiqueta de plantilla <code>url</code> y los nombres de las respectivas configuraciones de las URL. Nótese también cómo hemos añadido <code>?next=\{{request.path}}</code> al final de las URLs. Lo que esto hace es añadir el párametro URL <font face="Consolas, Liberation Mono, Courier, monospace">next</font> que contiene la dirección (URL) de la página <em>actual</em>, al final de la URL enlazada. Después de que el usuario haya iniciado o cerrado sesión con éxito, las vistas usarán el valor de este "<code>next</code>" para redirigir al usuario de vuelta a la página donde pincharon primeramente el enlace de inicio/cierre de sesión.</p> + +<div class="note"> +<p><strong>Nota</strong>: ¡Pruébalo! Si estás en la página de inicio y pinchas en la barra lateral "sidebar", después de que la operación se complete deberías acabar de vuelta en la misma página.</p> +</div> + +<h3 id="Probando_en_vistas">Probando en vistas</h3> + +<p>Si estás usando vistas basadas en funciones, la forma más facil para restringir el acceso a tus funciones es aplicar el decorador <code>login_required</code> a tu función de vista, como se muestra más abajo. Si el usuario ha iniciado sesión entonces tu código de vista se ejecutará como normalmente lo hace. Si el usuario no ha iniciado sesión, se redirigirá a la URL de inicio de sesión definida en tu configuración de proyecto (<code>settings.LOGIN_URL</code>), pasando el directorio absoluto actual como el parámetro URL <code>next</code>. Si el usuario tiene éxito en el inicio de sesión entonces será devuelto a esta página, pero esta vez autenticado.</p> + +<pre class="brush: python notranslate">from django.contrib.auth.decorators import login_required + +@login_required +def my_view(request): + ...</pre> + +<div class="note"> +<p><strong>Nota:</strong> ¡Tú puedes hacer el mismo tipo de cosas manualmente probando con <code>request.user.is_authenticated</code>, pero el decorador es mucho más conveniente!</p> +</div> + +<p>De manera similar, la forma más fácil de restringir el acceso a los usuarios que han iniciado sesión en tus vistas basadas en clases es extender de <code>LoginRequiredMixin</code>. Necesitas declarar primeramente este <code>mixin </code>en la lista de super clases, antes de la clase de vista principal.</p> + +<pre class="brush: python notranslate">from django.contrib.auth.mixins import LoginRequiredMixin + +class MyView(LoginRequiredMixin, View): + ...</pre> + +<p>Esto tiene exactamente el mismo comportamiento de redirección que el decorador <code>login_required</code>. También puedes especificar una localización alternativa para redirigir al usuario si no están autenticados (<code>login_url</code>), y un nombre de parámetro URL en lugar de "<code>next</code>" para insertar el directorio absoluto actual (<code>redirect_field_name</code>).</p> + +<pre class="brush: python notranslate">class MyView(LoginRequiredMixin, View): + login_url = '/login/' + redirect_field_name = 'redirect_to' +</pre> + +<p>Para detalles adicionales, echa un vistazo a <a href="https://docs.djangoproject.com/en/1.10/topics/auth/default/#limiting-access-to-logged-in-users">Django docs</a>.</p> + +<h2 id="Ejemplo_-_listando_los_libros_del_usuario_actual">Ejemplo - listando los libros del usuario actual</h2> + +<p>Ahora que sabemos cómo restringir una página a un usuario concreto, vamos a crear una vista de los libros que el usuario tiene prestados actualmente.</p> + +<p>Desafortunadamente, ¡todavía no tenemos una forma de pedir prestados los libros a los usuarios! Por eso, antes de que podamos crear la lista de libros vamos primeramente a extender el modelo <code>BookInstance</code> para dar soporte al concepto de pedir prestado y usar la aplicación del Administrador Djando para alquilar un número de libros a nuestro usuario de prueba.</p> + +<h3 id="Modelos">Modelos</h3> + +<p>Primero vamos a hacer posible para los usuarios tener una <code>BookInstance</code> en alquiler (ya tenemos un <code>status</code> y una fecha <code>due_back</code>, pero no tenemos todavía una asociación entre este modelo y un Usuario). Crearemos uno usando un campo <code>ForeignKey</code> (uno-a-muchos). También necesitaremos un mecanismo sencillo para probar si un libro alquilado está atrasado.</p> + +<p>Abre <strong>catalog/models.py</strong>, e importa el modelo <code>User</code> de <code>django.contrib.auth.models</code> (añade esto justamente debajo de la anterior línea de importación, arriba del todo del fichero, para que el <code>User</code> esté disponible para el posterior código del que hace uso):</p> + +<pre class="brush: python notranslate">from django.contrib.auth.models import User +</pre> + +<p>Después añade el campo <code>borrower</code> al modelo <code>BookInstance</code>:</p> + +<pre class="brush: python notranslate">borrower = models.ForeignKey(User, on_delete=models.SET_NULL, null=True, blank=True) +</pre> + +<p>Ya que estamos aquí, vamos a añadir una propiedad que podamos llamar desde nuestras plantillas para decir si una instancia particular de un libro está atrasada. Mientras que podríamos calcular esto en la misma plantilla, usar una propiedad (<a href="https://docs.python.org/3/library/functions.html#property">property</a>) como se muestra abajo será mucho más eficiente.</p> + +<pre class="brush: python notranslate">from datetime import date + +@property +def is_overdue(self): + if self.due_back and date.today() > self.due_back: + return True + return False</pre> + +<div class="note"> +<p><strong>Nota</strong>: Primeramente verificamos si la fecha <code>due_back</code> está vacía antes de realizar una comparación. Un campo vacío <code>due_back</code> provocaría a Django arrojar un error en lugar de mostrar la página: los valores vacíos no son comparables. ¡Esto no es algo que queramos para la experiencia de nuestros usuarios!</p> +</div> + +<p>Ahora que hemos actualizado nuestros modelos, necesitaremos hacer migraciones actuales en el proyecto y entonces aplicar esas migraciones:</p> + +<pre class="brush: bash notranslate">python3 manage.py makemigrations +python3 manage.py migrate +</pre> + +<h3 id="Administrador">Administrador</h3> + +<p>Ahora abre <strong>catalog/admin.py</strong>, y añade el campo <code>borrower</code> a la clase <code>BookInstanceAdmin</code> en ambas <code>list_display</code> y <code>fieldsets</code> como se muestra abajo. Esto hará el campo visible en la sección de Administrador, por lo que podemos asignar un <code>User</code> a una <code>BookInstance</code> cuando lo necesitemos.</p> + +<pre class="brush: python notranslate">@admin.register(BookInstance) +class BookInstanceAdmin(admin.ModelAdmin): + list_display = ('book', 'status'<strong>, 'borrower'</strong>, 'due_back', 'id') + list_filter = ('status', 'due_back') + + fieldsets = ( + (None, { + 'fields': ('book','imprint', 'id') + }), + ('Availability', { + 'fields': ('status', 'due_back'<strong>,'borrower'</strong>) + }), + )</pre> + +<h3 id="Alquilar_unos_pocos_libros">Alquilar unos pocos libros</h3> + +<p>Ahora que es posible alquilar libros a un usuario específico, ve y alquila un número de registros <code>BookInstance</code>. Establece su campo <code>borrowed</code> a tu usuario de prueba, establece el <code>status</code> "On loan" (en alquiler) y establece fechas de vencimiento tanto en el futuro como en el pasado.</p> + +<div class="note"> +<p><strong>Nota</strong>: No escribiremos el proceso, porque ¡ya sabes cómo usar el sitio de Administrador!</p> +</div> + +<h3 id="Vista_en_alquiler">Vista en alquiler</h3> + +<p>Ahora añadiremos una vista para obtener la lista de todos los libros que han sido alquilados al usuario actual. Usaremos la misma vista de lista genérica basada en clases con la que estamos familiarizada, pero esta vez también importaremos y extenderemos de <code>LoginRequiredMixin</code>, por lo que solamente un usuario que ha iniciado sesión podrá llamar a esta vista. También elegiremos declarar una <code>template_name</code> en lugar de usar la de por defecto, porque quizás acabemos teniendo unas pocas listas diferentes de registros de BookInstance, con diferentes vistas y plantillas.</p> + +<p>Añade lo siguiente a catalog/views.py:</p> + +<pre class="brush: python notranslate">from django.contrib.auth.mixins import LoginRequiredMixin + +class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView): + """ + Generic class-based view listing books on loan to current user. + """ + model = BookInstance + template_name ='catalog/bookinstance_list_borrowed_user.html' + paginate_by = 10 + + def get_queryset(self): + return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')</pre> + +<p>Para restringir nuestra consulta a solamente los objetos BookInstance del usuario actual, vamos a reimplementar <code>get_queryset()</code> como se muestra abajo. Nótese que "o" es el código almacenado para "on loan" (en alquiler) y vamos a ordenar por la fecha <code>due_back</code> para que los elementos más antiguos se muestren primero.</p> + +<h3 id="Configuración_URL_para_libros_alquilados">Configuración URL para libros alquilados</h3> + +<p>Ahora abre <strong>/catalog/urls.py</strong> y añade la url <code>url()</code> apuntando a la vista anterior (puedes simplemente copiar el texto de abajo al final del fichero).</p> + +<pre class="brush: python notranslate">urlpatterns += [ + url(r'^mybooks/$', views.LoanedBooksByUserListView.as_view(), name='my-borrowed'), +]</pre> + +<h3 id="Plantilla_para_libros_alquilados">Plantilla para libros alquilados</h3> + +<p>Ahora todo lo que necesitamos hacer para esta página es añadir una plantilla. Primero, creamos el fichero plantilla <strong>/catalog/templates/catalog/bookinstance_list_borrowed_user.html</strong> y establecemos el siguiente contenido en ella:</p> + +<pre class="brush: python notranslate">{% extends "base_generic.html" %} + +{% block content %} + <h1>Borrowed books</h1> + + {% if bookinstance_list %} + <ul> + + {% for bookinst in bookinstance_list %} + <li class="{% if bookinst.is_overdue %}text-danger{% endif %}"> + <a href="{% url 'book-detail' bookinst.book.pk %}">\{{bookinst.book.title}}</a> (\{{ bookinst.due_back }}) + </li> + {% endfor %} + </ul> + + {% else %} + <p>There are no books borrowed.</p> + {% endif %} +{% endblock %}</pre> + +<p>Esta plantilla es muy similar a esas que hemos creado previamente para los objetos <code>Book</code> y <code>Author</code>. La única "cosa" nueva aquí es que comprobamos el método que hemos añadido en el modelo <code>(bookinst.is_overdue</code>) y lo usamos para cambiar el color de los elementos atrasados.</p> + +<p>Cuando el servidor de desarrollo esté en ejecución, deberías ser capaz de ver la lista de los usuarios que han iniciado sesión en tu navegador en <a href="http://127.0.0.1:8000/catalog/mybooks/">http://127.0.0.1:8000/catalog/mybooks/</a>. Prueba esto con tu usuario iniciado en la sesión y cerrado en la sesión (en el segundo caso, deberías ser redirigido a la página de inicio).</p> + +<h3 id="Añadir_la_lista_a_la_barra_lateral">Añadir la lista a la barra lateral</h3> + +<p>El último paso es añadir un enlace para esta nueva página en la barra lateral "sidebar". Pondremos esto en la misma sección donde mostramos otra información para el usuario que ha iniciado la sesión.</p> + +<p>Abre la plantilla base (<strong>/locallibrary/catalog/templates/base_generic.html</strong>) y añade la línea en negrita a la barra lateral como se muestra.</p> + +<pre class="brush: python notranslate"> <ul class="sidebar-nav"> + {% if user.is_authenticated %} + <li>User: \{{ user.get_username }}</li> +<strong> <li><a href="{% url 'my-borrowed' %}">My Borrowed</a></li></strong> + <li><a href="{% url 'logout'%}?next=\{{request.path}}">Logout</a></li> + {% else %} + <li><a href="{% url 'login'%}?next=\{{request.path}}">Login</a></li> + {% endif %} + </ul> +</pre> + +<h3 id="¿Cómo_se_ve">¿Cómo se ve?</h3> + +<p>Cuando cualquier usuario ha iniciado sesión, verán el enlace <em>My Borrowed</em> (Mis Alquileres) en la barra lateral, y la lista de libros mostrados como se ve abajo (¡el primer libro no tiene fecha de vencimiento, que es un bug que esperamos arreglar en un tutorial posterior!).</p> + +<p><img alt="Library - borrowed books by user" src="https://mdn.mozillademos.org/files/14105/library_borrowed_by_user.png" style="border-style: solid; border-width: 1px; display: block; height: 215px; margin: 0px auto; width: 530px;"></p> + +<h2 id="Permisos">Permisos</h2> + +<p>Los permisos están asociados con los modelos, y definen las operaciones que pueden llevarse a cabo en un modelo instanciado por un usuario que tiene el permiso. Por defecto, Django automáticamente da los permisos <em>add</em>, <em>change</em>, and <em>delete</em> (añadir, cambiar y eliminar) a todos los modelos, que permiten a los usuarios con los permisos realizar las acciones asociadas a través del sitio de Administrador. Tú puedes definir tus propios permisos a los modelos y concedérselos a usuarios específicos. También puedes cambiar los permisos asociados con diferentes instancias del mismo modelo.</p> + +<p>Probar permisos en vistas y plantillas es muy similar a probar sobre el estado de autenticación (y, de hecho, probar un permiso también prueba una autenticación).</p> + +<h3 id="Modelos_2">Modelos</h3> + +<p>La definición de permisos está hecha en la sección del modelo "<code>class Meta</code>", usando el campo <code>permissions</code>. Puedes especificar tantos permisos como necesites en una tupla, cada permiso está definido a sí mismo en una tupla anidada que contiene el nombre del permiso y el valor mostrado del mismo. Por ejemplo, podríamos definir un permiso para permitir a un usuario marcar un libro que ya ha sido devuelto, como se muestra:</p> + +<pre class="brush: python notranslate">class BookInstance(models.Model): + ... + class Meta: + ... +<strong> permissions = (("can_mark_returned", "Set book as returned"),) </strong> </pre> + +<p>Podríamos asignar el permiso a un grupo bibliotecario "Librarian" en el sitio de Administración.</p> + +<p>Abre <strong>catalog/models.py</strong>, y añade el permiso como se muestra arriba. Necesitarás volver a ejecutar tus migraciones (ejecutar <code>python3 manage.py makemigrations</code> y <code>python3 manage.py migrate</code>) para actualizar la base de datos de forma apropiada.</p> + +<h3 id="Plantillas">Plantillas</h3> + +<p>Los permisos del usuario actual están almacenados en una variable de plantilla llamada <code>\{{ perms }}</code>. Puedes comprobar si el usuario actual tiene un permiso particular usando el nombre de variable específico con la "app" asociada en Django — ej. <code>\{{ perms.catalog.can_mark_returned }}</code> será <code>True</code> (cierto) si el usuario tiene el permiso, y <code>False</code> (falso) en otro caso. De forma típica probamos el permiso usando la etiqueta de plantilla <code>{% if %}</code> como se muestra:</p> + +<pre class="brush: python notranslate">{% if perms.catalog.<code>can_mark_returned</code> %} + <!-- We can mark a BookInstance as returned. --> + <!-- Perhaps add code to link to a "book return" view here. --> +{% endif %} +</pre> + +<h3 id="Vistas">Vistas</h3> + +<p>Los permisos pueden ser probados en una vista de función usando el decorador <code>permission_required</code> o en una vista basada en clases usando el <code>PermissionRequiredMixin</code>. El patrón y el comportamiento son los mismos que para la autenticación de inicio de sesión, aunque desde luego podrías razonablemente tener que añadir múltiples permisos.</p> + +<p>Decorador de vista de funciones:</p> + +<pre class="brush: python notranslate">from django.contrib.auth.decorators import permission_required + +@permission_required('catalog.<code>can_mark_returned</code>') +@permission_required('catalog.<code>can_edit</code>') +def my_view(request): + ...</pre> + +<p>"Mixin" de permisos requeridos para vistas basadas en clases:</p> + +<pre class="brush: python notranslate">from django.contrib.auth.mixins import PermissionRequiredMixin + +class MyView(PermissionRequiredMixin, View): + permission_required = 'catalog.<code>can_mark_returned</code>' + # Or multiple permissions + permission_required = ('catalog.<code>can_mark_returned</code>', 'catalog.can_edit') + # Note that 'catalog.can_edit' is just an example + # the catalog application doesn't have such permission!</pre> + +<h3 id="Ejemplo">Ejemplo</h3> + +<p>Nosotros no actualizaremos la <em>LocalLibrary</em> aquí; ¡quizás en el siguiente tutorial!</p> + +<h2 id="Desafíate_a_ti_mismo">Desafíate a ti mismo</h2> + +<p>Anteriormente en este artículo te mostramos cómo crear una página para el usuario actual para listar los libros que había pedido prestado. El desafío ahora es crear una página similar que solamente sea visible para los bibliotecarios, que muestre todos los libros que hayan sido prestados, y que incluya el nombre de cada prestatario.</p> + +<p>Deberías ser capaz de seguir el mismo patrón que el de la otra vista. La principal diferencia es que necesitarás restringir la vista a solamente los bibliotecarios. Podrías hacer esto basándote en si es un miembro de los empleados (decorador de función: <code>staff_member_required</code>, variable de plantilla: <code>user.is_staff</code>) pero nosotros te recomendamos que en su lugar uses el permiso <code>can_mark_returned</code> y <code>PermissionRequiredMixin</code>, como se describe en la sección anterior.</p> + +<div class="warning"> +<p><strong>Importante</strong>: Recuerda no usar tu súper usuario para pruebas basadas en permisos (la comprobación de permisos siempre devuelve cierto para súper usuarios, ¡incluso si un permiso no ha sido definido todavía!). En su lugar, crea un usuario bibliotecario, y añade entonces la capacidad requerida.</p> +</div> + +<p>Cuando hayas terminado, tu página debería verse algo parecida a la captura de pantalla de abajo.</p> + +<p><img alt="All borrowed books, restricted to librarian" src="https://mdn.mozillademos.org/files/14115/library_borrowed_all.png" style="border-style: solid; border-width: 1px; display: block; height: 283px; margin: 0px auto; width: 500px;"></p> + +<ul> +</ul> + +<h2 id="Sumario">Sumario</h2> + +<p>Excelente trabajo — has creado un sitio web para que los miembros de la biblioteca puedan iniciar sesión y ver su propio contenido, y los bibliotecarios (con el permiso correcto) puedan usarlo para ver todos los libros alquilados y sus prestatarios. En este momento estamos todavía simplemente viendo contenido, pero los mismos principios y técnicas son usados cuando empiezas a modificar y añadir datos.</p> + +<p>En nuestro siguiente artículo observaremos cómo puedes usar los formularios de Django para recoger la entrada de datos del usuario, y entonces empezar a modificar algunos de nuestros datos almacenados.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/auth/">Autenticación de Usuario en Django</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/auth/default//">Usando el sistema por defecto de Autenticación de Django</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/class-based-views/intro/#decorating-class-based-views">Introducción a clases basadas en vistas > Decoradores</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Sessions", "Learn/Server-side/Django/Forms", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> + +<div id="gtx-trans" style="position: absolute; left: 170px; top: 8184.58px;"> +<div class="gtx-trans-icon"></div> +</div> diff --git a/files/es/learn/server-side/django/deployment/index.html b/files/es/learn/server-side/django/deployment/index.html new file mode 100644 index 0000000000..ddcb7f5c4e --- /dev/null +++ b/files/es/learn/server-side/django/deployment/index.html @@ -0,0 +1,672 @@ +--- +title: 'Tutorial de Django Parte 11: Desplegando Django a producción' +slug: Learn/Server-side/Django/Deployment +translation_of: Learn/Server-side/Django/Deployment +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}</div> + +<p class="summary">Ahora que has creado (y probado) un fantastico sitio web para la <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Biblioteca Local</a>, querrás instalarlo en un servidor web público de manera que pueda ser accedido por el personal y los miembros de la biblioteca a través de Internet. Este artículo proporciona una visión general de cómo buscar un host para desplegar tu sitio web y de lo que necesitas hacer para conseguir que tu sitio esté listo en producción.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Completar todos los tutoriales de los temas previos, incluyendo <a href="/en-US/docs/Learn/Server-side/Django/Testing">Django Tutorial Part 10: Testing a Django web application</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Aprender ¿cómo? y ¿dónde? puedes puedes desplegar una app de Django en producción.</td> + </tr> + </tbody> +</table> + +<h2 id="Introducción">Introducción</h2> + +<p>Una vez que tu sitio este terminado (o lo suficientemente terminado como para iniciar una prueba pública) vas a necesitar alojarla en un lugar más público y accesible que tu computadora personal.</p> + +<p>Hasta ahora has estado trabajando en un entorno de desarrollo, usando <em>Django development web server </em>para compartir tu sitio con el navegador/red local, y corriendo tu sitio web con configuraciones (inseguras) de desarrollo que exponen la depuración y otra informacion privada. Antes de que puedas alojar tu sitio web externamente, lo primero que tendrás que hacer es:</p> + +<ul> + <li>Introducir algunos cambios en las configuraciones del proyecto.</li> + <li>Elegir un entorno para alojar la aplicacion Django.</li> + <li>Elegir un entorno para alojar cualquier archivo estático.</li> + <li>Configurar una infraestructura a nivel producción para servir tu sitio web.</li> +</ul> + +<p>Este tutorial provee una guía de opciones para elegir un sitio de alojamiento, una breve descripción general de lo que necesitas hacer para preparar tu aplicación Django en producción, y un ejemplo práctico de cómo instalar el sitio web de LocalLibrary en el servicio de alojamiento en la nube de <a href="https://www.heroku.com/">Heroku</a>.</p> + +<h2 id="¿Qué_es_un_entorno_de_producción">¿Qué es un entorno de producción?</h2> + +<p>El entorno de producción es el entorno proporcionado por el servidor en el que correrá su sitio web para uso externo. El entorno incluye:</p> + +<ul> + <li>Equipos en los que el sitio web correrá.</li> + <li>Sistema operativo (p.e. Linux, Windows).</li> + <li>Lenguajes de programación y librerías sobre las que su sitio web está escrito.</li> + <li>Servidor web empleado para servir páginas y otros contenidos (p.e. Nginx, Apache).</li> + <li>Servidor de aplicaciones que transmite peticiones "dinámicas" entre su sitio web Django y el servidor web.</li> + <li>Bases de datos que su sitio web necesita.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Dependiendo de como esté configurado su entorno de producción, usted podría disponer también de un proxy inverso, balanceador de carga, etc.</p> +</div> + +<p>El servidor podría estar ubicado en sus propias instalaciones y conectado a Internet a través de un enlace rápido, pero lo más común es utilizar un computador alojado "en la nube". Esto en realidad implica que su código es ejecutado en algún computador remoto (o posiblemente un computador "virtual") en el centro (o centros) de datos de su compañía de servicios de <em>hosting.</em> El servidor remoto normalmente ofrecerá un determinado nivel garantizado de recursos de computación (es decir, CPU, RAM, memoria de almacenamiento, etc) y de conectividad a Internet por un cierto precio.</p> + +<p>A este tipo de hardware de computación/comunicaciones accesible de forma remota se le denomina <em>Infrastructure as a Service </em>o<em> Infraestructura como Servicio (IaaS)</em>. Muchos proveedores de IaaS ofrecen la opción de preinstalar un sistema operativo en particular, sobre el cual se debe instalar el resto de componentes de su entorno de producción. Otros permiten seleccionar entornos plenamente configurados, con incluso configuraciones de Django y servidor web establecidas.</p> + +<div class="note"> +<p><strong>Nota</strong>: Los entornos pre-construidos le permiten establecer su sitio web de manera muy sencilla, ya que reducen el trabajo de configuración, pero las opciones disponibles podrían limitarle al uso de un servidor (u otros componentes) poco conocido, o podrían estar basados en versiones antiguas del Sistema Operativo. A menudo es preferible que uno mismo instale sus propios componentes, de manera que disponga de los que desee, y en el momento que necesite subir el nivel de prestaciones de alguna parte del sistema, tener cierta idea de por dónde empezar</p> +</div> + +<p>Otros proveedores de <em>hosting</em> incluyen Django como parte de una <em>Plataform as a Service </em>o<em> Plataforma como Servicio (PaaS)</em>. En este tipo de <em>hosting</em> no necesita preocuparse de la mayor parte del entorno de producción (servidor web, servidor de aplicaciones, balanceadores de carga), dado que la plataforma host ya se ocupa de todo ello por usted (así como de casi todo lo necesario para escalar su aplicación). Esto hace el despliegue bastante sencillo, puesto que ya solo necesita concentrarse en su aplicación web y no en el resto de la infraestructura de servidor.</p> + +<p>Algunos desarrolladores elegirán la mayor flexibilidad ofrecida por una IaaS frente a una PaaS, mientras que otros valorarán el reducido coste general de mantenimiento y la mayor facilidad de escalado de PaaS. Cuando se está empezando, la instalación del sitio web en un sistema PaaS es mucho más sencilla, así que eso es lo que haremos en este tutorial. </p> + +<div class="note"> +<p><strong>Consejo:</strong> Si eliges un proveedor de hosting adaptado a Python/Django, éste debería facilitar instrucciones de cómo instalar un sitio web Django usando diferentes configuraciones de servidor web, servidor de aplicaciones, proxy inverso, etc (esto es irrelevante si eliges una PaaS). Por ejemplo, existen muchas guías paso-a-paso para distintas configuraciones en la <a href="https://www.digitalocean.com/community/tutorials?q=django">Digital Ocean Django community docs</a>.</p> +</div> + +<h2 id="Eligiendo_un_proveedor_de_hosting">Eligiendo un proveedor de hosting</h2> + +<p>Existen más de 100 proveedores de hosting de los que se sabe que, o bien dan soporte activo, o funcionan bien con Django (puedes encontrar una lista bastante extensa en <a href="http://djangofriendly.com/hosts/">Djangofriendly hosts</a>). Estos proveedores proporcionan diferentes tipos de entornos (IaaS, PaaS), así como diferentes niveles de recursos de computación y comunicaciones a diferentes precios.</p> + +<p>Algunos aspectos a considerar al elegir un host son:</p> + +<ul> + <li>Una estimación de cómo de ocupado va a estar el sitio y el coste de los recursos de datos y computación requeridos para atender esa demanda.</li> + <li>Nivel de soporte para el escalado tanto horizontal (añadir más máquinas) como vertical (subir de nivel con máquinas más potentes), y el coste que ello supone.</li> + <li>Dónde están ubicados los centros de datos de los proveedores y, por consiguientte, a cuáles será probablemente más rápido el acceso.</li> + <li>Los históricos de permanencia en actividad e inactividad del host.</li> + <li>Herramientas proporcionadas para la gestión del sitio — si son fáciles de usar y si son seguras (Por ejemplo, SFTP frente a FTP). </li> + <li>Frameworks incorporadas para poder monitorear tu servidor.</li> + <li>Limitaciones conocidas. Algunos hosts bloquearán deliberadamente ciertos servicios (por ejemplo, email). Otros ofrecerán solo un cierto número de horas de "tiempo vivo" en determinados niveles de precios, u ofrecerán solo una pequeña cantidad de almacenamiento.</li> + <li>Beneficios adicionales. Algunos proveedores pueden ofrecer de forma gratuita nombres de dominio y soporte para certificados SSL por los que, de otro modo, tendrías que pagar.</li> + <li>Si el nivel "gratuito" del que dependes expira al cabo de un tiempo, o si el coste de migrar a un nivel más caro puede implicar que sea más conveniente usar algún otro servicio desde el primer momento.</li> +</ul> + +<p>La buena noticia cuando estás en los comienzos es que existen bastantes sitios que proporcionan entornos de computación de "evaluación", "desarrollo" o "de nivel aficionado" de forma gratuita. Se trata siempre de entornos bastantes limitados/restringidos en recursos, y debes estar precavido en que pueden expirar al cabo de un periodo de introducción. Son, no obstante, muy útiles para probar sitios con poco tráfico en un entorno real, y pueden proporcionar una migración sencilla contratando más recursos si el sitio alcanza más ocupación. Entre las opciones conocidas de esta categoría tenemos <a href="https://www.heroku.com/">Heroku</a>, <a href="https://www.pythonanywhere.com/">Python Anywhere</a>, <a href="http://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/billing-free-tier.html">Amazon Web Services</a>, <a href="https://azure.microsoft.com/en-us/pricing/details/app-service/">Microsoft Azure</a>, etc. </p> + +<p>Muchos proveedores disponen también de un nivel "básico" que proporciona niveles de capacidad de computación más útiles y con menos limitaciones. <a href="https://www.digitalocean.com/">Digital Ocean</a> y <a href="https://www.pythonanywhere.com/">Python Anywhere</a> son ejemplos de proveedores populares de hosting que ofrecen niveles básicos de computación relativamente baratos (en el rango de los 5 a los 10 $USD mensuales).</p> + +<div class="note"> +<p><strong>Nota:</strong> Recuerda que el precio no es el único criterio de selección. Si tu sitio web tiene éxito, la escalabilidad puede convertirse en la consideración más importante.</p> +</div> + +<h2 id="Preparando_tu_sitio_web_para_hacerlo_público">Preparando tu sitio web para hacerlo público</h2> + +<p>La <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django skeleton website</a> creada usando las herramientas <em>django-admin </em>y <em>manage.py</em> están configuradas para hacer más sencillo el desarrollo. Muchos de los ajustes del proyecto Django (especificados en <strong>settings.py</strong>) deberían ser distintos en producción, por razones tanto de seguridad como de rendimiento.</p> + +<div class="note"> +<p><strong>Consejo:</strong> Es bastante común disponer de un archivo <strong>settings.py</strong> separado en producción, e importar los ajustes sensibles desde un archivo aparte o desde una variable de entorno. Este archivo debería, por tanto, estar protegido, aún cuando el resto del código fuente esté disponible en un repositorio público.</p> +</div> + +<p>Los ajustes críticos que debes comprobar son:</p> + +<ul> + <li><code>DEBUG</code>. Debería establecerse como <code>False</code> en producción (<code>DEBUG = False</code>). Así se evita que se muestre la traza de depuración sensible/confidencial y la información variable.</li> + <li><code>SECRET_KEY</code>. Es un valor aleatorio grande utilizado para la protección CRSF etc. Es importante que la clave utilizada en producción no esté en el control fuente ni accesible desde fuera del servidor de producción. La documentación Django sugiere que debería ser cargada desde una variable de entorno o leída desde un archivo de sólo servicio (<em>serve-only file</em>).</li> + <li> + <pre class="notranslate"># Read SECRET_KEY from an environment variable +import os +SECRET_KEY = os.environ['SECRET_KEY'] + +#OR + +#Read secret key from a file +with open('/etc/secret_key.txt') as f: + SECRET_KEY = f.read().strip()</pre> + </li> +</ul> + +<p>Modifiquemos la aplicación <em>LocalLibrary</em> de manera que leamos nuestras variables <code>SECRET_KEY</code> y <code>DEBUG</code> desde variables de entorno si han sido definidas o, en otro caso, usar los valores por defecto del archivo de configuración.</p> + +<p><span>Abra </span><strong>/locallibrary/settings.py</strong><span>, deshabilite la configuración original de l </span><code>SECRET_KEY</code><span> y añada las nuevas líneas tal como se muestran abajo en <strong>negrita</strong>. Durante el desarrollo no se especificará ninguna variable de entorno para la clave, por lo que se usará el valor por defecto (no debería importar qué clave utilizas aquí, o si la clave tiene "fugas", dado que no la utilizarás en producción).</span></p> + +<pre class="brush: python notranslate"># SECURITY WARNING: keep the secret key used in production secret! +# SECRET_KEY = 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag' +<strong>import os</strong> +<strong>SECRET_KEY = os.environ.get('DJANGO_SECRET_KEY', 'cg#p$g+j9tax!#a3cup@1$8obt2_+&k3q+pmu)5%asj6yjpkag')</strong> +</pre> + +<p>A continuación, comenta el ajuste de <code>DEBUG</code> existente y añade la nueva línea que se muestra abajo.</p> + +<pre class="brush: python notranslate"># SECURITY WARNING: don't run with debug turned on in production! +# DEBUG = True +<strong>DEBUG = bool( os.environ.get('DJANGO_DEBUG', True) )</strong> +</pre> + +<p>El valor de <code>DEBUG</code> será <code>True</code> por defecto, pero será <code>False</code> si el valor de la variable de entorno <code>DJANGO_DEBUG</code> se establece como una cadena vacía, es decir, <code>DJANGO_DEBUG=''</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Sería más intuitivo si pudiéramos simplemente marcar y desmarcar la variable de entorno <code>DJANGO_DEBUG</code> a <code>True</code> y <code>False</code> directamente, en lugar de usar "cualquier cadena" o "cadena vacía" (respectivamente). Por desgracia, los valores de las variables de entorno son almacenados como cadenas de Python (<em>Python strings</em>), y la única cadena que se evalúa como <code>False</code> es la cadena vacía (por ejemplo, <code>bool('')==False</code>).</p> +</div> + +<p><a href="https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/">Deployment checklist</a> (Django docs) proporciona una lista de comprobación completa de ajustes que podrías querer cambiar. Puedes también sacar una lista de algunos de ellos usando el siguiente comando de terminal:</p> + +<pre class="brush: python notranslate">python3 manage.py check --deploy +</pre> + +<h2 id="Ejemplo_Instalando_LocalLibrary_en_Heroku">Ejemplo: Instalando LocalLibrary en Heroku</h2> + +<p>Esta sección aborda una demostración práctica de cómo instalar <em>LocalLibrary</em> en <a href="http://heroku.com">Heroku PaaS cloud</a>.</p> + +<h3 id="¿Por_qué_Heroku">¿Por qué Heroku?</h3> + +<p>Heroku es uno de los servicios PaaS basados en la nube más duraderos y conocidos. Originalmente únicamente daba soporte a aplicaciones Ruby, pero actualmente puede utilizarse para aplicaciones host de muchos entornos de programación, incluido Django!</p> + +<p>Vamos a elegir Heroku por varias razones:</p> + +<ul> + <li>Heroku tiene un nivel gratuito (<a href="https://www.heroku.com/pricing">free tier</a>) que es <em>verdaderamente</em> gratuito (aunque con algunas limitaciones).</li> + <li>Como PaaS, Heroku se hace cargo de gran parte de la infraestructura web por nosotros. Esto hace mucho más sencillos los comienzos, al no tener que preocuparnos por servidores, balanceadores de carga, proxys inversos, o cualquier otro aspecto de la infraestructura web, de los que Heroku se ocupa por nosotros en un segundo plano.</li> + <li>Aunque tenga algunas limitaciones, éstas no afectarán a nuestra aplicación particular. Por ejemplo: + <ul> + <li>Heroku sólo proporciona almacenamiento efímero, por lo que los archivos subidos por el usuario no pueden almacenarse de forma segura en el propio Heroku.</li> + <li>El nivel gratuito mantendrá dormida cualquier aplicación web inactiva que no haya tenido requerimientos dentro de un periodo de media hora. El sitio puede tardar varios segundos en responder cuando se le despierte.</li> + <li>El nivel gratuito limita el tiempo que el sitio puede estar en ejecución a cierta cantidad de horas al mes (sin contar el tiempo que el sitio permanece "dormido"). Esto está bien para un sitio de poco uso o de demostración, pero no es asumible si se necesita una disponibilidad del 100%. </li> + <li>Otras limitaciones se relacionan en <a href="https://devcenter.heroku.com/articles/limits">Limits</a> (Heroku docs).</li> + </ul> + </li> + <li>Lo principal es que funciona, y si te termina gustando, escalar tus aplicaciones será muy sencillo.</li> +</ul> + +<p>Si bien Heroku es perfecto para alojar esta demostración, puede no serlo para tu sitio web real. Heroku facilita la instalación y el escalado, a costa de ser menos flexible, y potencialmente mucho más caro una vez que abandonas el nivel gratuito.</p> + +<h3 id="¿Cómo_funciona_Heroku">¿Cómo funciona Heroku?</h3> + +<p>Heroku ejecuta sitios web Django dentro de uno o más "<a href="https://devcenter.heroku.com/articles/dynos">Dynos</a>", que son contenedores Unix virtualizados y aislados que proporcionan el entorno necesario para ejecutar una aplicación. Los dynos están completamente aislados y disponen de un sistema de archivos <em>efímero</em> (sistema de archivos de vida corta que es limpiado/vaciado cada vez que el dyno se reinicia). Lo único que los dynos comparten por defecto son las variables de configuración (<a href="https://devcenter.heroku.com/articles/config-vars">configuration variables</a>) de las aplicaciones. Heroku utiliza interrnamente un balanceador de carga para distribuir el tráfico web entre todas las dynos "web". Puesto que no se comparte nada entre ellas, Heroku puede escalar una app horizontalmente simplemente añadiendo más dynos (aunque, claro está, podrías necesitar escalar tu base de datos para aceptar conexiones adicionales).</p> + +<p>Puesto que el sistema de archivos es efímero, no puedes instalar los servicios requeridos por tu aplicación directamente (por ejemplo, bases de datos, colas, sistemas de cacheado, almacenamiento, servicios de correo electrónico, etc). En su lugar, las aplicaciones web de Heroku usan servicios de respaldo proporcionados por Heroku o terceros como "add-ons" independientes. Una vez adjuntados a tu aplicación web, los dynos acceden a los servicios usando la información contenida en las variables de configuración de la aplicación.</p> + +<p>Para ejecutar tu aplicación, Heroku necesita poder instalar el entorno y las dependencias adecuados, y entender cómo están enlazados. Para las apps Django, esta información se proporciona en una serie de archivos de texto:</p> + +<ul> + <li><strong>runtime.txt</strong>:<strong> </strong>el lenguaje de programación y la versión a utilizar.</li> + <li><strong>requirements.txt</strong>: dependiencias de los componentes de Python, incluyendo a Django.</li> + <li><strong>Procfile</strong>: Lista de procesos que han de ejecutarse para arrancar la aplicación web. Para Django, esto será normalmente el servidor de aplicaciones web Gunicorn (con un script .wsgi).</li> + <li><strong>wsgi.py</strong>: Configuración <a href="http://wsgi.readthedocs.io/en/latest/what.html">WSGI</a> para invocar a nuestra aplicación Django en el entorno Heroku.</li> +</ul> + +<p>Los desarrolladores interactúan con Heroku usando una app/terminal cliente especial, algo muy parecido a un bash script de Unix. Esto permite subir código almacenado en un repositorio git, inspeccionar los procesos en ejecución, ver logs, establecer variables de configuración, y mucho más!.</p> + +<p>Para conseguir nuestra aplicación para trabajar en Heroku, necesitaremos colocar nuestra aplicación web Django dentro de un repositorio git, añadir los archivos anteriores, integrar con una base de datos add-on, y hacer cambios para manejar correctamente los archivos estáticos.</p> + +<p>Una vez hecho todo eso, podemos crear una cuenta Heroku, obtener el cliente Heroku, y usarlo para instalar nuestro sitio web.</p> + +<div class="note"> +<p><strong>Nota: </strong>Las instrucciones indicadas abajo reflejan la forma de trabajar con Heroku en el momento de la redacción. Si Heroku cambia sus procesos de forma significativa, podrías preferir, en su lugar, revisar su documentación de instalación: <a href="https://devcenter.heroku.com/articles/getting-started-with-python#introduction">Getting Started on Heroku with Django</a>.</p> +</div> + +<p>Con esto ya tienes una visión general de lo que necesitas para empezar (vea <a href="https://devcenter.heroku.com/articles/how-heroku-works">How Heroku works</a> para tener una guía más exhaustiva).</p> + +<h3 id="Creando_un_repositorio_de_aplicación_en_Github">Creando un repositorio de aplicación en Github</h3> + +<p>Heroku está estrechamente integrado con el sistema de control de versiones de código fuente <strong>git</strong>, usándolo para subir/sincronizar cualquier cambio que hagas en los sistemas activos. Esto se hace añadiendo un nuevo repositorio "remoto" heroku denominado <em>heroku</em> que apunta a un repositorio para tu fuente en la nube Heroku. Durante el desarrollo usas git para almacenar los cambios en tu repositorio "maestro". Cuando quieras desplegar tu sitio, sincronizas tus cambios con el repositorio Heroku.</p> + +<div class="note"> +<p><strong>Nota:</strong> Si estás acostumbrado a seguir buenas prácticas de desarrollo de software, probablemente ya estás usando git o algún otro sistema SCM. Si ya dispones de un repositorio git, podrás saltarte este paso.</p> +</div> + +<p>Existen muchas formas de trabajar con git, pero una de las más sencillas es crear en primer lugar una cuenta en <a href="https://github.com/">Github</a>, crear allí el repositorio, y a continuación sincronizarlo localmente:</p> + +<ol> + <li>Visita <a href="https://github.com/">https://github.com/</a> y crea una cuenta.</li> + <li>Una vez conectado, haz click en el enlace <strong>+</strong> de la barra de tareas superior y selecciona <strong>New repository</strong>.</li> + <li>Rellena todos los campos de este formulario. Aunque no son obligatorios, es muy recomendable que los rellenes todos. + <ul> + <li>Introduce el nombre del nuevo repositorio (por ejemplo, <em>django_local_library</em>), y una descripción (por ejemplo "Sitio web de la Biblioteca Local escrita en Django").</li> + <li>Selecciona <strong>Python</strong> en la lista de selección <em>Add .gitignore.</em></li> + <li>Selecciona tu licencia en la lista de selección <em>Add license</em>.</li> + <li>Marca <strong>Initialize this repository with a README</strong>.</li> + </ul> + </li> + <li>Pulsa <strong>Create repository</strong>.</li> + <li>Haz click en el botón verde "<strong>Clone or download</strong>" en la página de tu nuevo repositorio.</li> + <li>Copia el valor de la URL del campo de texto situado dentro de la caja de diálogo que aparece (debería decir algo como: <strong>https://github.com/<em><your_git_user_id></em>/django_local_library.git</strong>).</li> +</ol> + +<p>Ahora que el repositorio ("repo") ha sido creado, querremos clonarlo en nuestra computadora local:</p> + +<ol> + <li>Instala <em>git</em> para tu computadora local (puedes encontrar versiones para distintas plataformas <a href="https://git-scm.com/downloads">here</a>).</li> + <li>Abre una ventana/terminal de comandos y clona tu repositorio usando la URL que copiaste anteriormente: + <pre class="brush: bash notranslate">git clone https://github.com/<strong><em><your_git_user_id></em></strong>/django_local_library.git +</pre> + Esto creará el repositorio debajo del punto actual.</li> + <li>Navega dentro del nuevo repositorio. + <pre class="brush: bash notranslate">cd django_local_library.git</pre> + </li> +</ol> + +<p>El paso final es copiar en él tu aplicación y a continuación añadir los archivos a tu repositorio usando git:</p> + +<ol> + <li>Copia tu aplicación Django en esta carpeta (todos los archivos que estén al mismo nivel que <strong>manage.py</strong> y por debajo, <strong>no</strong> su carpeta locallibrary contenedora). </li> + <li>Abre el archivo <strong>.gitignore</strong>, copia las siguientes líneas al final del mismo, y guárdalo (este archivo se utiliza para identificar los archivos que, por defecto, no deberían subirse a git). + <pre class="notranslate"># Text backup files +*.bak + +#Database +*.sqlite3</pre> + </li> + <li>Abre una ventana/terminal de comandos y utiliza el comando <code>add</code> para añadir todos los archivos a git. + <pre class="brush: bash notranslate">git add -A +</pre> + </li> + <li>Utiliza el comando status para comprobar que todos los archivos que vas a añadir son correctos (quieres incluir ficheros fuentes, no binarios, archivos temporales, etc). Debería tener un aspecto similar a la lista siguiente. + <pre class="notranslate">> git status +On branch master +Your branch is up-to-date with 'origin/master'. +Changes to be committed: + (use "git reset HEAD <file>..." to unstage) + + modified: .gitignore + new file: catalog/__init__.py + ... + new file: catalog/migrations/0001_initial.py + ... + new file: templates/registration/password_reset_form.html</pre> + </li> + <li>Si estás conforme, consolida tus archivos en el repositorio local: + <pre class="brush: bash notranslate">git commit -m "First version of application moved into github"</pre> + </li> + <li>A continuación, sincroniza tu repositorio local con el sitio web Github, usando lo siguiente: + <pre class="notranslate">git push origin master</pre> + </li> +</ol> + +<p>Una vez completada esta operación, deberías poder regresar a la página de Github donde creaste tu repositorio, refrescar la página, y comprobar que tu toda tu aplicación ha sido ya cargada. Puedes continuar actualizando tu repositorio según vayan cambiando los archivos, usando este ciclo add/commit/push.</p> + +<div class="note"> +<p><strong>Consejo:</strong> Este es un buen momento para hacer una copia de seguridad de tu proyecto "simple" — algunos de los cambios que vamos a ir haciendo en las siguientes secciones podrían ser útiles para el despliegue en cualquier plataforma (o para el desarrollo), pero otros no.</p> + +<p>La <em>mejor </em>manera de hacer esto es usar <em>git</em> para gestionar tus revisiones. Con <em>git</em> puedes no solo volver a una versión anterior en particular, sino que puedes mantener ésta en una "rama" separada de tus cambios en producción, y seleccionar determinados cambios a trasladar entre las ramas de producción y desarrollo. <a href="https://help.github.com/articles/good-resources-for-learning-git-and-github/">Learning Git</a> merece la pena el esfuerzo, pero queda fuera del alcance de este tema.</p> + +<p>La forma <em>más fácil </em>de hacer ésto es simplemente copiar tus archivos en otra ubicación. Usa la manera que más se ajuste a tus conocimientos de git!</p> +</div> + +<h3 id="Actualizar_la_app_para_Heroku">Actualizar la app para Heroku</h3> + +<p>Esta sección explica los cambios que necesitaras hacer a nuestra aplicación <em>LocalLibrary</em> para ponerla a funcionar en Heroku. Mientras que las instrucciones disponibles en <a href="https://devcenter.heroku.com/articles/getting-started-with-python#introduction">Getting Started on Heroku with Django</a> de Heroku asumen que también vas a utilizar el cliente Heroku para ejecutar el entorno de desarrollo local, los cambios que aquí se reflejan son compatibles con el servidor de desarrollo Django existente y las formas de funcionamiento que ya hemos aprendido.</p> + +<h4 id="Procfile">Procfile</h4> + +<p>Crea el archivo <code>Procfile</code> (sin extensión) en la carpeta raíz de tu repositorio GitHub para declarar los tipos de procesos de la aplicación y los puntos de entrada. Copia en él el texto siguiente:</p> + +<pre class="notranslate">web: gunicorn locallibrary.wsgi --log-file -</pre> + +<p>La palabra "<code>web:</code>" le dice a Heroku que se trata de una web dyno y puede ser enviada a través del tráfico HTTP. El proceso a arrancar en este dyno es <em>gunicorn</em>, un servidor de aplicaciones web popular recomendado por Heroku. Arrancamos Gunicorn usando la información de configuración que se encuentra en el módulo <code>locallibrary.wsgi</code> (creado con nuestro esqueleto de aplicación: <strong>/locallibrary/wsgi.py</strong>).</p> + +<h4 id="Gunicorn">Gunicorn</h4> + +<p><a href="http://gunicorn.org/">Gunicorn</a> es el servidor HTTP recomendado para usar con Django en Heroku (tal como se indicaba en el Procfile anterior). Es un servidor HTTP puro-Python para aplicaciones WSGI que puede ejecutar múltiples procesos Python concurrentes dentro de un único dyno (para obtener más información, véase <a href="https://devcenter.heroku.com/articles/python-gunicorn">Deploying Python applications with Gunicorn</a>).</p> + +<p>Aunque no necesitaremos <em>Gunicorn</em> para servir nuestra aplicación LocalLibrary durante el desarrollo, lo instalaremos de manera que sean parte de nuestros <a href="#requirements">requerimientos</a> de Heroku para instalar en el servidor remoto.</p> + +<p>Instala <em>Gunicorn</em> localmente usando <em>pip</em> en la línea de comandos (que instalamos en <a href="/en-US/docs/Learn/Server-side/Django/development_environment">setting up the development environment</a>):</p> + +<pre class="brush: bash notranslate">pip3 install gunicorn +</pre> + +<h4 id="Configuración_de_la_Base_de_Datos">Configuración de la Base de Datos</h4> + +<p>No podemos usar la base de datos por defecto SQLite en Heroku dado que está basada-en-fichero, y sería borrada del sistema de archivos <em>efímero</em> cada que se reiniciara la aplicación (normalmente una vez al día, y cada vez que la aplicación o sus variables de configuración fueran modificadas).</p> + +<p>El mecanismo de Herocu para gestionar esta situación es usar una <a href="https://elements.heroku.com/addons#data-stores">database add-on</a> y configurar la aplicación web utilizando información de una <a href="https://devcenter.heroku.com/articles/config-vars">variable de configuración</a> del entorno, establecida por la add-on. Existen numerosas opciones de bases de datos, pero nosotros utilizaremos el <a href="https://devcenter.heroku.com/articles/heroku-postgres-plans#plan-tiers">nivel hobby tier</a> de la base de datos <em>Heroku postgres</em> ya que es gratuita, soportada por Django, e incorporada en nuestra nuevas apps Heroku al usar el nivel gratuito plan dyno hobby.</p> + +<p>La información de conexión a la base de datos es proporcionada a la web dyno usando una variable de configuración denominada <code>DATABASE_URL</code>. En lugar de codificar esta información en Django, Heroku recomienda que los desarrolladores utilicen el paquete <a href="https://warehouse.python.org/project/dj-database-url/">dj-database-url</a> para extraer la variable de entorno <code>DATABASE_URL</code> y automáticamente convertirla al formato de configuración deseado por Django. Además para instalar el paquete <em>dj-database-url</em> necesitaremos también instalar <a href="http://initd.org/psycopg/">psycopg2</a>, ya que Django lo necesita para interactuar con la base de datos Postgres.</p> + +<h5 id="dj-database-url_Configuración_de_base_de_datos_de_Django_a_partir_de_una_variable_de_entorno">dj-database-url (Configuración de base de datos de Django a partir de una variable de entorno)</h5> + +<p>Instala <em>dj-database-url</em> a nivel local para que se convierta en parte de nuestros <a href="#requirements">requerimientos</a> para instalar Heroku en el servidor remoto:</p> + +<pre class="notranslate">$ pip3 install dj-database-url +</pre> + +<h5 id="settings.py">settings.py</h5> + +<p>Abre <strong>/locallibrary/settings.py</strong> y copia la siguiente configuración al final del archivo:</p> + +<pre class="notranslate"># Heroku: Update database configuration from $DATABASE_URL. +import dj_database_url +db_from_env = dj_database_url.config(conn_max_age=500) +DATABASES['default'].update(db_from_env)</pre> + +<div class="note"> +<p><strong>Nota:</strong></p> + +<ul> + <li>Nosotros seguiremos utilizando SQLite durante el desarrollo porque la variable de entorno <code>DATABASE_URL</code> no será fijada en nuestra computadora de desarrollo.</li> + <li>El valor <code>conn_max_age=500</code> hace que la conexión sea persistente, lo que es más eficiente que recrear la conexión en cada ciclo de petición. No obstante, esto es opcional y puede ser eliminado si es necesario.</li> +</ul> +</div> + +<h5 id="psycopg2_soporte_a_la_base_de_datos_Python_Postgres">psycopg2 (soporte a la base de datos Python Postgres)</h5> + +<p>Django necesita <em>psycopg2</em> para trabajar con las bases de datos Postgres y tú necesitarás añadir esto a los <a href="#requirements">requirements.txt</a> para que Heroku lo instale en el servidor remoto (como se expone más adelante en la sección de requerimientos).</p> + +<p>Django utilizará la base de datos SQLite en modo local por defecto, porque la variable de entorno <code>DATABASE_URL</code> no está establecida en nuestro entorno local. Si quieres cambiar a Postgres completamente y usar nuestra base de datos del nivel gratuito de Heroku tanto en desarrollo como en producción, puedes hacerlo. Por ejemplo, para instalar psycopg2 y sus dependencias localmente en un sistema basado en Linux, usarías los siguientes comandos bash/terminal:</p> + +<pre class="brush: bash notranslate"><code>sudo apt-get install python-pip python-dev libpq-dev postgresql postgresql-contrib</code> +pip3 install psycopg2 +</pre> + +<p>Puedes encontrar instrucciones de instalación para el resto de plataformas en <a href="http://initd.org/psycopg/docs/install.html">psycopg2 website</a>.</p> + +<p>No obstante, esto no es necesario — no necesitas tener activa PostGreSQL en el equipo local, en tanto que se lo indicas a Heroku como requerimiento, en <code>requirements.txt</code> (ver a continuación).</p> + +<h4 id="Sirviendo_ficheros_estáticos_en_producción">Sirviendo ficheros estáticos en producción</h4> + +<p>Durante el desarrollo utilizábamos Django y el servidor web de desarrollo de Django para servir nuestros ficheros estáticos (CSS, JavaScript, etc). En un entorno de producción normalmente se sirven los ficheros estáticos desde una red de entrega de contenidos (CDN, Content Delivery Network) o desde el servidor web.</p> + +<div class="note"> +<p><strong>Nota:</strong> Servir ficheros estáticos vía Django/aplicación web es ineficiente ya que las peticiones tienen que pasar por código adicional innecesario (Django), en vez de ser gestionados directamente por el servidor web o una CDN completamente independiente. Si bien esto no tiene relevancia en el uso local durante el desarrollo, el uso de este mecanismo en producción tiene un significativo impacto de rendimiento. </p> +</div> + +<p>Para facilitar el alojamiento de archivos estáticos de forma separada de la aplicación web Django, Django proporciona la herramienta <em>collectstatic</em> para recoger estos archivos para el despliegue (hay una variable de configuración que define de dónde se deben recopliar los archivos cuando se ejecuta <em>collectstatic</em>). Las plantillas Django hacen referencia a la localización de almacenamiento de los archivos estáticos en relación a una variable de configuración (<code>STATIC_URL</code>), por tanto, esto puede modificarse se los archivos estáticos son movidos a otro host/servidor.</p> + +<p>Las variables de configuración más relevantes son:</p> + +<ul> + <li><code>STATIC_URL</code>: Es la localización URL base desde la cual se servirán los archivos estáticos, por ejemplo en una CDN. Se usa para variables de plantilla estáticas a las que se acceden en nuestra plantilla base (ver <a href="/en-US/docs/Learn/Server-side/Django/Home_page">Django Tutorial Part 5: Creating our home page</a>).</li> + <li><code>STATIC_ROOT</code>: Es la ruta absoluta a un directorio en el que la herramienta "collectstatic" de Django reunirá todos los archivos estáticos referenciados en nuestras plantillas. Una vez recopilados, podrán ser cargados como un grupo a donde hayan de ser alojados.</li> + <li><code>STATICFILES_DIRS</code>: Relaciona directorios adicionales en los que la herramienta collestatic de Django debería buscar archivos estáticos.</li> +</ul> + +<h5 id="settings.py_2">settings.py</h5> + +<p>Abra <strong>/locallibrary/settings.py</strong> y copie la configuración siguiente al final del archivo. La variable <code>BASE_DIR</code> debería haber sido ya definida en tu fichero (la variable <code>STATIC_URL</code> puede haber sido ya definida dentro del archivo cuando fue creado. Puesto que no provocará ningún fallo, podrías borrar la referencias duplicadas).</p> + +<pre class="notranslate"># Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.10/howto/static-files/ + +# The absolute path to the directory where collectstatic will collect static files for deployment. +STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles') + +# The URL to use when referring to static files (where they will be served from) +STATIC_URL = '/static/' +</pre> + +<p>Nosotros haremos el servicio de ficheros utilizando una librería denominada <a href="https://warehouse.python.org/project/whitenoise/">WhiteNoise</a>, que instalaremos y configuraremos en la siguiente sección.</p> + +<p>Para más información, vea <a href="https://devcenter.heroku.com/articles/django-assets">Django and Static Assets</a> (Heroku docs).</p> + +<h4 id="Whitenoise">Whitenoise</h4> + +<p>Hay muchas formas de servir ficheros estáticos en producción (ya vimos los ajustes Django relevantes en las secciones previas). Heroku recomienda usar el proyecto <a href="https://warehouse.python.org/project/whitenoise/">WhiteNoise</a> para servir objetos estáticos directamente desde Gunicorn en producción.</p> + +<div class="note"> +<p><strong>Nota: </strong>Heroku llama automáticamente a <em>collectstatic</em> y prepara tus ficheros estáticos para ser usados por WhiteNoise después de que se cargue tu aplicación. Revisa la documentación <a href="https://warehouse.python.org/project/whitenoise/">WhiteNoise</a>, en la que se explica cómo funciona y por qué la implementación es un método para servir estos ficheros relativamente eficiente.</p> +</div> + +<p>Los pasos para instalar <em>WhiteNoise</em> para usarlo dentro del proyecto son:</p> + +<h5 id="WhiteNoise">WhiteNoise</h5> + +<p>Instala WhiteNoise localmente usando el siguiente comando:</p> + +<pre class="notranslate">$ pip3 install whitenoise +</pre> + +<h5 id="settings.py_3">settings.py</h5> + +<p>Para instalar <em>WhiteNoise</em> en tu aplicación Django, abre <strong>/locallibrary/settings.py</strong>, busca la opción <code>MIDDLEWARE</code> y añade <code>WhiteNoiseMiddleware</code> cerca de la parte superior de la lista, justo debajo de <code>SecurityMiddleware</code>:</p> + +<pre class="notranslate">MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', + <strong>'whitenoise.middleware.WhiteNoiseMiddleware',</strong> + 'django.contrib.sessions.middleware.SessionMiddleware', + 'django.middleware.common.CommonMiddleware', + 'django.middleware.csrf.CsrfViewMiddleware', + 'django.contrib.auth.middleware.AuthenticationMiddleware', + 'django.contrib.messages.middleware.MessageMiddleware', + 'django.middleware.clickjacking.XFrameOptionsMiddleware', +] +</pre> + +<p>Opcionalmente, puedes reducir el tamaño de los ficheros estáticos al ser servidos (lo que lo hace más eficiente). Añade lo siguiente al final de <strong>/locallibrary/settings.py</strong>:</p> + +<pre class="notranslate"># Simplified static file serving. +# https://warehouse.python.org/project/whitenoise/ +STATICFILES_STORAGE = 'whitenoise.storage.CompressedManifestStaticFilesStorage' +</pre> + +<h4 id="Requerimientos">Requerimientos</h4> + +<p>Los requerimientos Python de tu aplicación web deben ser almacenados en un archivo <strong>requirements.txt</strong> en la carpeta raíz de tu repositorio. Heroku los instalará cuando reconstruya tu entorno. Puedes crear este archivo utilizando <em>pip</em> en la línea de comandos (ejecuta los siguiente en la raíz del repositorio):</p> + +<pre class="brush: bash notranslate">pip3 freeze > requirements.txt</pre> + +<p>Después de instalar todas las dependencias anteriores, tu archivo <strong>requirements.txt</strong> debería tener <em>al menos</em> estos objetos (aunque los números de versión pueden ser diferentes). Por favor, borra cualquier otra dependencia no listada abajo, a menos que la hayas añadido explícitamente para esta aplicación.</p> + +<pre class="notranslate">dj-database-url==0.4.1 +Django==1.10.2 +gunicorn==19.6.0 +<strong>psycopg2==2.6.2</strong> +whitenoise==3.2.2 +</pre> + +<div class="note"> +<p>Asegúrate de que existe una línea <strong>psycopg2</strong> como la que se ve arriba! Incluso aunque no lo hayas instalado localmente, deberías añadirla a <strong>requirements.txt</strong>.</p> +</div> + +<h4 id="Runtime">Runtime</h4> + +<p>El archivo <strong>runtime.txt</strong>, si ha sido definido, le dice a Heroku que lenguaje de programación usar. Crea el archivo en el raíz del repositorio y añade el siguiente texto:</p> + +<pre class="notranslate">python-3.5.2</pre> + +<div class="note"> +<p><strong>Nota:</strong> Heroku sólo soporta un número pequeño de <a href="https://devcenter.heroku.com/articles/python-support#supported-python-runtimes">Python runtimes</a>. Tú puedes especificar valores de runtime de Python 3, pero en el momento de esta redacción la versión anterior será soportada como definida.</p> +</div> + +<h4 id="Guardar_los_cambios_en_Github_y_volver_a_probar.">Guardar los cambios en Github y volver a probar.</h4> + +<p>A continuacion, guardemos nuestros cambios en Github. En el terminal (dentro de nuestro respositorio), introduce los comandos siguientes:</p> + +<pre class="brush: python notranslate">git add -A +git commit -m "Added files and changes required for deployment to heroku" +git push origin master</pre> + +<p>Antes de continuar, probemos de nuevo nuestro sitio localmente y asegurémonos de que no ha sido afectado por ninguno de los cambios anteriores. Pon en marcha el servidor web de desarrollo de la forma habitual y comprueba que el sitio aún funciona como esperas en tu navegador.</p> + +<pre class="brush: bash notranslate">python3 manage.py runserver</pre> + +<p>Ya deberíamos estar preparados para empezar a desplegar LocalLibrary en Heroku.</p> + +<h3 id="Hazte_con_una_cuenta_Heroku">Hazte con una cuenta Heroku</h3> + +<p>Para empezar a usar Heroku necesitarás en primer lugar crear una cuenta:</p> + +<ul> + <li>Ve a <a href="https://www.heroku.com/">www.heroku.com</a> y haz click en el botón <strong>SIGN UP FOR FREE</strong>.</li> + <li>Introduce tus datos y pulsa a continuación <strong>CREATE FREE ACCOUNT</strong>. Se te pedirá que compruebes que has recibido un email de registro.</li> + <li>Haz click en el enlace de activación de la cuenta que aparece en el email de registro. Serás llevado de vuelta a tu cuenta en el navegador web.</li> + <li>Introduce tu contraseña y haz click en <strong>SET PASSWORD AND LOGIN</strong>.</li> + <li>Ya estarás contectado y serás llevado al tablón de Heroku (Heroku dashboard): <a href="https://dashboard.heroku.com/apps">https://dashboard.heroku.com/apps</a>.</li> +</ul> + +<h3 id="Instala_el_cliente">Instala el cliente</h3> + +<p>Descarga e instala el cliente Heroku siguiendo estas <a href="https://devcenter.heroku.com/articles/getting-started-with-python#set-up">instructiones para Heroku</a>.</p> + +<p>Una vez instalado el cliente, ya podrás ejecutar comandos. Por ejemplo, para mostrar ayuda en el cliente:</p> + +<pre class="brush: bash notranslate">heroku help +</pre> + +<h3 id="Crea_y_sube_el_sitio_web">Crea y sube el sitio web</h3> + +<p>Para crear la app ejecutamos el comando "create" en el directorio raíz de nuestro repositorio. Esta operación crea un git remoto ("puntero hacia el repositorio remoto") denominado <em>heroku</em> en nuestro entorno git local.</p> + +<pre class="brush: bash notranslate">heroku create</pre> + +<div class="note"> +<p><strong>Nota:</strong> Puedes nombrar el remoto, si lo deseas, especificando un valor después de "create". Si no, obtendrás un nombre aleatorio. Este nombre es el que se utiliza en la URL por defecto.</p> +</div> + +<p>Podemos a continuación "empujar" (push) nuestra aplicación hacia el respositorio Heroku como se muestra abajo. Este proceso subirá la aplicación, la empaquetará en un dyno, ejecutará collestatic, y arrancará el sitio.</p> + +<pre class="brush: bash notranslate">git push heroku master</pre> + +<p>Si tenemos suerte, la app ya estará "corriendo" en el sitio, pero no estará funcionando correctamente ya que no hemos colocado las tablas que usa nuestra aplicación. Para hacer esto necesitamos utilizar el comando <code>heroku run</code> y arrancar un "<a href="https://devcenter.heroku.com/articles/deploying-python#one-off-dynos">one off dyno</a>" para realizar una operación de migración. Introduce el siguiente comando en el terminal:</p> + +<pre class="brush: bash notranslate">heroku run python manage.py migrate</pre> + +<p>Vamos a necesitar también poder añadir libros y autores, así que vamos a crear nuestro superusuario de administración, de nuevo utilizando un "one-off dyno":</p> + +<pre class="brush: bash notranslate">heroku run python manage.py createsuperuser</pre> + +<p>Una vez llevado a cabo ésto, podremos ver el sitio. Debería funcionar, aunque no tendrá aún ningún libro. Para abrir el navegador hacia el nuevo sitio web, usa el comando:</p> + +<pre class="brush: bash notranslate">heroku open</pre> + +<p>Crea algunos libros en el sitio de administración, y comprueba que el sitio se comporta tal y como esperas.</p> + +<h3 id="Gestionando_addons">Gestionando addons</h3> + +<p>Puedes revisar los add-ons de tu app usando el comando <code>heroku addons</code>. Se listarán todos los addons, su nivel de precio y estado.</p> + +<pre class="brush: bash notranslate">>heroku addons + +Add-on Plan Price State +───────────────────────────────────────── ───────── ───── ─────── +heroku-postgresql (postgresql-flat-26536) hobby-dev free created + └─ as DATABASE</pre> + +<p>Aquí vemos que tenemos un único add-on, la base de datos postgres SQL. Es gratuito, y fue creado automáticamente cuando se creó la aplicación. Puedes abrir una página web en la que examinar con más detalle el add-on de la base de datos (o cualquier otro add-on) utilizando el siguiente comando:</p> + +<pre class="brush: bash notranslate">heroku addons:open heroku-postgresql +</pre> + +<p>Otros comandos te permiten crear, destruir, subir o bajar de versión de los addons (con una sintaxis similar a la de abrir). Para más información, consulta <a href="https://devcenter.heroku.com/articles/managing-add-ons">Managing Add-ons</a> (Heroku docs).</p> + +<h3 id="Estableciendo_las_variables_de_configuración">Estableciendo las variables de configuración</h3> + +<p>Puedes revisar las variables de configuración para el sitio con el comando <code>heroku config</code>. Abajo puedes comprobar que solo tenemos una variable, <code>DATABASE_URL</code>, usada para configurar nuestra base de datos.</p> + +<pre class="brush: bash notranslate">>heroku config + +=== locallibrary Config Vars +DATABASE_URL: postgres://uzfnbcyxidzgrl:j2jkUFDF6OGGqxkgg7Hk3ilbZI@ec2-54-243-201-144.compute-1.amazonaws.com:5432/dbftm4qgh3kda3</pre> + +<p>Si recuerdas de la sección <a href="#Getting_your_website_ready_to_publish">Preparando tu sitio web para hacerlo público</a>, tenemos que establecer variables de entorno para <code>DJANGO_SECRET_KEY</code> y <code>DJANGO_DEBUG</code>. Vamos a hacerlo ahora.</p> + +<div class="note"> +<p><strong>Nota:</strong> La clave secreta tiene que ser verdaderamente secreta! Una forma de generar una nueva clave es crear un nuevo proyecto Django (<code>django-admin startproject nombredeproyecto</code>) y obtener la clave generada para tí de su archivo <strong>settings.py</strong>.</p> +</div> + +<p>Establecemos el valor de la variable <code>DJANGO_SECRET_KEY</code> con el comando <code>config:set</code> (como se muestra abajo). Recuerda usar tu propia clave secreta!</p> + +<pre class="brush: bash notranslate">>heroku config:set DJANGO_SECRET_KEY=eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh&= + +Setting DJANGO_SECRET_KEY and restarting locallibrary... done, v7 +DJANGO_SECRET_KEY: eu09(ilk6@4sfdofb=b_2ht@vad*$ehh9-)3u_83+y%(+phh +</pre> + +<p>De forma similar, establecemos <code>DJANGO_DEBUG</code>:</p> + +<pre class="brush: bash notranslate">>heroku config:set <code>DJANGO_DEBUG='' + +Setting DJANGO_DEBUG and restarting locallibrary... done, v8</code></pre> + +<p>Si visitas ahora el sitio recibirás un error "Bad request", porque es <em>obligatorio</em> establecer <a href="https://docs.djangoproject.com/en/1.10/ref/settings/#allowed-hosts">ALLOWED_HOSTS</a> si tienes establecido <code>DEBUG=False</code> (como medida de seguridad). Abre <strong>/locallibrary/settings.py</strong> y cambia el valor de <code>ALLOWED_HOSTS</code> para incluir la url base de tu app (por ejemplo, 'locallibrary1234.herokuapp.com') y la URL que usas normalmente en tu servidor de desarrollo local.</p> + +<pre class="brush: python notranslate">ALLOWED_HOSTS = ['<your app URL without the https:// prefix>.herokuapp.com','127.0.0.1'] +# For example: +# ALLOWED_HOSTS = ['fathomless-scrubland-30645.herokuapp.com','127.0.0.1'] +</pre> + +<p>A continuación guarda los cambios y consolídalos en tu repo Github y en Heroku.</p> + +<pre class="brush: bash notranslate">git add -A +git commit -m 'Update ALLOWED_HOSTS with site and development server URL' +git push origin master +git push heroku master</pre> + +<div class="note"> +<p>Una vez completada la actualización del sitio en Heroku, introduce una URL que no exista (por ejemplo, <strong>/catalog/doesnotexist/</strong>). Antes se habría mostrado una página de depuración detallada, pero ahora deberías simplemente ver una página de "Not Found".</p> +</div> + +<h3 id="Depuración">Depuración</h3> + +<p>El cliente Heroku proporciona algunas herramientas para la depuración:</p> + +<pre class="brush: bash notranslate">heroku logs # Show current logs +heroku logs --tail # Show current logs and keep updating with any new results +heroku config:set DEBUG_COLLECTSTATIC=1 # Add additional logging for collectstatic (this tool is run automatically during a build) +heroku ps #Display dyno status +</pre> + +<p>Si necesitas más información de la que te proporcionan estas herramientas, tendrás que investigar en <a href="https://docs.djangoproject.com/en/1.10/topics/logging/">Django Logging</a>.</p> + +<ul> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>Has llegado al final de este tutorial sobre la instalación de apps Django en producción, así como de la serie de tutoriales sobre el trabajo con Django. Esperamos que los hayas encontrado útiles. Puedes encontrar una versión completa del <a href="https://github.com/mdn/django-locallibrary-tutorial">código fuente en Github aquí</a>.<br> + <br> + El siguiente paso sería leer nuestros últimos artículos, y finalmente completar la evaluación.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/howto/deployment/">Deploying Django</a> (Django docs) + + <ul> + <li><a href="https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/">Deployment checklist</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/howto/static-files/deployment/">Deploying static files</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/">How to deploy with WSGI</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/modwsgi/">How to use Django with Apache and mod_wsgi</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/gunicorn/">How to use Django with Gunicorn</a> (Django docs)</li> + </ul> + </li> + <li>Heroku + <ul> + <li><a href="https://devcenter.heroku.com/articles/django-app-configuration">Configuring Django apps for Heroku</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/getting-started-with-python#introduction">Getting Started on Heroku with Django</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/django-assets">Django and Static Assets</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/python-concurrency-and-database-connections">Concurrency and Database Connections in Django</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/how-heroku-works">How Heroku works</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/dynos">Dynos and the Dyno Manager</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/config-vars">Configuration and Config Vars</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/limits">Limits</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/python-gunicorn">Deploying Python applications with Gunicorn</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/articles/deploying-python">Deploying Python and Django apps on Heroku</a> (Heroku docs)</li> + <li><a href="https://devcenter.heroku.com/search?q=django">Other Heroku Django docs</a></li> + </ul> + </li> + <li>Digital Ocean + <ul> + <li><a href="https://www.digitalocean.com/community/tutorials/how-to-serve-django-applications-with-uwsgi-and-nginx-on-ubuntu-16-04">How To Serve Django Applications with uWSGI and Nginx on Ubuntu 16.04</a></li> + <li><a href="https://www.digitalocean.com/community/tutorials?q=django">Other Digital Ocean Django community docs</a></li> + </ul> + </li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Testing", "Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/development_environment/index.html b/files/es/learn/server-side/django/development_environment/index.html new file mode 100644 index 0000000000..cf47cdefa9 --- /dev/null +++ b/files/es/learn/server-side/django/development_environment/index.html @@ -0,0 +1,421 @@ +--- +title: Puesta en marcha de un entorno de desarrollo Django +slug: Learn/Server-side/Django/development_environment +tags: + - Aprendizaje + - Codificación de scripts + - Entorno de Desarrollo + - Principiante + - Python + - django + - instalación + - introducción +translation_of: Learn/Server-side/Django/development_environment +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}</div> + +<p class="summary">Ahora que sabes para qué se utiliza Django, te enseñaremos cómo configurar y probar un entorno de desarrollo Django en Windows, Linux (Ubuntu), y Mac OS X — cualquiera que sea el sistema operativo común que estés utilizando, este artículo te dará lo que necesitas para ser capaz de empezar a desarrollar aplicaciones Django.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td> + <p>Saber como abrir un terminal / linea de comandos. Saber como instalar paquetes de software en el sistema operativo de tu computadora de desarrollo.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Tener funcionando un entorno de desarrollo Django (1.10) en tu computadora.</td> + </tr> + </tbody> +</table> + +<h2 id="Visión_general_del_entorno_de_desarrollo_Django">Visión general del entorno de desarrollo Django</h2> + +<p>Django hace muy fácil configurar tu computadora de manera que puedas empezar a desarrollar aplicaciones web. Esta sección explica qué consigues con el entorno de desarrollo y proporciona una visión general de algunas de tus opciones de puesta en marcha y configuración. El resto del artículo explica el método <em>recomendado</em> de instalación del entorno de desarrollo de Django en Ubuntu, Mac OS X, y Windows, y cómo puedes probarlo.</p> + +<h3 id="¿Qué_es_el_entorno_de_desarrollo_Django">¿Qué es el entorno de desarrollo Django?</h3> + +<p>El entorno de desarrollo es una instalación de Django en tu computadora local que puedes usar para desarrollar y probar apps Django antes de desplegarlas al entorno de producción.</p> + +<p>Las principales herramientas que el mismo Django proporciona son un conjunto de scripts de Python para crear y trabajar con proyectos Django, junto con un simple <em>servidor web de desarrollo</em> que puedes usar para probar de forma local (es decir en tu computadora, no en un servidor web externo) aplicaciones web Django con el explorador web de tu computadora.</p> + +<p>Hay otras herramientas periféricas, que forman parte del entorno de desarrollo, que no cubriremos aquí. Estas incluyen cosas como un <a href="/en-US/docs/Learn/Common_questions/Available_text_editors">editor de textos</a> o IDE para editar código, una herramienta de gestión del control de fuentes como <a href="https://git-scm.com/">Git</a> para gestionar con seguridad las diferentes versiones de tu código. Asumimos que tienes ya un editor de textos instalado.</p> + +<h3 id="¿Cuáles_son_las_opciones_de_puesta_en_marcha_de_Django">¿Cuáles son las opciones de puesta en marcha de Django?</h3> + +<p>Django es extremadamente flexible en términos de cómo y dónde puede instalarse y configurarse. Django puede ser:</p> + +<ul> + <li>instalado en diferentes sistemas operativos.</li> + <li>ser usado con Python 3 y Python 2.</li> + <li>instalado desde las fuentes, desde el Python Package Index (PyPi) y en muchos casos desde la aplicación de gestión de paquetes de la computadora.</li> + <li>configurado para usar una de entre varias bases de datos, que pueden también necesitar ser instaladas y configuradas por separado.</li> + <li>ejecutarse en el entorno Python del sistema principal o dentro de entornos virtuales Python separados.</li> +</ul> + +<p>Cada una de estas opciones requieren configuraciones y puesta en marcha ligeramente diferentes. Las siguientes subsecciones explican algunas de tus opciones. En el resto del artículo te mostraremos como ajustar Django en un pequeño número de sistemas operativos, y se supondrá ese ajuste a lo largo del resto del módulo.</p> + +<div class="note"> +<p><strong>Nota</strong>: La documentación oficial de Django cubre otras posibles opciones de instalación. Enlazamos a los <a href="#furtherreading">documentos apropiados más abajo</a>.</p> +</div> + +<h4 id="¿Qué_sistemas_operativos_están_soportados">¿Qué sistemas operativos están soportados?</h4> + +<p>Las aplicaciones web Django pueden ejecutarse en casi cualquier máquina donde pueda funcionar el lenguaje de programación Python: Windows, Mac OS X, Linux/Unix, Solaris, por nombrar sólo unos pocos. Casi cualquier computadora debería tener el rendimiento necesario para ejecutar Django durante el desarrollo.</p> + +<p>En este artículo proporcionamos instrucciones para Windows, Mac OS X, y Linux/Unix.</p> + +<h4 id="¿Qué_versión_de_Python_deberías_usar">¿Qué versión de Python deberías usar?</h4> + +<p>Django se ejecuta por encima de Python, y puede uarse tanto con Python 2 o con Python 3 (o ambos). Cuando estés seleccionando una versión deberías tener en cuenta que:</p> + +<ul> + <li>Python 2 es una versión tradicional del lenguaje que no va a tener más características nuevas pero que tiene disponible para los desarrolladores, un enorme repositorio de bibliotecas de terceros de alta calidad (algunas de las cuales no están disponibles en Python 3).</li> + <li>Python 3 es una actualización de Python 2 que, aunque similar, es más consistente y fácil de usar. Python 3 también es el futuro de Python, y continúa su evolución.</li> + <li>También es posible soportar ambas versiones usando bibliotecas (ej. <a href="http://pythonhosted.org/six/">six</a>), aunque no sin un esfuerzo adicional de desarrollo.</li> +</ul> + +<ul> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Historicamente Python 2 era la única elección realista, porque muy pocas bibliotecas de terceros estaban disponibles para Python 3. La tendencia actual es que la mayoría de paquetes nuevos y populares del <a href="https://pypi.python.org/pypi">Python Package Index</a> (PyPi) soporten ambas versiones de Python. Aunque todavía haya muchos paquetes que sólo están disponibles para Python 2, elegir Python 3 es actualmente una opción muy popular.</p> +</div> + +<p>Te recomendamos que uses la última versión de Python 3 a menos que el sitio dependa de bibliotecas de terceros que sólo están disponibles para Python 2.</p> + +<p>Este artículo te explicará como instalar un entorno para Python 3 (el ajuste equivalente para Python 2 sería muy similar).</p> + +<h4 id="¿Dónde_puedo_descagarme_Django">¿Dónde puedo descagarme Django?</h4> + +<p>Hay tres lugares para descargar Django:</p> + +<ul> + <li>El Python Package Repository (PyPi), usando la herramienta <em>pip</em>. Este es el mejor modo de obtener la última veersión estable de Django.</li> + <li>Usar una versión del gestor de paquetes de tu computadora. Las distribuciones de Django que se empaquetan con los sistemas operativos ofrecen un mecanismo de instalación ya familiar. Ten en cuenta sin embargo que la versión empaquetada puede ser bastante antigua, y sólo puede ser instalada en el entorno de Python del sistema (que puede no ser el que tu quieras).</li> + <li>Instalar desde la fuente. Puedes obtener y descargar la versión con el último grito de Python partiendo de las fuentes. Esto no es lo recomendable para principiantes, pero es necesario cuando estás listo para empezar a contribuir codificando el propio Django.</li> +</ul> + +<p>Este artículo te muestra como instalar Django desde PyPi, para conseguir la última versión estable.</p> + +<h4 id="¿Qué_base_de_datos">¿Qué base de datos?</h4> + +<p>Django soporta cuatro bases de datos importantes (PostgreSQL, MySQL, Oracle y SQLite), y hay bibliotecas comunitarias que proporcionan varios niveles de soporte para otras bases de datos populares SQL y NOSQL. Te recomendamos que elijas la misma base de datos tanto para la producción como para el desarrollo (aunque Django abstrae muchas de las diferencias entre las bases usando su Object-Relational Mapper (ORM), hay todavía <a href="https://docs.djangoproject.com/en/1.10/ref/databases/">problemas potenciales</a> que es mejor evitar).</p> + +<p>Durante este artículo (y la mayoría de este módulo) usaremos la base de datos <em>SQLite</em>, que almacena sus datos en un fichero. SQLite está pensado para ser usado como base ligera y no puede soportar un alto nivel de concurrencia. Es sin embargo una excelente elección para aplicaciones que son principalmente de sólo lectura.</p> + +<div class="note"> +<p><strong>Nota</strong>: Django está configurado para usar SQLite por defecto cuando comienzas tu proyecto de sitio web usando las herramientas estándard (<em>django-admin</em>). Es una gran elección cuando estás empezando porque no requiere configuración o puesta en marcha adicional. </p> +</div> + +<h4 id="¿Instalar_Python_en_un_entorno_de_sistema_o_virtual">¿Instalar Python en un entorno de sistema o virtual?</h4> + +<p>Cuando instalas Python3 obtienes un único entorno global que es compartido con todo el código Python3. Si bien puedes instalar los paquetes que te gusten en el entorno, sólo puedes instalar al mismo tiempo una versión en particular de cada paquete.</p> + +<div class="note"> +<p><strong>Nota</strong>: Las aplicaciones Python instaladas en el entorno global pueden entrar en conflicto potencialmente unas con otras (ej. si dependen de diferentes versiones del mismo paquete). </p> +</div> + +<p>Si instalas Django dentro del entorno por defecto/global sólo podrás apuntar a una sóla versión de Django en la computadora. Esto puede ser un problema si quieres crear nuevos sitios (usando la última versión de Django) pero manteniendo los sitios web que dependen de versiones más antiguas.</p> + +<div class="note"></div> + +<p>Como resultado, los desarrolladores experimentados de Python/Django normalmente ejecutan las aplicaciones Python dentro de <em>entornos virtuales Python</em> independientes. De esta forma se habilitan múltiples entornos Django diferentes en la misma computadora. !El mismo equipo de desarrollo Django recomienda que uses entornos Python virtuales!</p> + +<div class="note"></div> + +<p>Este módulo da por supuesto que has instalado Django en un entorno virtual, y te mostraremos cómo hacerlo más abajo.</p> + +<h2 id="Instalación_de_Python_3">Instalación de Python 3</h2> + +<p>Para poder usar Django tendrás que instalar Python en tu sistema operativo. Si estás usando <em>Python 3</em> necesitarás la herramienta <a href="https://pypi.python.org/pypi">Python Package Index</a> — <em>pip3</em> — que se usa para gestionar (instalar, actualizar y eliminar) los paquetes/bibliotecas Python usados por Django y tus otras aplicaciones Python.</p> + +<p>Esta sección explica brevemente como puedes comprobar qué versiones de Python están presentes, e instalar nuevas versiones cuando lo necesites, en Ubuntu Linux 16.04, Mac OS X, y Windows 10.</p> + +<div class="note"> +<p><strong>Nota</strong>: Dependiendo de tu plataforma, podrías también ser capaz de instalar Python/pip desde la propia aplicación de gestión de paquetes de tu sistema o vía otros mecanismos. Para la mayoría de las plataformas puedes descargar los ficheros de instalación requeridos desde <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a> e instalarlos usando el método apropiado específico de la plataforma.</p> +</div> + +<h3 id="Ubuntu_16.04">Ubuntu 16.04</h3> + +<p>Ubuntu Linux incluye Python 3 por defecto. Puedes confirmarlo ejecutando el siguiente comando en una terminal:</p> + +<pre class="brush: bash"><span style="line-height: 1.5;">python3 -V + Python 3.5.2</span></pre> + +<p>Sin embargo la herramienta Python Package Index que necesitarás para instalar paquetes de Python 3 (incluido Django) <strong>No</strong> está disponible por defecto. Puedes instalar pip3 en un terminal bash usando:</p> + +<pre class="brush: bash">sudo apt-get install python3-pip +</pre> + +<h3 id="Mac_OS_X">Mac OS X</h3> + +<p>Mac OS X "El Capitan" no incluye Python 3. Puedes confirmarlo ejecutando los siguientes comandos en un terminal bash:</p> + +<pre class="brush: bash"><span style="line-height: 1.5;">python3 -V + </span>-bash: python3: command not found</pre> + +<p>Puedes instalar fácilmente Python 3 (junto con la herramienta <em>pip3</em>) desde <a href="https://www.python.org/">python.org</a>:</p> + +<ol> + <li>Descarga el instalador requerido: + <ol> + <li>Vete a <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a></li> + <li>Selecciona el botón <strong>Descarga Python 3.5.2</strong> (el número exacto de versión menor puede ser diferente).</li> + </ol> + </li> + <li>Localiza el fichero usando <em>Finder</em>, haz doble-click sobre el fichero del paquete. Pincha siguiente en las ventanas de instalación.</li> +</ol> + +<p>Puedes confirmar ahora una instalación satisfactoria comprobando <em>Python 3</em> como se muestra a continuación:</p> + +<pre class="brush: bash"><span style="line-height: 1.5;">python3 -V + Python 3.5.2</span>0 +</pre> + +<p>Puedes igualmente comprobar que <em>pip3</em> está instalado listando los paquetes disponibles:</p> + +<pre class="brush: bash">pip3 list</pre> + +<h3 id="Windows_10">Windows 10</h3> + +<p>Windows no incluye Python por defecto, pero puedes instalarlo fácilmente (junto con la herramienta <em>pip3</em>) desde <a href="https://www.python.org/">python.org</a>:</p> + +<ol> + <li>Descarga el instalador requerido: + <ol> + <li>Vete a <a href="https://www.python.org/downloads/">https://www.python.org/downloads/</a></li> + <li>Selecciona el botón de <strong>Descarga Python 3.6.3</strong> (la versión menor exacta puede ser diferente).</li> + </ol> + </li> + <li>Instala Python haciendo doble-click en el fichero descargado y pulsando siguiente en las ventanas de instalación</li> +</ol> + +<p>Puedes verificar a continuación que Python 3 se instaló correctamente entrando el siguiente texto en una ventana de comandos:</p> + +<pre class="brush: bash"><span style="line-height: 1.5;">py -3 -V + Python 3.6.3</span> +</pre> + +<p>El instalador de Windows incorpora <em>pip3</em> (el gestor de paquetes de Python) por defecto. Puedes listar paquetes como se muestra a continuación:</p> + +<pre class="brush: bash"><span style="line-height: 1.5;">pip3 list</span> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: El instalador debería poner en marcha todo lo que necesitas para que el comando de arriba funcione. Si por el contrario obtienes un mensaje de que Python no puede ser encontrado, puede que necesites añadirlo al path de tu sistema.</p> +</div> + +<h2 id="Uso_de_Django_dentro_de_un_entorno_virtual_de_Python">Uso de Django dentro de un entorno virtual de Python</h2> + +<p>Las bibliotecas que usaremos para crear nuestros entornos virtuales están en <a href="https://virtualenvwrapper.readthedocs.io/en/latest/index.html">virtualenvwrapper</a> (Linux and Mac OS X) y <a href="https://pypi.python.org/pypi/virtualenvwrapper-win">virtualenvwrapper-win</a> (Windows), que utilizan a su vez la herramienta <a href="https://developer.mozilla.org/en-US/docs/Python/Virtualenv">virtualenv</a>. Las herramientas wrapper crean una interfaz consistente para la gestión de interfaces en todas las plataformas.</p> + +<h3 id="Instalación_del_software_del_entorno_virtual">Instalación del software del entorno virtual</h3> + +<h4 id="Puesta_en_marcha_del_entorno_virtual_en_Ubuntu">Puesta en marcha del entorno virtual en Ubuntu</h4> + +<p>Después de instalar Python y pip puedes instalar <em>virtualenvwrapper</em> (que incluye <em>virtualenv</em>) usando <em>pip3</em> como se muestra.</p> + +<pre><code>sudo pip3 install virtualenvwrapper</code></pre> + +<p>A continuación añade las siguientes líneas al final del fichero de inicio de tu shell (éste es un fichero oculto llamado <strong>.bashrc</strong> que se encuentra en tu directorio de inicio del usuario). Ésto ajusta la localización de donde deberían vivir los entornos virtuales, la localización de los directorios de tus proyectos de desarrollo, y la localización del script instalado con este paquete:</p> + +<pre><code>export WORKON_HOME=$HOME/.virtualenvs +export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 +export PROJECT_HOME=$HOME/Devel +source /usr/local/bin/virtualenvwrapper.sh</code></pre> + +<p>A continuación volver a recargar el fichero de inicio ejecutando el siguiente comando en el terminal:</p> + +<pre><code>source ~/.bashrc</code></pre> + +<p>En este punto deberías ver un puñado de scripts empezando a ejecutarse como se muestra a continuación:</p> + +<pre><code>virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/premkproject +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/postmkproject +... +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/preactivate +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/postactivate +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/get_env_details</code></pre> + +<p>Ahora puedes crear un nuevo entorno virtual con el comando <code>mkvirtualenv</code>.</p> + +<h4 id="Puesta_en_marcha_del_entorno_virtual_en_Mac_OS_X">Puesta en marcha del entorno virtual en Mac OS X</h4> + +<p>El ajuste de virtualenvwrapper en Mac OS X es casi idéntico a como es en Ubuntu. </p> + +<p>Instalar <em>virtualenvwrapper</em> (y <em>virtualenv</em> incluido en el paquete) usando <em>pip</em> como se muestra a continuación.</p> + +<pre><code>sudo pip3 install virtualenvwrapper</code></pre> + +<p>A continuación añadir las siguientes líneas al final del fichero de inicio de tu shell. Son las mismas líneas que para Ubuntu, pero el fichero de inicio se llama de forma diferente <strong>.bash_profile</strong> y está oculto en tu directorio de inicio.</p> + +<pre><code>export WORKON_HOME=$HOME/.virtualenvs +export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3 +export PROJECT_HOME=$HOME/Devel +source /usr/local/bin/virtualenvwrapper.sh</code></pre> + +<p><strong>Nota</strong>: Si no puedes encontrar <strong>.bash-profile</strong> para editar en el finder, puedes también abrirlo usando nano.</p> + +<p>Los comandos parecen algo como lo siguiente.</p> + +<pre><code>cd ~ # Navegar a mi directorio de inicio +ls -la # Listar el contenido del directorio. Deberias ver .bash_profile +nano .bash_profile # Abrir el fichero en el editor de texto nano, en el terminal +# Avanzar hast el final del fichero, y copiar y pegar las lineas de arrriba +# Usar Ctrl+X para salir de nano, Elegir Y para guardar el fichero.</code></pre> + +<p>A continuación recargar el fichero de inicio realizando la siguiente llamada en el terminal:</p> + +<pre><code>source ~/.bash_profile</code></pre> + +<p>En este punto deberías ver un puñado de scripts empezando a ejecutarse (los mismos scripts que para la instalación en Ubuntu). Deberías ser ahora capaz de crear un nuevo entorno virtual con el comado <code>mkvirtualenv</code>.</p> + +<h4 id="Puesta_en_marcha_del_entorno_virtual_en_Windows_10">Puesta en marcha del entorno virtual en Windows 10</h4> + +<p>Instalar <a href="https://pypi.python.org/pypi/virtualenvwrapper-win">virtualenvwrapper-win</a> es incluso más simple que poner en marcha <em>virtualenvwrapper</em> porque no necesitas configurar donde almacena la herramienta la información del entorno (hay un valor por defecto). Todo lo que necesitas hacer es ejecutar el siguiente comando en la consola de comandos en línea:</p> + +<pre><code>pip3 install virtualenvwrapper-win</code></pre> + +<p>Y a continuación ya puedes crear un nuevo entorno virtual con <code>mkvirtualenv</code></p> + +<h3 id="Creación_de_un_entorno_virtual">Creación de un entorno virtual</h3> + +<p>Una vez que hayas instalado <em>virtualenvwrapper</em> o <em>virtualenvwrapper-win</em> trabajar con entornos virtuales es muy similar en todas las plataformas.</p> + +<p>Ahora puedes crear un nuevo entorno virtual con el comando <code>mkvirtualenv</code>. A medida que se ejecuta este comando verás que se va poniendo en marcha el entorno (lo que verás es ligeramente específico de la plataforma). Cuando se completa el comando el nuevo entorno virtual estará activo — podrás comprobarlo porque el comienzo del prompt será el nombre del entorno entre paréntesis (como se muestra abajo).</p> + +<pre><code>$ mkvirtualenv my_django_environment + +Running virtualenv with interpreter /usr/bin/python3 +... +virtualenvwrapper.user_scripts creating /home/ubuntu/.virtualenvs/t_env7/bin/get_env_details +(my_django_environment) ubuntu@ubuntu:~$</code> +</pre> + +<p>Una vez que estás dentro del entorno virutal puedes instalar Django e iniciar el desarrollo.</p> + +<div class="note"> +<p><strong>Nota</strong>: De ahora en adelante en este artículo (y por ende en el módulo) asume por favor que todos los comandos se ejecutan en un entorno virtual Python como el que acabamos de poner en marcha arriba.</p> +</div> + +<h3 id="Uso_de_un_entorno_virtual">Uso de un entorno virtual</h3> + +<p>Hay sólo otros pocos comandos útiles que deberías conocer (hay más en la documentación de la herramienta, pero éstos son los que usarás de forma habitual:</p> + +<ul> + <li><code>deactivate</code> — Salir del entorno virutal Python actual</li> + <li><code>workon</code> — Listar los entornos virtuales disponibles</li> + <li><code>workon name_of_environment</code> — Activar el entorno virtual Python especificado</li> + <li><code>rmvirtualenv name_of_environment</code> — Borrar el entorno especificado.</li> +</ul> + + + +<h2 id="Instalación_de_Django">Instalación de Django</h2> + +<p>Una vez que has creado el entorno virtual, y realizado la llamada <code>workon</code> para entrar en él, puedes usar <em>pip3 </em>para instalar Django. </p> + +<pre class="brush: bash">pip3 install django +</pre> + +<p>Puedes comprobar que está instalado Django ejecutando el siguiente comando (esto sólo comprueba que Python puede encontrar el módulo Django):</p> + +<pre class="brush: bash"># Linux/Mac OS X +python3 -m django --version + 1.11.7 + +# Windows +py -3 -m django --version + 1.11.7 +</pre> + +<div class="note"> +<p><strong>Nota</strong>: En Windows se lanzan scripts <em>Python 3</em> añadiendo como prefijo del comando con <code>py -3</code>, mientras que en Linux/Mac OSX, el comando es <code>python3</code>.</p> +</div> + +<div class="warning"> +<p><strong>Importante</strong>: El resto de este <strong>modulo </strong>usa, para invocar Python 3, el comando <em>Linux</em> (<code>python3</code>) . Si estás trabajando en <em>Windows </em>simplemente reemplazar este prefijo con: <code>py -3</code></p> +</div> + +<h2 id="Comprobación_de_tu_instalación">Comprobación de tu instalación</h2> + +<p>La prueba de arriba funciona, pero no es muy divertida. Una comprobación más interesante es crear un esqueleto de proyecto y ver si funciona. Para hacer ésto, navega primero en tu consola de comandos/terminal a donde quieras almacenar tus aplicaciones Django. Crea una carpeta para la comprobación de tu sitio y navega a ella.</p> + +<pre class="brush: bash">mkdir django_test +cd django_test +</pre> + +<p>Puedes crear a continuación un nuevo esqueleto de sitio llamado "<em>mytestsite</em>" usando la herramienta <strong>django-admin</strong> como se muestra a continuación. Después de crear el sitio puedes navegar a la carpeta donde encontrarás el script principal para la gestión de proyectos, llamado <strong>manage.py</strong>.</p> + +<pre class="brush: bash">django-admin startproject mytestsite +cd mytestsite</pre> + +<p>Podemos arrancar el <em>servidor web de desarrollo</em> desde esta carpeta usando <strong>manage.py</strong> y el comando <code>runserver</code>, como se muestra.</p> + +<pre class="brush: bash">$ <strong>python3 manage.py runserver </strong> +Performing system checks... + +System check identified no issues (0 silenced). + +You have 13 unapplied migration(s). Your project may not work properly until you apply the migrations for app(s): admin, auth, contenttypes, sessions. +Run 'python manage.py migrate' to apply them. + +September 19, 2016 - 23:31:14 +Django version 1.10.1, using settings 'mysite.settings' +Starting development server at http://127.0.0.1:8000/ +Quit the server with CONTROL-C. +</pre> + +<div class="note"> +<p><strong>Nota</strong>: El comando anterior muestra el comando Linux/Mac OS X. En este punto ¡puedes ignorar las advertencias sobre "13 unapplied migration(s)"!</p> +</div> + +<p>Una vez que tengas funcionando el servidor puedes ver el sitio navegando a la siguiente URL en tu explorador web local : <code>http://127.0.0.1:8000/</code>. Deberías ver un sitio parecido a este:</p> + +<p><img alt="The home page of the skeleton Django app." src="https://mdn.mozillademos.org/files/13893/Django_Skeleton_Website_Homepage.png" style="border-style: solid; border-width: 1px; display: block; height: 544px; margin: 0px auto; width: 865px;"></p> + +<ul> +</ul> + +<h2 id="Sumario">Sumario</h2> + +<p>Ahora tienes levantado y funcionando en tu computadora tu entorno de desarrollo Django .</p> + +<p>En la sección de pruebas viste brevemente cómo crear un nuevo sitio web Django usando <code>django-admin startproject</code>, y hacerlo funcionar en tu explorador usando el servidor web de desarrollo (<code><strong>python3 manage.py runserver</strong></code>).</p> + +<p>En el siguiente artículo expandimos este proceso, construyendo una aplicación web simple pero completa.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/es/2.0/intro/install/">Guía de instalación rápida</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/es/2.0/topics/install/">Cómo instalar Django — Guía Completa</a> (Django docs) - incluye información sobre cómo borrar Django</li> + <li><a href="https://docs.djangoproject.com/es/2.0/howto/windows/">Cómo instalar Django en Windows</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Introduction", "Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/django_assessment_blog/index.html b/files/es/learn/server-side/django/django_assessment_blog/index.html new file mode 100644 index 0000000000..cb5ac7ad88 --- /dev/null +++ b/files/es/learn/server-side/django/django_assessment_blog/index.html @@ -0,0 +1,307 @@ +--- +title: 'Evaluación: DIY Django mini blog' +slug: Learn/Server-side/Django/django_assessment_blog +translation_of: Learn/Server-side/Django/django_assessment_blog +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}</div> + +<p class="summary">En esta evaluación usarás el conocimiento de Django que has adquirido en el módulo <a href="/es/docs/Learn/Server-side/Django" style="font-size: 1.25rem;">Framework Web Django (Python)</a> para crear un blog muy básico<span style="font-size: 1.25rem;">.</span></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos Previos:</th> + <td>Before attempting this assessment you should have already worked through all the articles in this module.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender los fundamentos de Django , incluidos las configuraciones de URL , modelos, vistas, formularios y templates.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen_del_proyecto">Resumen del proyecto</h2> + +<p>Las paginas que necesitan ser mostradas, sus URLs, y otros requisitos son listados debajo: </p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Pagina</th> + <th scope="col">URL</th> + <th scope="col">Requisitos</th> + </tr> + </thead> + <tbody> + <tr> + <td>Home page</td> + <td><code>/</code> and <code>/blog/</code></td> + <td>Una pagina inicial que describa el sitio</td> + </tr> + <tr> + <td>Lista de todos las publicaciones del blog</td> + <td><code>/blog/blogs/</code></td> + <td> + <p>Lista de todos las publicaciones del blog:</p> + + <ul> + <li>Accessible to all users from a sidebar link.</li> + <li>List sorted by post date (newest to oldest).</li> + <li>List paginated in groups of 5 articles.</li> + <li>List items display the blog title, post date, and author.</li> + <li>Blog post names are linked to blog detail pages.</li> + <li>Blogger (author names) are linked to blog author detail pages.</li> + </ul> + </td> + </tr> + <tr> + <td>Blog autor (blogger) pagina de detalles</td> + <td><code>/blog/blogger/<em><author-id></em></code></td> + <td> + <p>Information for a specified author (by id) and list of their blog posts:</p> + + <ul> + <li>Accessible to all users from author links in blog posts etc.</li> + <li>Contains some biographical information about the blogger/author.</li> + <li>List sorted by post date (newest to oldest).</li> + <li>Not paginated.</li> + <li>List items display just the blog post name and post date.</li> + <li>Blog post names are linked to blog detail pages.</li> + </ul> + </td> + </tr> + <tr> + <td>Blog post detail page</td> + <td><code>/blog/<em><blog-id></em></code></td> + <td> + <p>Blog post details.</p> + + <ul> + <li>Accessible to all users from blog post lists.</li> + <li>Page contains the blog post: name, author, post date, and content.</li> + <li>Comments for the blog post should be displayed at bottom.</li> + <li>Comments should be sorted in order: oldest to most recent.</li> + <li>Contains link to add comments at end for logged in users (see Comment form page)</li> + <li>Blog posts and comments need only display plain text. There is no need to support any sort of HTML markup (e.g. links, images, bold/italic, etc).</li> + </ul> + </td> + </tr> + <tr> + <td>List of all bloggers</td> + <td><code>/blog/bloggers/</code></td> + <td> + <p>List of bloggers on system:</p> + + <ul> + <li>Accessible to all users from site sidebar</li> + <li>Blogger names are linked to Blog author detail pages.</li> + </ul> + </td> + </tr> + <tr> + <td>Comment form page</td> + <td><code>/blog/<em><blog-id></em>/create</code></td> + <td> + <p>Create comment for blog post:</p> + + <ul> + <li>Accessible to logged-in users (only) from link at bottom of blog post detail pages.</li> + <li>Displays form with description for entering comments (post date and blog is not editable).</li> + <li>After a comment has been posted, the page will redirect back to the associated blog post page.</li> + <li>Users cannot edit or delete their posts.</li> + <li>Logged out users will be directed to the login page to log in, before they can add comments. After logging in, they will be redirected back to the blog page they wanted to comment on.</li> + <li>Comment pages should include the name/link to the blogpost being commented on.</li> + </ul> + </td> + </tr> + <tr> + <td>User authentication pages</td> + <td><code>/accounts/<em><standard urls></em></code></td> + <td> + <p>Standard Django authentication pages for logging in, out and setting the password:</p> + + <ul> + <li>Login/out should be accessible via sidebar links.</li> + </ul> + </td> + </tr> + <tr> + <td>Admin site</td> + <td><code>/admin/<em><standard urls></em></code></td> + <td> + <p>Admin site should be enabled to allow create/edit/delete of blog posts, blog authors and blog comments (this is the mechanism for bloggers to create new blog posts):</p> + + <ul> + <li>Admin site blog posts records should display the list of associated comments inline (below each blog post).</li> + <li>Comment names in the Admin site are created by truncating the comment description to 75 characters.</li> + <li>Other types of records can use basic registration.</li> + </ul> + </td> + </tr> + </tbody> +</table> + +<p>In addition you should write some basic tests to verify:</p> + +<ul> + <li>All model fields have the correct label and length.</li> + <li>All models have the expected object name (e.g.<code> __str__()</code> returns the expected value).</li> + <li>Models have the expected URL for individual Blog and Comment records (e.g. <code>get_absolute_url()</code> returns the expected URL).</li> + <li>The BlogListView (all-blog page) is accessible at the expected location (e.g. /blog/blogs)</li> + <li>The BlogListView (all-blog page) is accessible at the expected named url (e.g. 'blogs')</li> + <li>The BlogListView (all-blog page) uses the expected template (e.g. the default)</li> + <li>The BlogListView paginates records by 5 (at least on the first page)</li> +</ul> + +<div class="note"> +<p><strong>Note</strong>: There are of course many other tests you can run. Use your discretion, but we'll expect you to do at least the tests above.</p> +</div> + +<p>The following section shows <a href="#Screenshots">screenshots</a> of a site that implements the requirements above.</p> + +<h2 id="Screenshots">Screenshots</h2> + +<p>The following screenshot provide an example of what the finished program should output.</p> + +<h3 id="List_of_all_blog_posts">List of all blog posts</h3> + +<p>This displays the list of all blog posts (accessible from the "All blogs" link in the sidebar). Things to note:</p> + +<ul> + <li>The sidebar also lists the logged in user.</li> + <li>Individual blog posts and bloggers are accessible as links in the page.</li> + <li>Pagination is enabled (in groups of 5)</li> + <li>Ordering is newest to oldest.</li> +</ul> + +<p><img alt="List of all blogs" src="https://mdn.mozillademos.org/files/14319/diyblog_allblogs.png" style="border-style: solid; border-width: 1px; display: block; height: 363px; margin: 0px auto; width: 986px;"></p> + +<h3 id="List_of_all_bloggers">List of all bloggers</h3> + +<p>This provides links to all bloggers, as linked from the "All bloggers" link in the sidebar. In this case we can see from the sidebar that no user is logged in.</p> + +<p><img alt="List of all bloggers" src="https://mdn.mozillademos.org/files/14321/diyblog_blog_allbloggers.png" style="border-style: solid; border-width: 1px; display: block; height: 256px; margin: 0px auto; width: 493px;"></p> + +<h3 id="Blog_detail_page">Blog detail page</h3> + +<p>This shows the detail page for a particular blog.</p> + +<p><img alt="Blog detail with add comment link" src="https://mdn.mozillademos.org/files/14323/diyblog_blog_detail_add_comment.png" style="border-style: solid; border-width: 1px; display: block; height: 640px; margin: 0px auto; width: 986px;"></p> + +<p>Note that the comments have a date <em>and</em> time, and are ordered from oldest to newest (opposite of blog ordering). At the end we have a link for accessing the form to add a new comment. If a user is not logged in we'd instead see a suggestion to log in.</p> + +<p><img alt="Comment link when not logged in" src="https://mdn.mozillademos.org/files/14325/diyblog_blog_detail_not_logged_in.png" style="border-style: solid; border-width: 1px; display: block; height: 129px; margin: 0px auto; width: 646px;"></p> + +<h3 id="Add_comment_form">Add comment form</h3> + +<p>This is the form to add comments. Note that we're logged in. When this succeeds we should be taken back to the associated blog post page.</p> + +<p><img alt="Add comment form" src="https://mdn.mozillademos.org/files/14329/diyblog_comment_form.png" style="border-style: solid; border-width: 1px; display: block; height: 385px; margin: 0px auto; width: 778px;"></p> + +<h3 id="Author_bio">Author bio</h3> + +<p>This displays bio information for a blogger along with their blog posts list.</p> + +<p><img alt="Blogger detail page" src="https://mdn.mozillademos.org/files/14327/diyblog_blogger_detail.png" style="border-style: solid; border-width: 1px; display: block; height: 379px; margin: 0px auto; width: 982px;"></p> + +<h2 id="Steps_to_complete">Steps to complete</h2> + +<p>The following sections describe what you need to do.</p> + +<ol> + <li>Create a skeleton project and web application for the site (as described in <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">Django Tutorial Part 2: Creating a skeleton website</a>). You might use 'diyblog' for the project name and 'blog' for the application name.</li> + <li>Create models for the Blog posts, Comments, and any other objects needed. When thinking about your design, remember: + <ul> + <li>Each comment will have only one blog, but a blog may have many comments.</li> + <li>Blog posts and comments must be sorted by post date.</li> + <li>Not every user will necessarily be a blog author though any user may be a commenter.</li> + <li>Blog authors must also include bio information.</li> + </ul> + </li> + <li>Run migrations for your new models and create a superuser.</li> + <li>Use the admin site to create some example blog posts and blog comments.</li> + <li>Create views, templates, and URL configurations for blog post and blogger list pages.</li> + <li>Create views, templates, and URL configurations for blog post and blogger detail pages.</li> + <li>Create a page with a form for adding new comments (remember to make this only available to logged in users!)</li> +</ol> + +<h2 id="Hints_and_tips">Hints and tips</h2> + +<p>This project is very similar to the <a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a> tutorial. You will be able to set up the skeleton, user login/logout behaviour, support for static files, views, URLs, forms, base templates and admin site configuration using almost all the same approaches.</p> + +<p>Some general hints:</p> + +<ol> + <li>The index page can be implemented as a basic function view and template (just like for the locallibrary).</li> + <li>The list view for blog posts and bloggers, and the detail view for blog posts can be created using the <a href="/en-US/docs/Learn/Server-side/Django/Generic_views">generic list and detail views</a>.</li> + <li>The list of blog posts for a particular author can be created by using a generic list Blog list view and filtering for blog object that match the specified author. + <ul> + <li>You will have to implement <code>get_queryset(self)</code> to do the filtering (much like in our library class <code>LoanedBooksAllListView</code>) and get the author information from the URL.</li> + <li>You will also need to pass the name of the author to the page in the context. To do this in a class-based view you need to implement <code>get_context_data()</code> (discussed below).</li> + </ul> + </li> + <li>The <em>add comment</em> form can be created using a function-based view (and associated model and form) or using a generic <code>CreateView</code>. If you use a <code>CreateView</code> (recommended) then: + <ul> + <li>You will also need to pass the name of the blog post to the comment page in the context (implement <code>get_context_data()</code> as discussed below).</li> + <li>The form should only display the comment "description" for user entry (date and associated blog post should not be editable). Since they won't be in the form itself, your code will need to set the comment's author in the<code> form_valid()</code> function so it can be saved into the model (<a href="https://docs.djangoproject.com/en/1.10/topics/class-based-views/generic-editing/#models-and-request-user">as described here</a> — Django docs). In that same function we set the associated blog. A possible implementation is shown below (<code>pk</code> is a blog id passed in from the URL/URL configuration). + <pre class="brush: python"> def form_valid(self, form): + """ + Add author and associated blog to form data before setting it as valid (so it is saved to model) + """ + #Add logged-in user as author of comment + form.instance.author = self.request.user + #Associate comment with blog based on passed id + form.instance.blog=get_object_or_404(Blog, pk = self.kwargs['pk']) + # Call super-class form validation behaviour + return super(BlogCommentCreate, self).form_valid(form) +</pre> + </li> + <li>You will need to provide a success URL to redirect to after the form validates; this should be the original blog. To do this you will need to override <code>get_success_url()</code> and "reverse" the URL for the original blog. You can get the required blog ID using the <code>self.kwargs</code> attribute, as shown in the <code>form_valid()</code> method above.</li> + </ul> + </li> +</ol> + +<p>We briefly talked about passing a context to the template in a class-based view in the <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Generic_views#Overriding_methods_in_class-based_views">Django Tutorial Part 6: Generic list and detail views</a> topic. To do this you need to override <code>get_queryset()</code> (first getting the existing context, updating it with whatever additional variables you want to pass to the template, and then returning the updated context. For example, the code fragment below shows how you can add a blogger object to the context based on their <code>BlogAuthor</code> id.</p> + +<pre class="brush: python">class SomeView(generic.ListView): + ... + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(SomeView, self).get_context_data(**kwargs) + # Get the blogger object from the "pk" URL parameter and add it to the context + context['blogger'] = get_object_or_404(BlogAuthor, pk = self.kwargs['pk']) + return context +</pre> + +<h2 id="Assessment">Assessment</h2> + +<p>The assessment for this task is <a href="https://github.com/mdn/django-diy-blog/blob/master/MarkingGuide.md">available on Github here</a>. This assessment is primarily based on how well your application meets the requirements we listed above, though there are some parts of the assessment that check your code uses appropriate models, and that you have written at least some test code. When you're done, you can check out our <a href="https://github.com/mdn/django-diy-blog">the finished example</a> which reflects a "full marks" project.</p> + +<p>Once you've completed this module you've also finished all the MDN content for learning basic Django server-side website programming! We hope you enjoyed this module and feel you have a good grasp of the basics!</p> + +<p>{{PreviousMenu("Learn/Server-side/Django/web_application_security", "Learn/Server-side/Django")}}</p> + +<p> </p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/forms/index.html b/files/es/learn/server-side/django/forms/index.html new file mode 100644 index 0000000000..4160e537b6 --- /dev/null +++ b/files/es/learn/server-side/django/forms/index.html @@ -0,0 +1,661 @@ +--- +title: 'Tutorial de Django Parte 9: Trabajo con formularios' +slug: Learn/Server-side/Django/Forms +translation_of: Learn/Server-side/Django/Forms +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/authentication", "Learn/Server-side/Django/Testing", "Learn/Server-side/Django")}}</div> + +<p class="summary">En este tutorial te mostraremos cómo trabajar con Formularios HTML en Django, y en particular, la forma más fácil de escribir formularios para crear, actualizar y borrar instancias de modelo. Como parte de esta demostración extenderemos el sitio web <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a> de manera que los bibliotecarios puedan renovar libros, y crear, actualizar y borrar autores utilizando nuestros propios formularios (en vez de utilizar la aplicación de administración).</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td>Completar todos los temas de tutoriales anteriores, incluyendo <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions">Tutorial Django Parte 8: Autenticación y permisos de usuarios</a>.</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Comprender como escribir formularios para obtener informacion de los usuarios y actualizar la base de datos. Comprender cómo las vistas de edición basadas en clase genérica pueden simplificar enormemente la creación de formularios trabajando con un solo modelo.</td> + </tr> + </tbody> +</table> + +<h2 id="Visión_General">Visión General</h2> + +<p>Un <a href="/en-US/docs/Web/Guide/HTML/Forms">Formulario HTML </a>es un conjunto de uno o más campos/widgets en una página web, que pueden ser usados para recolectar información de los usuarios para el envío a un servidor. Los formularios son un mecanismo flexible para recolectar datos de entrada porque <span id="result_box" lang="es"><span>son widgets adecuados para ingresar diferentes tipos de datos, incluyendo campos de texto, checkboxes, radio buttons, selector de fechas, etc. Los formularios son también una forma relativamente segura de compartir datos con el servidor, ya que permiten enviar información en peticiones </span></span><code>POST</code> <span class="short_text" id="result_box" lang="es"><span>con protección de falsificación de solicitud entre sitios.</span></span></p> + +<p>Si bien nosotros aún no hemos creado ningún formulario en este tutorial todavia, ya lo hemos encontrado en el sitio de administración de Django; por ejemplo, la captura de pantalla de abajo muestra un formulario para editar uno de nuestros modelos de <a href="/en-US/docs/Learn/Server-side/Django/Models">Libro</a>, compuesto de un número de listas de selección y editores de texto.</p> + +<p><img alt="Admin Site - Book Add" src="https://mdn.mozillademos.org/files/13979/admin_book_add.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<p>Trabajar con formularios puede ser complicado! Los desarrolladores deben de escribir código HTML para el formulario, validar y adecuadamente limpiar los datos ingresados en el servidor (y posiblemente también en el browser o navegador), volver a publicar el formulario con mensajes de error para informar a los usuarios de cualquier campo invalido, manejar los datos cuando hayan sido enviados exitosamente y finalmente, responder al usuario de alguna manera, para indicar el éxito de la operación. Django Forms elimina mucho del trabajo de todos estos pasos, al proporcionar un marco de trabajo que le permite definir formularios y sus campos a travéz de programación y luego, utilizar estos objetos para generar el código HTML del formulario y manejar gran parte de la validación y la interacción del usuario.</p> + +<p>En este tutorial vamos a mostrarle algunas de las formas de crear y trabajar con formularios y en particular, cómo las vistas genéricas de edición de formularios pueden significativamente reducir la cantidad del trabajo necesario para crear formularios para manejar sus modelos. En el camino iremos extendiendo nuestra aplicación <em>LocalLibrary</em> por agregar un formulario para permitir a los bibliotecarios renovar libros de la biblioteca y crearemos páginas para crear, editar o eliminar libros y autores (reproduciendo una versión básica del formulario mostrado arriba para editar libros).</p> + +<h2 id="Formularios_HTML">Formularios HTML</h2> + +<p>Primero, una breve revisión de <a href="/en-US/docs/Learn/HTML/Forms">Formularios HTML</a>. Considere un simple formulario HTML, con un solo campo de texto para entrar el nombre de algun "equipo" y su etiqueta asociada:</p> + +<p><img alt="Simple name field example in HTML form" src="https://mdn.mozillademos.org/files/14117/form_example_name_field.png" style="border-style: solid; border-width: 1px; display: block; height: 44px; margin: 0px auto; width: 399px;"></p> + +<p>El formulario es definido en HTML como una colección de elementos dentro de las etiquetas <code><form>...</form></code>, conteniendo por lo menos un elemento de entrada - <code>input</code> de tipo enviar - <code>type="submit"</code>.</p> + +<pre class="brush: html notranslate"><form action="/team_name_url/" method="post"> + <label for="team_name">Enter name: </label> + <input id="team_name" type="text" name="name_field" value="Default name for team."> + <input type="submit" value="OK"> +</form></pre> + +<p>Si bien acá solo tenemos un campo de texto para ingresar el nombre del equipo, un formulario puede tener cualquier número de otros elementos de entrada y sus etiquetas asociadas. El tipo del atributo del campo - <code>type</code> define que clase de widget será mostrado. El nombre - <code>name</code> y el identificador - <code>id</code> del campo son usados para identificar el campo en JavaScript/CSS/HTML, mientrras que el valor - <code>value</code> define el valor inicial para el campo cuando este se muestra por primera vez. La etiqueta del equipo correspondiente es especificada utilizando la etiqueta - <code style="font-style: normal; font-weight: normal;">label</code> (consulte "Enter name" arriba), con un campo <code style="font-style: normal; font-weight: normal;">for</code> que contiene el valor de identificación <code style="font-style: normal; font-weight: normal;">id</code> de la entrada asociada <code style="font-style: normal; font-weight: normal;">input</code>.</p> + +<p>La entrada de envío - <code>submit</code> se mostrará como un botón (de forma predeterminada) que el usuario puede presionar para cargar los datos en todos los demás elementos de entrada en el formulario al servidor (en este caso, solo el nombre del equipo - <code>team_name</code>). Los atributos del formulario definen el metodo - <code>method</code> de HTTP usado para enviar los datos y el destino de los datos al servidor (<code>action</code>):</p> + +<ul> + <li><code>action</code>: El recurso URL - resource/URL donde los datos serán enviados para su procesamiento cuando se envíe el formulario. Si esto no se establece (o se deja como una cadena vacía), entonces el formulario será enviado de regreso al URL de la página actual.</li> + <li><code>method</code>: El método utilizado por HTTP para enviar los datos: <em>post</em> o <em>get</em>. + <ul> + <li>El método <code>POST</code> siempre debe usarse si los datos enviados van a resultar en un cambio en la base de datos del servidor porque esto puede ser mas resistente a un ataque de solicitud de falsificación entre sitios (cross-site forgery request attacks).</li> + <li>El método <code>GET</code> unicamente debe usarse para cuando los formularios no cambian datos de usuario (por ejemplo, un formulario de búsqueda). También, este es recomendado para cuando desee guardar, marcar o compartir el URL.</li> + </ul> + </li> +</ul> + +<p>El rol del servidor es primero procesar el estado inicial del formulario ya sea conteniendo campos en blanco o completados previamente con valores inciales. Después de que el usuario presiona el botón de Enviar, el servidor recibirá los datos del formulario con valores del navegador web y deberá validar la información. Si el formulario contiene datos inválidos, el servidor deberá desplegar el formulario de nuevo, esta vez con datos ingresados por el usuario en campos "válidos" y mensajes para describir el problema en los campos con valor inválidos. Una vez el servidor recibe una petición con todos los datos de formulario válidos, este puede realizar una acción apropiada (por ejemplo, guardando los datos, regresando el resultado de una búsqueda, cargando un archivo, etc.) y luego notificar al usuario.</p> + +<p>Como puede imaginar, crear el código HTML, validar los datos retornados, redesplegar los datos ingresados con errores reportados si fuera necesario y realizar las operaciones deseadas sobre los datos válidos puede todo tomar bastante esfuerzo para "hacerlo bien". Django hace esto mucho más fácil por quitar parte del trabajo pesado y código repetitivo!</p> + +<h2 id="Proceso_del_manejo_de_formularios_de_Django">Proceso del manejo de formularios de Django</h2> + +<p>El manejo de formularios de Django utiliza las mismas técnicas que aprendimos en tutoriales anteriores (para mostrar información sobre nuestros modelos): la vista recibe una solicitud, realiza cualquier acción requerida incluyendo leer datos de los modelos, luego generar y devolver una página HTML (de una platilla, en la que pasamos un <em>contexto </em>conteniendo los datos a ser desplegados). Lo que hace las cosas más complicadas es que el servidor también necesita poder procesar los datos proporcionados por el usuario y volver a mostrar la página si hay algún error.</p> + +<p>A continuación se muestra un diagram de flujo del proceso de cómo Django maneja las solicitudes de formulario, comenzando con una solicitud de una página que contiene un formulario (mostrado en verde).</p> + +<p><img alt="Updated form handling process doc." src="https://mdn.mozillademos.org/files/14205/Form%20Handling%20-%20Standard.png" style="display: block; height: 569px; margin: 0px auto; width: 800px;"></p> + +<p>Basado en el diagrama de anterior, las principales pasos que hace el proceso del manejo de formularios de Django son:</p> + +<ol> + <li>Mostrar el formulario predeterminado la primera vez que es solicitado por el usuario. + <ul> + <li>El formulario puede contener campos en blanco (por ejemplo, si está creando un registro nuevo), o puede estar rellenado previamente con valores iniciales (por ejemplo, si está modificando un registro o si tiene valores iniciales predeterminados útiles).</li> + <li>El formulario se conoce como no vinculado en este punto porque no esta asociado con ningún dato ingresado por el usuario (aunque pueda tener valores iniciales).</li> + </ul> + </li> + <li>Recibir datos de una solicitud de envío y vincularlo al formulario. + <ul> + <li>La vinculacion de datos al formulario significa que los datos ingresados por el usuario y cualquier error están disponibles cuando necesitamos volver a desplegar el formulario. </li> + </ul> + </li> + <li>Limpiar y validar los datos. Clean and validate the data. + <ul> + <li>La limpieza de los datos realiza una sanitización de la entrada (por ejemplo, remover caracteres no válidos que podrían ser usados para enviar contenido malicioso al servidor) y convertirlos en tipos consistente de Python.</li> + <li>La validación verifica que los valores sean apropiados para el campo (por ejemplo, que esten en el rango correcto de fechas, no sean demasiado cortos ni demasiado largos, etc.)</li> + </ul> + </li> + <li>Si algún dato es no válido, volver a mostrar el formulario, esta vez con cualquier valor rellenado por el usuario y los mensajes de error para los campos con problemas.</li> + <li>Si todos los datos son válidos, realizar las acciones requeridas (por ejemplo, guardar los datos, enviar un correo electrónico, devolver el resultado de una búsqueda, cargar un archivo, etc)</li> + <li>Una vez todas las acciones se hayan completado, redirijir al usuario a otra página</li> +</ol> + +<p>Django provee una serie de herramientas y enfoques para ayudarlo con las tareas detalladas anteriormente. La más fundamental es la clase <code>Form</code>, la cuál simplifica la generación de formularios HTML y la limpieza y validación de datos. En la siguiente sección describimos cómo funcionan los formularios usando el ejemplo práctico de una página para permitir a los bibliotecarios renovar libros.</p> + +<div class="note"> +<p><strong>Nota:</strong> Comprender como se usa la clase <code>Form</code> lo ayudará cuando analicemos las clases de marco de formulario de más "alto nivel" de Django.</p> +</div> + +<h2 id="Renew-book_form_usando_un_Form_y_la_funcion_view">Renew-book form usando un Form y la funcion view</h2> + +<p>A continuación, vamos a añadir una página que permita a los bibilotecarios renovar los libros prestados. Para hacer esto crearemos un formulario que permita a los usuarios introducir una fecha. Rellenaremos el campo con un valor inicial de 3 semanas desde la fecha actual (el periodo de préstamo normal), y añadiremos alguna validación para asegurar que el bibilotecario no pueda introducir una fecha pasada o una demasiado lejana en el futuro. Cuando se haya introducido una fecha válida, la escribiremos sobre el campo <code>BookInstance.due_back</code> del registro actual.</p> + +<p>El ejemplo utilizará una vista basada en funciones y una clase <code>Form</code>. Las próximas secciones explican como los formularios funcionan, y los cambios que necesitas realizar para continuar adelante con nuestro proyecto <em>LocalLibrary</em>.</p> + +<h3 id="Clase_Form">Clase Form</h3> + +<p>La clase Form es el corazón del sistema de manejo de formularios de Django. Especifica los campos en el formulario, su diseño, widgets de visualización, etiquetas, valores iniciales, valores válidos y (una vez validados) los mensajes de error asociados con campos no válidos. La clase también proporciona métodos para renderizarse en plantillas usando formatos predefinidos (tablas, listas, etc.) o para obtener el valor de cualquier elemento (permitiendo el renderizado manual de grano fino).</p> + +<h4 id="Declarando_un_Form">Declarando un Form</h4> + +<p>La sintaxis de declaración para un formulario es muy similar a la de declarar un modelo, y comparte los mismos tipos de campo (y algunos parámetros similares). Esto tiene sentido porque en ambos casos debemos asegurarnos de que cada campo maneja los tipos correctos de datos, está restringido a datos válidos y tiene una descripción para la visualización / documentación.</p> + +<p>Para crear un formulario (<code>Form</code>) es necesario importar la libreria f<code>orms</code>, derivada de la clase <code>Form</code>, y tambien declarar los campos del formulario. A continuación se muestra una clase de formulario muy básica para nuestro formulario de renovación de libros de la biblioteca:</p> + +<pre class="brush: python notranslate">from django import forms + +class RenewBookForm(forms.Form): + renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).") +</pre> + +<h4 id="Campos_del_Form">Campos del Form</h4> + +<p>En este caso, tenemos un único <code><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#datefield">DateField</a></code> para ingresar la fecha de renovación que se mostrará en HTML con un valor en blanco, la etiqueta predeterminada "Fecha de renovación:" y algún texto de uso útil: "Ingrese una fecha entre ahora y 4 semanas (valor predeterminado 3 semanas)." Como no se especifica ninguno de los otros argumentos opcionales, el campo aceptará fechas utilizando los input_formats: AAAA-MM-DD (2016-11-06), MM / DD / AAAA (26/02/2016), MM / DD / AA ( 25/10/16), y se representará con el widget predeterminado: DateInput.</p> + +<p>Hay muchos otros tipos de campos de formulario, que reconocerá en gran medida por su similitud con las clases de campo de modelo equivalentes: <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#booleanfield"><code>BooleanField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#charfield"><code>CharField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#choicefield"><code>ChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#typedchoicefield"><code>TypedChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#datefield"><code>DateField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#datetimefield"><code>DateTimeField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#decimalfield"><code>DecimalField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#durationfield"><code>DurationField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#emailfield"><code>EmailField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#filefield"><code>FileField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#filepathfield"><code>FilePathField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#floatfield"><code>FloatField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#imagefield"><code>ImageField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#integerfield"><code>IntegerField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#genericipaddressfield"><code>GenericIPAddressField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#multiplechoicefield"><code>MultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#typedmultiplechoicefield"><code>TypedMultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#nullbooleanfield"><code>NullBooleanField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#regexfield"><code>RegexField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#slugfield"><code>SlugField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#timefield"><code>TimeField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#urlfield"><code>URLField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#uuidfield"><code>UUIDField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#combofield"><code>ComboField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#multivaluefield"><code>MultiValueField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#splitdatetimefield"><code>SplitDateTimeField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#modelmultiplechoicefield"><code>ModelMultipleChoiceField</code></a>, <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#modelchoicefield"><code>ModelChoiceField</code></a>.</p> + +<p>Los argumentos que son comunes a la mayoría de los campos se enumeran a continuación (estos tienen valores predeterminados sensibles):</p> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#required">required</a>: Si es <code>True</code>, el campo no se puede dejar en blanco o dar un valor <code>None</code>. Los Campos son obligatorios por defecto, tambien puedes establecer <code>required=False</code> para permitir valores en blanco en el formulario.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#label">label</a>: label es usado cuando renderizamos el campo en HTML. Si <a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#label">label</a> no es especificado entonces Django crearía uno a partir del nombre del campo al poner en mayúscula la primera letra y reemplazar los guiones bajos por espacios (por ejemplo. <em>Renewal date</em>).</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#label-suffix">label_suffix</a>: <span class="tlid-translation translation" lang="es"><span title="">Por defecto, se muestran dos puntos después de la etiqueta</span></span> (ejemplo. Renewal date<strong>:</strong>). Este argumento le permite especificar como sufijo diferente que contiene otros caracteres.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#initial">initial</a>: El valor inicial para el campo cuando es mostrado en el formulario.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#widget">widget</a>: <span class="tlid-translation translation" lang="es"><span title="">El widget de visualización para usar</span></span>.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#help-text">help_text</a> (como se ve en el ejemplo anterior): texto adicional que se puede mostrar en formularios para explicar cómo usar el campo.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#error-messages">error_messages</a>: Una lista de mensajes de error para el campo. Puede reemplazarlos con sus propios mensajes si es necesario.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#validators">validators</a>: Una lista de funciones que se invocarán en el campo cuando se valide.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#localize">localize</a>: Permite la localización de la entrada de datos del formulario (consulte el enlace para obtener más información).</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/#disabled">disabled</a>: El campo se muestra pero su valor no se puede editar si esto es <code>True</code>. Por defecto es <code>False</code>.</li> +</ul> + +<h4 id="Validación">Validación</h4> + +<p>Django proporciona numerosos lugares donde puede validar sus datos. La forma más fácil de validar un solo campo es anular el método <code>clean_<strong><fieldname></strong>()</code> para el campo que desea verificar. Entonces, por ejemplo, podemos validar lo ingresado <code>renewal_date</code> los valores son entre ahora y 4 semanas mediante la implementación <code>clean_<strong>renewal_date</strong>() </code>como se muestra abajo.</p> + +<pre class="brush: python notranslate">from django import forms + +<strong>from django.core.exceptions import ValidationError +from django.utils.translation import ugettext_lazy as _ +import datetime #for checking renewal date range. +</strong> +class RenewBookForm(forms.Form): + renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).") + +<strong> def clean_renewal_date(self): + data = self.cleaned_data['renewal_date'] + + #Check date is not in past. + if data < datetime.date.today(): + raise ValidationError(_('Invalid date - renewal in past')) + + #Check date is in range librarian allowed to change (+4 weeks). + if data > datetime.date.today() + datetime.timedelta(weeks=4): + raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead')) + + # Remember to always return the cleaned data. + return data</strong></pre> + +<p>Hay dos cosas importantes a tener en cuenta. El primero es que obtenemos nuestros datos usando <code>self.cleaned_data['renewal_date']</code> y que devolvemos estos datos si los cambiamos o no al final de la función. Este paso nos permite "limpiar" y desinfectar los datos de entrada potencialmente insegura utilizando los validadores predeterminados, y convertirlos al tipo estándar correcto para los datos (en este caso, un objeto Python <code>datetime.datetime</code>).</p> + +<p>El segundo punto es que si un valor cae fuera de nuestro rango, elevamos un <code>ValidationError</code>, especificando el texto de error que queremos mostrar en el formulario si se ingresa un valor no válido. El ejemplo anterior también envuelve este texto en uno de las <a href="https://docs.djangoproject.com/en/1.10/topics/i18n/translation/">funciones de traduccion de Django</a> <code>ugettext_lazy()</code> (importado como <code>_()</code>), lo cual es una buena práctica si desea traducir su sitio más tarde.</p> + +<div class="note"> +<p><strong>Nota:</strong> Existen muchos otros métodos y ejemplos para validar formularios en <a href="https://docs.djangoproject.com/en/1.10/ref/forms/validation/">Validacion de Formularios y campos</a> (Django docs). Por ejemplo, en los casos en que tiene varios campos que dependen unos de otros, puede anular la función <a href="https://docs.djangoproject.com/en/1.10/ref/forms/api/#django.forms.Form.clean">Form.clean()</a> function y colocar un <code>ValidationError</code>.</p> +</div> + +<p>¡Eso es todo lo que necesitamos para el formulario en este ejemplo!</p> + +<h4 id="Copia_el_Formulario">Copia el Formulario</h4> + +<p>Crea y abre el archivo <strong>locallibrary/catalog/forms.py</strong> y copie el listado completo del código del bloque anterior en él.</p> + +<h3 id="Configuracion_del_URL">Configuracion del URL</h3> + +<p>Antes de crear nuestra vista, agreguemos una configuración de URL para la página de renovar libros. Copie la siguiente configuración en la parte inferior de <strong>locallibrary/catalog/urls.py</strong>.</p> + +<pre class="brush: python notranslate">urlpatterns += [ + url(r'^book/(?P<pk>[-\w]+)/renew/$', views.renew_book_librarian, name='renew-book-librarian'), +]</pre> + +<p>La configuración de URL redirigirá las URL con el formato <strong>/catalog/book/<em><bookinstance id></em>/renew/</strong> a la función llamada <code>renew_book_librarian()</code> en <strong>views.py</strong>, y envia el id de <code>BookInstance</code> como parametro llamado <code>pk</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Podemos nombrar nuestros datos de URL capturados "pk" como queramos, porque tenemos un control completo sobre la función de vista (no estamos usando una clase de vista de detalles genérica que espere parámetros con un nombre determinado). sin embargo <code>pk</code>, abreviatura de "primary key", es una convención razonable de usar!</p> +</div> + +<h3 id="View">View</h3> + +<p>Como se discutió en el <a href="#django_form_handling_process">proceso de manejo de formularios de Django</a> arriba, la vista debe presentar el formulario predeterminado cuando se llama por primera vez y luego volver a representarlo con mensajes de error si los datos no son válidos, o procesar los datos y redirigirlos a una nueva página si los datos son válidos. Para realizar estas diferentes acciones, la vista debe poder saber si se está llamando por primera vez para presentar el formulario predeterminado, o una vez posterior para validar los datos.</p> + +<p>Para formularios que usan una solicitud <code>POST</code> para enviar información al servidor, el patrón más común es que la vista pruebe con el tipo de solicitud <code>POST</code> (<code>if request.method == 'POST':</code>) para identificar las solicitudes de validación de formularios y <code>GET</code> (usando una condición <code>else</code> ) para identificar la solicitud de creación de formulario inicial. Si desea enviar sus datos utilizando una solicitud <code>GET</code> entonces, un enfoque típico para identificar si esta es la primera invocación de vista o posterior es leer los datos del formulario (por ejemplo, leer un valor oculto en el formulario).</p> + +<p>El proceso de renovacion de un libro escribira cambios en nuestra base de datos , entonces por convencion usaremos una peticion de tipo <code>POST</code>. El siguiente fragmento de código muestra el patrón (muy estándar) para este tipo de vista de funciones. </p> + +<pre class="brush: python notranslate">from django.shortcuts import get_object_or_404 +from django.http import HttpResponseRedirect +from django.core.urlresolvers import reverse +import datetime + +from .forms import RenewBookForm + +def renew_book_librarian(request, pk): + book_inst=get_object_or_404(BookInstance, pk = pk) + + # If this is a POST request then process the Form data +<strong> if request.method == 'POST':</strong> + + # Create a form instance and populate it with data from the request (binding): + form = RenewBookForm(request.POST) + + # Check if the form is valid: + <strong>if form.is_valid():</strong> + # process the data in form.cleaned_data as required (here we just write it to the model due_back field) + book_inst.due_back = form.cleaned_data['renewal_date'] + book_inst.save() + + # redirect to a new URL: + return HttpResponseRedirect(reverse('all-borrowed') ) + + # If this is a GET (or any other method) create the default form. +<strong> else:</strong> + proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3) + form = RenewBookForm(initial={'renewal_date': proposed_renewal_date,}) + + return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'bookinst':book_inst})</pre> + +<p>Primero importamos nuestro formulario (<code>RenewBookForm</code>) y una serie de otros objetos / métodos útiles utilizados en el cuerpo de la función de vista:</p> + +<ul> + <li><code><a href="https://docs.djangoproject.com/en/1.10/topics/http/shortcuts/#get-object-or-404">get_object_or_404()</a></code>: Devuelve un objeto especificado de un modelo en función de su valor de clave principal y genera una excepción <code>Http404</code> (not found) si el registro no existe. </li> + <li><code><a href="https://docs.djangoproject.com/en/1.10/ref/request-response/#django.http.HttpResponseRedirect">HttpResponseRedirect</a></code>: Esto crea una redirección a una URL especificada (HTTP status code 302). </li> + <li><code><a href="https://docs.djangoproject.com/en/1.10/ref/urlresolvers/#django.urls.reverse">reverse()</a></code>: Esto genera una URL a partir de un nombre de configuración de URL y un conjunto de argumentos. Es el equivalente en Python de la etiqueta <code>url</code> que hemos estado usando en nuestras plantillas.</li> + <li><code><a href="https://docs.python.org/3/library/datetime.html">datetime</a></code>: Una libreria de Python para manejar las fechas y horas (dates and time). </li> +</ul> + +<p>En la vista, primero usamos el argumento <code>pk</code> argument en <code>get_object_or_404()</code> para obtener el actual <code>BookInstance</code> (si esto no existe, la vista se cerrará inmediatamente y la página mostrará un error "no encontrado"). Si no se trata de una solicitud POST (manejada por la cláusula else), creamos el formulario predeterminado que pasa un valor inicial (initial) para el campo renewal_date (como se muestra en negrita a continuación, esto es 3 semanas desde la fecha actual)..</p> + +<pre class="brush: python notranslate"> book_inst=get_object_or_404(BookInstance, pk = pk) + + # If this is a GET (or any other method) create the default form + <strong>else:</strong> + proposed_renewal_date = datetime.date.today() + datetime.timedelta(<strong>weeks=3</strong>) + <strong>form = RenewBookForm(initial={'</strong>renewal_date<strong>': </strong>proposed_renewal_date<strong>,})</strong> + + return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'bookinst':book_inst})</pre> + +<p>Después de crear el formulario, llamamos <code>render()</code> para crear la página HTML, especificando la plantilla y un contexto que contiene nuestro formulario. En este caso, el contexto también contiene nuestro <code>BookInstance</code>, que usaremos en la plantilla para proporcionar información sobre el libro que estamos renovando.</p> + +<p>Sin embargo, si esto es una solicitud <code>POST</code>, entonces crearemos nuestro objeto <code>form</code> y llenarlo con datos de la solicitud. Este proceso se llama "enlace" (binding) y nos permite validar el formulario. Luego verificamos si el formulario es válido, que ejecuta todo el código de validación en todos los campos, incluido el código genérico para verificar que nuestro campo de fecha sea realmente una fecha válida y nuestra funcion del formulario <code>clean_renewal_date()</code> chequea la fecha que tenga un rango correcto. </p> + +<pre class="brush: python notranslate"> book_inst=get_object_or_404(BookInstance, pk = pk) + + # If this is a POST request then process the Form data + if request.method == 'POST': + + # Create a form instance and populate it with data from the request (binding): +<strong> form = RenewBookForm(request.POST)</strong> + + # Check if the form is valid: + if form.is_valid(): + # process the data in form.cleaned_data as required (here we just write it to the model due_back field) + book_inst.due_back = form.cleaned_data['renewal_date'] + book_inst.save() + + # redirect to a new URL: + return HttpResponseRedirect(reverse('all-borrowed') ) + + return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'bookinst':book_inst})</pre> + +<p>Si el formulario no es válido llamamos <code>render()</code> de nuevo, pero esta vez el valor del formulario pasado en el contexto incluirá mensajes de error.</p> + +<p>Si el formulario es válido, entonces podemos comenzar a usar los datos, accediendo a ellos a través del atributo <code>form.cleaned_data</code> (ejemplo <code>data = form.cleaned_data['renewal_date']</code>). Aquí solo guardamos los datos en el valor <code>due_back</code> asociado al objeto <code>BookInstance</code>.</p> + +<div class="warning"> +<p><strong>Importante</strong>: Si bien también puede acceder a los datos del formulario directamente a través de la solicitud (por ejemplo <code>request.POST['renewal_date']</code> o <code>request.GET['renewal_date']</code> (si se esta usando una solicitud GET) esto NO es recomendable. Los datos limpios se desinfectan, validan y convierten en tipos compatibles con Python.</p> +</div> + +<p>El paso final en la parte de manejo de formularios de la vista es redirigir a otra página, generalmente una página de "éxito". En este caso usamos <code>HttpResponseRedirect</code> y <code>reverse()</code> para redirigir a la vista llamada <code>'all-borrowed'</code>(esto fue creado como el "desafío" en <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions#Challenge_yourself">Django Tutorial Part 8: User authentication and permissions</a>).Si no creó esa página, considere redirigir a la página de inicio en la URL '/').</p> + +<p>Eso es todo lo necesario para el manejo del formulario en sí, pero aún debemos restringir el acceso a la vista a los bibliotecarios. Probablemente deberíamos crear un nuevo permiso en <code>BookInstance</code> ("<code>can_renew</code>"),pero para simplificar las cosas aquí solo usamos la funcion decorator <code>@permission_required</code> con nuestro existente permiso <code>can_mark_returned</code>.</p> + +<p>La vista final es, por lo tanto, como se muestra a continuación. Copie esto en la parte inferior de <strong>locallibrary/catalog/views.py</strong>.</p> + +<pre class="notranslate"><strong>from django.contrib.auth.decorators import permission_required</strong> + +from django.shortcuts import get_object_or_404 +from django.http import HttpResponseRedirect +from django.url import reverse +import datetime + +from .forms import RenewBookForm + +<strong>@permission_required('catalog.<code>can_mark_returned</code>')</strong> +def renew_book_librarian(request, pk): + """ + View function for renewing a specific BookInstance by librarian + """ + book_inst=get_object_or_404(BookInstance, pk = pk) + + # If this is a POST request then process the Form data + if request.method == 'POST': + + # Create a form instance and populate it with data from the request (binding): + form = RenewBookForm(request.POST) + + # Check if the form is valid: + if form.is_valid(): + # process the data in form.cleaned_data as required (here we just write it to the model due_back field) + book_inst.due_back = form.cleaned_data['renewal_date'] + book_inst.save() + + # redirect to a new URL: + return HttpResponseRedirect(reverse('all-borrowed') ) + + # If this is a GET (or any other method) create the default form. + else: + proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3) + form = RenewBookForm(initial={'renewal_date': proposed_renewal_date,}) + + return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'bookinst':book_inst}) +</pre> + +<h3 id="La_plantilla">La plantilla</h3> + +<p>Crea la plantilla html referenciada en la vista dentro del directorio (<strong>/catalog/templates/catalog/book_renew_librarian.html</strong>) y copia el codigo a continuacion dentro del archivo que creaste:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} +{% block content %} + + <h1>Renew: \{{bookinst.book.title}}</h1> + <p>Borrower: \{{bookinst.borrower}}</p> + <p{% if bookinst.is_overdue %} class="text-danger"{% endif %}>Due date: \{{bookinst.due_back}}</p> + +<strong> <form action="" method="post"> + {% csrf_token %} + <table> + \{{ form }} + </table> + <input type="submit" value="Submit" /> + </form></strong> + +{% endblock %}</pre> + +<p>La mayor parte de esto será completamente familiar de los tutoriales anteriores. Extendemos la plantilla base y luego redefinimos el bloque de contenido. Podemos hacer referencia<code>\{{bookinst}}</code> (y sus variables) porque se pasó al objeto de contexto en la funci'on <code>render()</code>,y los usamos para colocar el título del libro, el prestatario y la fecha de vencimiento original.</p> + +<p>El código del formulario es relativamente simple. Primero declaramos las etiquetas del <code>form</code>,especificando dónde se debe enviar el formulario (<code>action</code>) y el <code>metodo</code> para enviar los datos (en este caso, una "POST HTTP"), si recuerda el <a href="#HTML_forms">HTML Forms</a> resumen en la parte superior de la página, un espacio vacío <code>action</code>como se muestra, significa que los datos del formulario se volverán a publicar en la URL actual de la página (¡que es lo que queremos!). Dentro de las etiquetas definimos la enntrada (input) <code>submit</code>, que un usuario puede presionar para enviar los datos. Esto <code>{% csrf_token %}</code> es agregado justo dentro de las etiquetas de formulario es parte de la protección de falsificación entre sitios de Django.</p> + +<div class="note"> +<p><strong>Nota:</strong> Agregue el {% csrf_token%} a cada plantilla de Django que cree que use POST para enviar datos. Esto reducirá la posibilidad de que usuarios malintencionados secuestran formularios.</p> +</div> + +<p>Todo lo que queda es la variable de la plantilla <code>\{{form}}</code>, <span class="tlid-translation translation" lang="es"><span title="">que pasamos a la plantilla en el diccionario de contexto.</span> <span title="">Quizás, como era de esperar, cuando se usa como se muestra, proporciona la representación predeterminada de todos los campos del formulario, incluidas sus etiquetas, widgets y texto de ayuda; la representación es la que se muestra a continuación:</span></span></p> + +<pre class="brush: html notranslate"><tr> + <th><label for="id_renewal_date">Renewal date:</label></th> + <td> + <input id="id_renewal_date" name="renewal_date" type="text" value="2016-11-08" required /> + <br /> + <span class="helptext">Enter date between now and 4 weeks (default 3 weeks).</span> + </td> +</tr> +</pre> + +<div class="note"> +<p><strong>Nota:</strong> <span class="tlid-translation translation" lang="es"><span title="">Quizás no sea obvio porque solo tenemos un campo, pero de forma predeterminada cada campo se define en su propia fila de tabla (razón por la cual la variable está dentro de la etiqueta</span></span> <code>table </code>arriba).Esta misma representación (rendering) se proporciona si hace referencia a la variable de plantilla <code>\{{ form.as_table }}</code>.</p> +</div> + +<p>Si tuviera que ingresar una fecha no válida, también obtendría una lista de los errores que se muestran en la página (en negrita a continuación).</p> + +<pre class="brush: html notranslate"><tr> + <th><label for="id_renewal_date">Renewal date:</label></th> + <td> +<strong> <ul class="errorlist"> + <li>Invalid date - renewal in past</li> + </ul></strong> + <input id="id_renewal_date" name="renewal_date" type="text" value="2015-11-08" required /> + <br /> + <span class="helptext">Enter date between now and 4 weeks (default 3 weeks).</span> + </td> +</tr></pre> + +<h4 id="Otras_formas_de_usar_variable_de_la_plantilla_de_formulario">Otras formas de usar variable de la plantilla de formulario</h4> + +<p>Usando <code>\{{form}}</code> como se muestra arriba, cada campo se representa como una fila de la tabla. También puede representar cada campo como un elemento de la lista (usando <code>\{{form.as_ul}}</code> ) o como un parrafo (usando <code>\{{form.as_p}}</code>).</p> + +<p>Lo que es aún más genial es que puede tener un control completo sobre la representación de cada parte del formulario, indexando sus propiedades mediante la notación de puntos. Entonces, por ejemplo, podemos acceder a una serie de elementos separados de los campos de <code>renewal_date</code>-</p> + +<ul> + <li><code>\{{form.renewal_date}}:</code> The whole field.</li> + <li><code>\{{form.renewal_date.errors}}</code>: The list of errors.</li> + <li><code>\{{form.renewal_date.id_for_label}}</code>: The id of the label.</li> + <li><code>\{{form.renewal_date.help_text}}</code>: The field help text.</li> + <li>etc!</li> +</ul> + +<p>Para obtener más ejemplos de cómo reproducir manualmente los formularios en plantillas y recorrer dinámicamente los campos de la plantilla, vea <a href="https://docs.djangoproject.com/en/1.10/topics/forms/#rendering-fields-manually">Working with forms > Rendering fields manually</a> (Django docs).</p> + +<h3 id="Probando_la_página">Probando la página</h3> + +<p>Si aceptó el "desafío" en <a href="/en-US/docs/Learn/Server-side/Django/authentication_and_sessions#Challenge_yourself">Django Tutorial Part 8: User authentication and permissions</a> tendrá una lista de todos los libros prestados en la biblioteca, que solo es visible para el personal de la biblioteca. Podemos agregar un enlace a nuestra página de renovación al lado de cada artículo usando el código de plantilla a continuación.</p> + +<pre class="brush: html notranslate">{% if perms.catalog.can_mark_returned %}- <a href="{% url 'renew-book-librarian' bookinst.id %}">Renew</a> {% endif %}</pre> + +<div class="note"> +<p><strong>Nota</strong>: Recuerde que su inicio de sesión de prueba deberá tener el permiso "<code>catalog.can_mark_returned</code>" para acceder a la página de renovar el libro (quizás use su cuenta de superusuario).</p> +</div> + +<p>Alternativamente, puede construir manualmente una URL de prueba como esta — <a href="http://127.0.0.1:8000/catalog/book/<bookinstance id>/renew/">http://127.0.0.1:8000/catalog/book/<em><bookinstance_id></em>/renew/</a> (se puede obtener un ID de instancia de libro válido navegando a la página de detalles de un libro en su biblioteca y copiando el campo <code>id</code>).</p> + +<h3 id="Como_se_ve">Como se ve?</h3> + +<p>Si tiene éxito, el formulario predeterminado se verá así:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14209/forms_example_renew_default.png" style="border-style: solid; border-width: 1px; display: block; height: 292px; margin: 0px auto; width: 680px;"></p> + +<p>El formulario con un valor no válido ingresado se verá así:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14211/forms_example_renew_invalid.png" style="border-style: solid; border-width: 1px; display: block; height: 290px; margin: 0px auto; width: 658px;"></p> + +<p>La lista de todos los libros con enlaces renovados se verá así:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14207/forms_example_renew_allbooks.png" style="border-style: solid; border-width: 1px; display: block; height: 256px; margin: 0px auto; width: 613px;"></p> + +<h2 id="ModelForms">ModelForms</h2> + +<p>Crear una clase <code>Form</code> utilizando el enfoque descrito anteriormente es muy flexible, lo que le permite crear cualquier tipo de página de formulario que desee y asociarla con cualquier modelo o modelos.</p> + +<p>Sin embargo, si solo necesita un formulario para asignar los campos de un solo modelo, entonces su modelo ya definirá la mayor parte de la información que necesita en su formulario: campos, etiquetas, texto de ayuda, etc. En lugar de recrear las definiciones de modelo en su formulario , es más fácil usar una clase auxiliar <a href="https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/">ModelForm</a> para crear el formulario a partir de su modelo. El <code>ModelForm</code> puede usarse dentro de sus vistas exactamente de la misma manera que un ordinario <code>Form</code>.</p> + +<p>Un <code>ModelForm</code> que contiene el mismo campo que nuestro original <code>RenewBookForm</code>se muestra a continuación. Todo lo que necesita hacer para crear el formulario es agregar <code>class Meta</code> with the associated <code>model</code> (<code>BookInstance</code>) y una lista de los campos del modelo <code>fields</code>para incluir en el formulario (puede incluir todos los campos usando <code>fields = '__all__'</code>, o puedes usar <code>exclude</code> (en vez de <code>fields</code>) para especificar los campos que no se incluirán del modelo).</p> + +<pre class="brush: python notranslate">from django.forms import ModelForm +from .models import BookInstance + +class RenewBookModelForm(ModelForm): +<strong> class Meta: + model = BookInstance + fields = ['due_back',]</strong> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Esto podría no parece mucho más simple que simplemente usar un <code>Form</code>(y no es en este caso, porque solo tenemos un campo). Sin embargo, si tiene muchos campos, puede reducir la cantidad de código de manera bastante significativa.</p> +</div> + +<p>El resto de la información proviene de las definiciones de campo del modelo (por ejemplo, etiquetas, widgets, texto de ayuda, mensajes de error). Si estos no son del todo correctos, entonces podemos anularlos en nuestro <code>class Meta</code>, especificando un diccionario que contiene el campo a cambiar y su nuevo valor. Por ejemplo, en este formulario podríamos querer una etiqueta para nuestro campo de "Fecha de renovación" (en lugar del valor predeterminado basado en el nombre del campo: Fecha de vencimiento), y también queremos que nuestro texto de ayuda sea específico para este caso de uso. El <code>Meta</code> a continuación le muestra cómo anular estos campos, y puede configurar de manera similar <code>widgets</code> y <code>error_messages</code> si los valores predeterminados no son suficientes.</p> + +<pre class="brush: python notranslate">class Meta: + model = BookInstance + fields = ['due_back',] +<strong> labels = { 'due_back': _('Renewal date'), } + help_texts = { 'due_back': _('Enter a date between now and 4 weeks (default 3).'), } </strong> +</pre> + +<p>Para agregar validación, puede usar el mismo enfoque que para un normal <code>Form</code> — define una función llamada <code>clean_<em>field_name</em>()</code> y coloca (raise) <code>ValidationError</code> excepciones para valores no válidos. La única diferencia con respecto a nuestro formulario original es que el campo modelo se llama <code>due_back</code> y no "<code>renewal_date</code>".</p> + +<pre class="brush: python notranslate">from django.forms import ModelForm +from .models import BookInstance + +class RenewBookModelForm(ModelForm): +<strong> def clean_due_back(self): + data = self.cleaned_data['due_back'] + + #Check date is not in past. + if data < datetime.date.today(): + raise ValidationError(_('Invalid date - renewal in past')) + + #Check date is in range librarian allowed to change (+4 weeks) + if data > datetime.date.today() + datetime.timedelta(weeks=4): + raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead')) + + # Remember to always return the cleaned data. + return data +</strong> + class Meta: + model = BookInstance + fields = ['due_back',] + labels = { 'due_back': _('Renewal date'), } + help_texts = { 'due_back': _('Enter a date between now and 4 weeks (default 3).'), } +</pre> + +<p>La clase <code>RenewBookModelForm</code> a continuación es ahora funcionalmente equivalente a nuestro original <code>RenewBookForm</code>. Puede importarlo y usarlo donde quiera que lo use actualmente <code>RenewBookForm</code>.</p> + +<h2 id="Vistas_de_edición_genéricas">Vistas de edición genéricas</h2> + +<p>El algoritmo de manejo de formularios que utilizamos en nuestro ejemplo de vista de funciones anterior representa un patrón extremadamente común en las vistas de edición de formularios. Django extrae gran parte de esta "plantilla" para ti, para crear vistas de edición genéricas ( <a href="https://docs.djangoproject.com/en/1.10/ref/class-based-views/generic-editing/">generic editing views</a> ) para crear, editar y eliminar vistas basadas en modelos. No solo manejan el comportamiento de "vista", sino que crean automáticamente la clase de formulario (un <code>ModelForm</code>) para tu modelo.</p> + +<div class="note"> +<p><strong>Nota: </strong>Además de las vistas de edición descritas aquí, también hay una clase <a href="https://docs.djangoproject.com/en/1.10/ref/class-based-views/generic-editing/#formview">FormView</a> , que se encuentra en algún lugar entre nuestra vista de función y las otras vistas genéricas en términos de "flexibilidad" frente a "esfuerzo de codificación". Usando <code>FormView</code> tu necesitas crear el <code>Form</code>, pero no tiene que implementar todo el patrón estándar de manejo de formularios. En su lugar, solo tiene que proporcionar una implementación de la función que se llamará una vez que se sepa que el envío es válido.</p> +</div> + +<p>En esta sección, vamos a usar vistas de edición genéricas para crear páginas para agregar funcionalidad para crear, editar y eliminar registros de <code>Author</code> de nuestra libreria — Proporcionar efectivamente una reimplementación básica de partes del sitio de administración (esto podría ser útil si necesita ofrecer la funcionalidad de administrador de una manera más flexible que puede proporcionar el sitio de administrador).</p> + +<h3 id="Views">Views</h3> + +<p>Abre el archivo de vistas (<strong>locallibrary/catalog/views.py</strong>) y agregue el siguiente bloque de código al final:</p> + +<pre class="brush: python notranslate">from django.views.generic.edit import CreateView, UpdateView, DeleteView +from django.urls import reverse_lazy +from .models import Author + +class AuthorCreate(CreateView): + model = Author + fields = '__all__' + initial={'date_of_death':'05/01/2018',} + +class AuthorUpdate(UpdateView): + model = Author + fields = ['first_name','last_name','date_of_birth','date_of_death'] + +class AuthorDelete(DeleteView): + model = Author + success_url = reverse_lazy('authors')</pre> + +<p>Como puede ver, para crear las vistas de las que necesita derivar <code>CreateView</code>, <code>UpdateView</code>, y <code>DeleteView</code> (respectivamente) y luego definir el modelo asociado.</p> + +<p>Para los casos de "crear" y "actualizar", también debe especificar los campos para mostrar en el formulario (utilizando la misma sintaxis que para <code>ModelForm</code>). En este caso, mostramos la sintaxis para mostrar "todos" los campos y cómo puede enumerarlos individualmente. También puede especificar valores iniciales para cada uno de los campos utilizando un diccionario de pares nombre_campo / valor (aquí establecemos arbitrariamente la fecha de fallecimiento para fines de demostración; ¡es posible que desee eliminar eso!). Por defecto, estas vistas redirigirán en caso de éxito a una página que muestre el elemento del modelo recién creado / editado, que en nuestro caso será la vista detallada del autor que creamos en un tutorial anterior. Puede especificar una ubicación alternativa de redireccionamiento declarando explícitamente el parámetro <code>success_url</code> (como hecho en la clase <code>AuthorDelete</code> ).</p> + +<p>La clase <code>AuthorDelete</code> no necesita mostrar ninguno de los campos, por lo que no es necesario especificarlos. Sin embargo, debe especificar el <code>success_url</code>, porque no hay un valor predeterminado obvio para que Django lo use. En este caso usamos la función <code><a href="https://docs.djangoproject.com/en/1.10/ref/urlresolvers/#reverse-lazy">reverse_lazy()</a></code> para redirigir a nuestra lista de autores después de que un autor ha sido eliminado — <code>reverse_lazy()</code> is a lazily executed version of <code>reverse()</code>, se usa aquí porque estamos proporcionando una URL a un atributo de vista basado en clases.</p> + +<h3 id="Templates_-_Plantillas">Templates - Plantillas</h3> + +<p>Las vistas "create" y "update" utilizan la misma plantilla de forma predeterminada, que se nombrará después de su model: <em>model_name</em><strong>_form.html</strong> (puedes cambiar el sufijo a algo diferente a <strong>_form</strong> usando el campo <code>template_name_suffix</code>en tu vista, ejemplo: <code>template_name_suffix = '_other_suffix'</code>)</p> + +<p>Crea la siguiente plantilla <strong>locallibrary/catalog/templates/catalog/author_form.html </strong> y copia el siguiente texto:</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + +<form action="" method="post"> + {% csrf_token %} + <table> + \{{ form.as_table }} + </table> + <input type="submit" value="Submit" /> + +</form> +{% endblock %}</pre> + +<p>Esto es similar a nuestros formularios anteriores y representa los campos usando una tabla. Tenga en cuenta también cómo declaramos nuevamente<code>{% csrf_token %}</code> para garantizar que nuestros formularios sean resistentes a los ataques CSRF.</p> + +<p>La vista "delete" espera encontrar una plantilla con el formato <em>model_name</em><strong>_confirm_delete.html</strong> (de nuevo, puedes cambiar el sufijo usando <code>template_name_suffix</code> en tu vista). Crea la siguiente plantilla <strong>locallibrary/catalog/templates/catalog/author_confirm_delete.html</strong> y copia en el texto a continuación.</p> + +<pre class="brush: html notranslate">{% extends "base_generic.html" %} + +{% block content %} + +<h1>Delete Author</h1> + +<p>Are you sure you want to delete the author: \{{ author }}?</p> + +<form action="" method="POST"> + {% csrf_token %} + <input type="submit" action="" value="Yes, delete." /> +</form> + +{% endblock %} +</pre> + +<h3 id="Configuración_de_URL">Configuración de URL</h3> + +<p>Abra el archivo de configuración de URL (<strong>locallibrary/catalog/urls.py</strong>) y agregue la siguiente configuración al final del archivo:</p> + +<pre class="brush: python notranslate">urlpatterns += [ + url(r'^author/create/$', views.AuthorCreate.as_view(), name='author_create'), + url(r'^author/(?P<pk>\d+)/update/$', views.AuthorUpdate.as_view(), name='author_update'), + url(r'^author/(?P<pk>\d+)/delete/$', views.AuthorDelete.as_view(), name='author_delete'), +]</pre> + +<p>¡No hay nada particularmente nuevo aquí! Puede ver que las vistas son clases y, por lo tanto, deben llamarse a través de <code>.as_view()</code>,y deberías poder reconocer los patrones de URL en cada caso. Debemos usar <code>pk</code> como el nombre de nuestro valor de clave principal (primary key) capturado, ya que este es el nombre del parámetro esperado por las clases de vista.</p> + +<p>Las páginas de crear, actualiza y eliminar autor ahora estan listas para probar (no nos molestaremos en engancharlas en la barra lateral del sitio en este caso, aunque puede hacerlo si lo desea).</p> + +<div class="note"> +<p><strong>Nota</strong>:¡Los usuarios observadores habrán notado que no hicimos nada para evitar que usuarios no autorizados accedan a las páginas! Lo dejamos como un ejercicio para usted (pista: puede usar el <code>PermissionRequiredMixin</code> y cree un nuevo permiso o reutilice nuestro permiso <code>can_mark_returned</code> ).</p> +</div> + +<h3 id="Probando_la_página_2">Probando la página</h3> + +<p>Primero inicie sesión en el sitio con una cuenta que tenga los permisos que haya decidido que se necesitan para acceder a las páginas de edición del autor.</p> + +<p>Luego navegue a la página de creación del autor: <a href="http://127.0.0.1:8000/catalog/author/create/">http://127.0.0.1:8000/catalog/author/create/</a>, que debería verse como la captura de pantalla a continuación.</p> + +<p><img alt="Form Example: Create Author" src="https://mdn.mozillademos.org/files/14223/forms_example_create_author.png" style="border-style: solid; border-width: 1px; display: block; height: 184px; margin: 0px auto; width: 645px;"></p> + +<p>Ingrese los valores para los campos y luego presione <strong>Submit</strong> para guardar el registro del autor. Ahora debería ser llevado a una vista detallada para su nuevo autor, con una URL de algo como <em>http://127.0.0.1:8000/catalog/author/10</em>.</p> + +<p>Puede probar la edición de registros agregando <em>/update/</em> hasta el final de la vista detallada URL (e.g. <em>http://127.0.0.1:8000/catalog/author/10/update/</em>) — no mostramos una captura de pantalla, porque se parece a la página "create".</p> + +<p>Por último, podemos eliminar el autor, agregando eliminar (delete) al final de la vista detallada del autor URL (ejemplo. <em>http://127.0.0.1:8000/catalog/author/10/delete/</em>). Django debería mostrar la página de eliminación que se muestra a continuación. pulse <strong>Yes, delete.</strong> para eliminar el registro y ser llevado a la lista de todos los autores.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14221/forms_example_delete_author.png" style="border-style: solid; border-width: 1px; display: block; height: 194px; margin: 0px auto; width: 561px;"></p> + +<h2 id="Retarte_a_ti_mismo">Retarte a ti mismo</h2> + +<p>Crea algunos formularios para crear, editar y eliminar registros de <code>Book</code>.Puede usar exactamente la misma estructura de <code>Authors</code>. Si tu plantilla <strong>book_form.html</strong> es solo una versión renombrada de la copia de la plantilla <strong>author_form.html</strong>, entonces la nueva página "crear libro" se verá como la captura de pantalla a continuación:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/14225/forms_example_create_book.png" style="border-style: solid; border-width: 1px; display: block; height: 521px; margin: 0px auto; width: 595px;"></p> + +<ul> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>¡Crear y manejar formularios puede ser un proceso complicado! Django lo hace mucho más fácil al proporcionar mecanismos programáticos para declarar, representar y validar formularios. Además, Django proporciona vistas genéricas de edición de formularios que pueden hacer casi todo el trabajo para definir páginas que pueden crear, editar y eliminar registros asociados con una sola instancia de modelo.</p> + +<p>Hay mucho más que se puede hacer con los formularios (consulte nuestra lista Vea también a continuación), pero ahora debe comprender cómo agregar formularios básicos y código de manejo de formularios a sus propios sitios web.</p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/forms/">Working with forms</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/intro/tutorial04/#write-a-simple-form">Writing your first Django app, part 4 > Writing a simple form</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/api/">The Forms API</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/fields/">Form fields</a> (Django docs) </li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/forms/validation/">Form and field validation</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/class-based-views/generic-editing/">Form handling with class-based views</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/">Creating forms from models</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/class-based-views/generic-editing/">Generic editing views</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/authentication", "Learn/Server-side/Django/Testing", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/generic_views/index.html b/files/es/learn/server-side/django/generic_views/index.html new file mode 100644 index 0000000000..7eb6830a87 --- /dev/null +++ b/files/es/learn/server-side/django/generic_views/index.html @@ -0,0 +1,640 @@ +--- +title: 'Tutorial de Django Parte 6: Listas genéricas y vistas de detalle' +slug: Learn/Server-side/Django/Generic_views +tags: + - Aprender + - Principiante + - Tutorial + - django + - plantillas django + - vistas django +translation_of: Learn/Server-side/Django/Generic_views +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Home_page", "Learn/Server-side/Django/Sessions", "Learn/Server-side/Django")}}</div> + +<p class="summary">Este tutorial extiende nuestro sitio web de la <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website" style="font-size: 1.25rem;">BibliotecaLocal</a><span style="font-size: 1.25rem;">, añadiendo páginas de listas y detalles de libros y autores. Aquí aprenderemos sobre vistas genéricas basadas en clases, y mostraremos cómo éstas pueden reducir la cantidad de código que tienes que escribir para casos de uso común. También entraremos en el manejo de URL en gran detalle, mostrando cómo realizar un emparejamiento de patrones básico</span><span style="font-size: 1.25rem;">.</span></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Requisitos previos:</th> + <td> + <p>Completa todos los tópicos anteriores del tutorial, incluyendo <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creación de tu página de inicio</a>.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Entender dónde y cómo usar las vistas genéricas basadas en clases, y cómo extraer patrones desde las URLs y enviar la información a las vistas.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Visión_General">Visión General</h2> + +<p>En este tutorial vamos a completar la primera versión del sitio web <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">BibliotecaLocal</a> añadiendo páginas de lista y detalle para libros y autores (o para ser más precisos, te mostraremos cómo implementar las páginas de libros, ¡y te dejaremos crear las páginas de autores por tí mismo!)</p> + +<p>El proceso es similar al de creación de la página índice, que mostramos en el tutorial anterior. Aquí también necesitaremos crear mapeos URL, vistas y plantillas. La principal diferencia es que para las páginas de detalle tendremos el reto adicional de extraer información desde patrones en las URLs y pasarla a la vista. Para estas páginas vamos a mostrar un tipo de vista completamente diferente: vistas genéricas de lista y detalle basadas en clases. Estas pueden reducir significativamente la cantidad de código requerido para las vistas, haciéndolas más fáciles de escribir y mantener.</p> + +<p>La parte final del tutorial mostrará cómo paginar tu información al usar vistas de lista genéricas basadas en clases.</p> + +<h2 id="Página_de_lista_de_libros">Página de lista de libros</h2> + +<p>La página de lista de libros desplegará una lista con todos los registros de libros disponibles en la página, a la cual se accede usando la URL: <code>catalog/books/</code>. La página desplegará un título y un autor para cada registro, siendo el título un hipervículo a la página de detalle de libro relacionada. La página tendrá la misma estructura y navegación que todas las demás páginas en el sitio, y por tanto podemos extender la plantilla base (<strong>base_generic.html</strong>) que creamos en el tutorial anterior.</p> + +<h3 id="Mapeo_URL">Mapeo URL</h3> + +<p>Abre <strong>/catalog/urls.py</strong> y copia allí la línea que se muestra abajo en negrita. De manera muy similar al mapeo de nuestro índice, esta función <code>url()</code> define una expresión regular (RE) para comparala con la URL (<strong>r'^books/$'</strong>), una función de vista que será llamada si la URL coincide (<code>views.BookListView.as_view()</code>) y un nombre para este mapeo en particular.</p> + +<pre class="brush: python">urlpatterns = [ + url(r'^$', views.index, name='index'), +<strong> url(r'^books/$', views.BookListView.as_view(), name='books'),</strong> +]</pre> + +<p>Esta expresión regular coincide con URLs iguales a <code>books/</code> (<code>^</code> es un marcador de inicio de cadena y <code>$</code> es un marcador de fin de cadena). Como se discutió en el tutorial anterior, la URL debió previamente haber coincidido con <code>/catalog</code>, de modo que la vista será llamada en realidad para la URL: <code>/catalog/books/</code>.</p> + +<p>La función de vista tiene un formato diferente al anterior -- eso es porque esta vista será en realidad implementada como una clase. Heredaremos desde una función de vista genérica existente que ya hace la mayoría de lo que queremos que esta función de vista haga, en lugar de escribir la nuestra propia desde el inicio.</p> + +<p>Para las vistas basadas en clases de Django, accedemos a una función de vista apropiada llamando al método de clase <code>as_view()</code>. Esto hace todo el trabajo de crear una instancia de la clase, y asegurarse de que los métodos controladores correctos sean llamados para las solicitudes HTTP entrantes.</p> + +<h3 id="Vista_(basada_en_clases)">Vista (basada en clases)</h3> + +<p>Podríamos fácilmente escribir la vista de lista de libros como una función regular (tal como nuestra vista de índice anterior), la cual consultaría a la base de datos por todos los libros, y luego llamar a <code>render()</code> para pasar dicha lista a una plantilla específica. Sin embargo, en lugar de eso usaremos una vista de lista genérica basada en clases (ListView) -- una clase que hereda desde una vista existente. Debido a que la vista genérica ya implementa la mayoría de la funcionalidad que necesitamos, y sigue la práctica adecuada de Django, seremos capaces de crear una vista de lista más robusta con menos código, menos repetición, y por último menos mantenimiento.</p> + +<p>Abre <strong>catalog/views.py</strong>, y copia el siguiente código al final del archivo:</p> + +<pre class="brush: python">from django.views import generic + +class BookListView(generic.ListView): + model = Book</pre> + +<p>¡Eso es todo! La vista genérica consultará a la base de datos para obtener todos los registros del modelo especificado (<code>Book</code>) y renderizará una plantilla ubicada en <strong>/locallibrary/catalog/templates/catalog/book_list.html</strong> (que crearemos más abajo). Dentro de la plantilla puedes acceder a la lista de libros mediante la variable de plantilla llamada <code>object_list</code> O <code>book_list</code> (esto es, genéricamente, "<code><em>nombre_del_modelo</em>_list</code>").</p> + +<div class="note"> +<p><strong>Nota</strong>: Esta ruta complicada para la ubicación de la plantilla no es un error de digitación -- las vistas genéricas buscan plantillas en <code><em>/application_name/the_model_name</em>_list.html</code> (<code>catalog/book_list.html</code> en este caso) dentro del directorio de la aplicación <code>/<em>application_name</em>/templates/</code> (<code>/catalog/templates/</code>).</p> +</div> + +<p>Puedes añadir atributos para cambiar el comportamiento por defecto de arriba. Por ejemplo, puedes especificar otro archivo de plantilla si necesitas tener múltiples vistas que usen el mismo modelo, o puedes querer usar un nombre diferente de variable de plantilla si <code>book_list</code> no resulta intuitivo para tu caso particular de uso de plantilla. Posiblemente la variación más útil es cambiar/filtrar el conjunto de resultados que se devuelve, así, en lugar de listar todos los libros podrías listar los 5 libros más leídos por otros usuarios.</p> + +<pre class="brush: python">class BookListView(generic.ListView): + model = Book + context_object_name = 'my_book_list' # your own name for the list as a template variable + queryset = Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title war + template_name = 'books/my_arbitrary_template_name_list.html' # Specify your own template name/location</pre> + +<h4 id="Sobreescribiendo_métodos_en_vistas_basadas_en_clases">Sobreescribiendo métodos en vistas basadas en clases</h4> + +<p>Si bien no necesitamos hacerlo aquí, puedes también sobreescribir algunos de los métodos de clase.</p> + +<p>Por ejemplo, podemos sobreescribir el método <code>get_queryset()</code> para cambiar la lista de registros devueltos. Esto es más flexible que simplemente ajustar el atributo <code>queryset</code> como lo hicimos en el fragmento de código anterior (aunque en este caso no existe un beneficio real):</p> + +<p> </p> + +<pre class="brush: python">class BookListView(generic.ListView): + model = Book + + def get_queryset(self): + return Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title war +</pre> + +<p> </p> + +<p>Podríamos también sobreescribir <code>get_context_data()</code> con el objeto de pasar variables de contexto adicionales a la plantilla (ej. la lista de libros se pasa por defecto). El fragmento de abajo muestra cómo añadir una variable llamada "some_data" al contexto (la misma estaría entonces disponible como una variable de plantilla).</p> + +<pre class="brush: python">class BookListView(generic.ListView): + model = Book + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(BookListView, self).get_context_data(**kwargs) + # Get the blog from id and add it to the context + context['some_data'] = 'This is just some data' + return context</pre> + +<p>Cuando se hace esto es importante seguir este patrón:</p> + +<ul> + <li>Primero obtener el contexto existente desde nuestra superclase.</li> + <li>Luego añadir tu nueva información de contexto.</li> + <li>Luego devolver el nuevo contexto (actualizado).</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Revisa <a href="https://docs.djangoproject.com/en/1.10/topics/class-based-views/generic-display/">Built-in class-based generic views</a> (Django docs) para muchos más ejemplos de lo que puedes hacer.</p> +</div> + +<h3 id="Creando_la_plantilla_de_Vista_de_Lista">Creando la plantilla de Vista de Lista</h3> + +<p>Crea el archivo HTML <strong>/locallibrary/catalog/templates/catalog/book_list.html</strong> y copia allí el texto de abajo. Como se discutió antes, este es el archivo de plantilla por defecto esperado por la vista de lista genérica basada en clases (para un modelo llamado <code>Book</code> en una aplicación llamada <code>catalog</code>).</p> + +<p>Las plantillas para las vistas genéricas son como cualquier otra plantilla (si bien el contexto/información enviada a la plantilla puede variar, por supuesto). Como con nuestra plantilla <em>índice</em>, extendemos nuestra plantilla base en la primera línea, y luego reemplazamos el bloque llamado <code>content</code>.</p> + +<pre class="brush: html">{% extends "base_generic.html" %} + +{% block content %} + <h1>Book List</h1> + + <strong>{% if book_list %}</strong> + <ul> + + {% for book in book_list %} + <li> + <a href="\{{ book.get_absolute_url }}">\{{ book.title }}</a> (\{{book.author}}) + </li> + {% endfor %} + + </ul> + <strong>{% else %}</strong> + <p>There are no books in the library.</p> + <strong>{% endif %} </strong> +{% endblock %}</pre> + +<p>La vista envía el contexto (lista de libros) por defecto como <code>object_list</code> y <code>book_list</code> (son áliases, cualquiera de ellos funcionará).</p> + +<h4 id="Ejecución_condicional">Ejecución condicional</h4> + +<p>Usamos las etiquetas de plantilla <code><a href="https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#if">if</a></code>, <code>else</code> y <code>endif</code> para revisar si la <code>book_list</code> ha sido definida y no está vacía. Si <code>book_list</code> está vacía, entonces la cláusula <code>else</code> despliega un texto que explica que no existen libros a listar. Si <code>Book_list</code> no está vacía, entonces iteramos a través de la lista de libros.</p> + +<pre class="brush: html"><strong>{% if book_list %}</strong> + <!-- code here to list the books --> +<strong>{% else %}</strong> + <p>There are no books in the library.</p> +<strong>{% endif %}</strong> +</pre> + +<p>La condicional de arriba solo revisa un caso, pero puedes revisar condiciones adicionales usando la etiqueta de plantilla <code>elif</code> (ej. <code>{% elif var2 %}</code>). Para mayor información sobre operadores condicionales mira: <a href="https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#if">if</a>, <a href="https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#ifequal-and-ifnotequal">ifequal/ifnotequal</a>, y <a href="https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#ifchanged">ifchanged</a> en <a href="https://docs.djangoproject.com/en/1.10/ref/templates/builtins">Built-in template tags and filters</a> (Django Docs).</p> + +<h4 id="Lazos_For">Lazos For</h4> + +<p>La plantilla usa las etiquetas de plantilla <a href="https://docs.djangoproject.com/en/1.10/ref/templates/builtins/#for">for</a> y <code>endfor</code> para iterar a través de la lista de libros, como se muestra abajo. Cada iteración asigna a la variable de plantilla <code>book</code> la información para el ítem actual de la lista.</p> + +<pre class="brush: html">{% for <strong>book</strong> in book_list %} + <li> <!-- code here get information from each <strong>book</strong> item --> </li> +{% endfor %} +</pre> + +<p>Si bien no se usan aquí, Django creará otras variables dentro del lazo que puedes usar para monitorear la iteración. Por ejemplo, puedes revisar la variable <code>forloop.last</code> para realizar un procesamiento condicional la última vez que el lazo se ejecuta.</p> + +<h4 id="Accediendo_a_las_variables">Accediendo a las variables</h4> + +<p>El código dentro del lazo crea un ítem de lista para cada libro, que muestra tanto el título (como un enlace hacia la vista de detalle que aún no creamos) como el autor.</p> + +<pre class="brush: html"><a href="\{{ book.get_absolute_url }}">\{{ book.title }}</a> (\{{book.author}}) +</pre> + +<p>Accedemos a los <em>campos</em> del registro del libro asociado usando la "notación de punto" (ej. <code>book.title</code> y <code>book.author</code>), donde el texto que sigue a la palabra <code>book</code> es el nombre del campo (como se definió en el modelo).</p> + +<p>También podemos invocar <em>funciones</em> en el modelo desde dentro de nuestra plantilla -- en este caso invocamos a <code>book.get_absolute_url()</code> para obtener una URL que se podría usar para desplegar la página de detalle relacionada. Esto funciona siempre y cuando la función no tenga ningún argumento (¡no hay forma de enviar argumentos!).</p> + +<div class="note"> +<p><strong>Nota</strong>: Debemos tener cuidado de los "efectos secundarios" al invocar funciones en las plantillas. Aquí solo obtenemos una URL para desplegar, pero una función puede hacer casi cualquier cosa -- ¡no quisieramos borrar nuestra base de datos (por ejemplo) solo por renderizar nuestra plantilla!</p> +</div> + +<h4 id="Actualizar_la_plantilla_base">Actualizar la plantilla base</h4> + +<p>Abre la plantilla base (<strong>/locallibrary/catalog/templates/<em>base_generic.html</em></strong>) e inserta <strong>{% url 'books' %}</strong> en el enlace URL para <strong>All books</strong>, como se muestra abajo. Esto habilitará el enlace en todas las páginas (podemos ubicar esto exitosamente en su lugar ahora que hemos creado el mapeo url "books").</p> + +<pre class="brush: python"><li><a href="{% url 'index' %}">Home</a></li> +<strong><li><a href="{% url 'books' %}">All books</a></li></strong> +<li><a href="">All authors</a></li></pre> + +<h3 id="¿Cómo_se_ve">¿Cómo se ve?</h3> + +<p>Aún no podrás ver la lista de libros, porque aún nos falta una dependencia -- el mapeo URL para las páginas de detalle de libros, que se necesita para crear los hipervínculos a los libros individuales. Mostraremos tanto la lista de libros como las vistas de detalle después de la siguiente sección.</p> + +<h2 id="Página_de_detalle_de_libros">Página de detalle de libros</h2> + +<p>La página de detalle de libro desplegará información sobre un libro específico, a la que se accede usando la URL <code>catalog/book/<em><id></em></code> (donde <code><id></code> es la clave primaria para el libro). Además de los campos en el modelo <code>Book</code> (autor, resumen, ISBN, idioma, y género), listaremos también los detalles de las copias disponibles (<code>BookInstances</code>) incluyendo su estado, fecha de devolución esperada, edición e id. Esto permitirá a nuestros lectores no solo saber sobre el libro en sí, sino también confirmar si está disponible o cuándo lo estará.</p> + +<h3 id="Mapeo_URL_2">Mapeo URL</h3> + +<p>Abre <strong>/catalos/urls.py</strong> y añade el mapeador URL <strong>'book-detail'</strong> que se muestra abajo en negrita. Esta función <code>url()</code> define un patrón, vista de detalle genérica basada en clases asociada, y un nombre.</p> + +<pre class="brush: python">urlpatterns = [ + url(r'^$', views.index, name='index'), + url(r'^books/$', views.BookListView.as_view(), name='books'), +<strong> url(r'^book/(?P<pk>\d+)$', views.BookDetailView.as_view(), name='book-detail'),</strong> +]</pre> + +<p>A diferencia de nuestros mapeadores anteriores, en este caso estamos usando nuestra expresión regular (RE) para comparar frente a un "patrón" real en lugar de una simple cadena. Lo que hace esta RE en particular es coincidir con cualquier URL que empiece por <code>book/</code>, seguido de uno o más <em>dígitos</em> (números) antes del marcador de fin de línea. Mientras se realiza la comparación, se "capturan" los dígitos y son enviados a la función de vista como un parámetro llamado <code>pk</code>.</p> + +<div class="note"> +<p><strong>Nota</strong>: Como ya se discutió antes, nuestra URL coincidente es en realidad <code>catalog/book/<digits></code> (como estamos en la aplicación <strong>catalog</strong>, se asume <code>/catalog/</code>).</p> +</div> + +<div class="warning"> +<p><strong>Importante</strong>: La vista de detalle genérica basada en clases <em>espera</em> que se le envíe un parámetro llamado pk. Si estás escribiendo tu propia vista de función, puedes usar el nombre de parámetro que quieras, o incluso enviar la información como un argumento sin nombre.</p> +</div> + +<h4 id="Una_breve_introducción_a_las_expresiones_regulares">Una breve introducción a las expresiones regulares</h4> + +<p>Las <a href="https://docs.python.org/3/library/re.html">expresiones regulares</a> son una herramienta de mapeo de patrones increíblemente poderosa. Hemos dicho poco sobre ellas hasta ahora porque estuvimos comparando con cadenas fijas en nuestras URLs (en lugar de con patrones) y porque son, francamente, bastante intuitivas e intimidantes para los principiantes.</p> + +<div class="note"> +<p><strong>Nota</strong>: ¡No te asustes! Los tipos de patrones con los que estaremos comparando son bastante simples, ¡y en muchos casos están bien documentados!</p> +</div> + +<p>Lo primero que hay que saber es que las expresiones regulares deberían ser declaradas normalmente usando la sintaxis de literal de cadena sin procesar (esto es, están encerradas así: <strong>r'<tu expresión regular va aquí>'</strong>).</p> + +<p>Las partes principales de la sintaxis que necesitarás saber para declarar las coincidencias de patrones son:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Símbolo</th> + <th scope="col">Significado</th> + </tr> + </thead> + <tbody> + <tr> + <td>^</td> + <td>Coincide con el inicio del texto</td> + </tr> + <tr> + <td>$</td> + <td>Coincide con el fin del texto</td> + </tr> + <tr> + <td>\d</td> + <td>Coincide con un dígito (0, 1, 2, ... 9)</td> + </tr> + <tr> + <td>\w</td> + <td> + <p>Concide con un caracter de palabra, ej. cualquier caracter del alfabeto en mayúscula o minúscula, dígito o guión bajo (_)</p> + </td> + </tr> + <tr> + <td>+</td> + <td> + <p>Concide con uno o más caracteres del precedente. Por ejemplo, para coincidir con uno o más dígitos usarías <code>\d+</code>. Para concidir con uno o más caracteres "a", podrías usar <code>a+</code></p> + </td> + </tr> + <tr> + <td>*</td> + <td> + <p>Concide con cero o más caracteres del precedente. Por ejemplo, para coincidir con nada o una palabra podrías usar <code>\w*</code></p> + </td> + </tr> + <tr> + <td>( )</td> + <td> + <p>Captura la parte del patrón dentro de los paréntesis. Todos los valores capturados serán enviados a la vista como parámetros sin nombre (si se captura múltiples patrones, los parámetros asociados serán enviados en el órden en que fueron declaradas las capturas).</p> + </td> + </tr> + <tr> + <td>(?P<<em>name</em>>...)</td> + <td> + <p>Captura el patrón (indicado por ...) como una variable con nombre (en este caso "name"). Los valores capturados se envían a la vista con el nombre especificado. Tu vista debe, por tanto, ¡declarar un argumento con el mismo nombre!</p> + </td> + </tr> + <tr> + <td>[ ]</td> + <td> + <p>Concide con un caracter del conjunto. Por ejemplo, [abc] coincidirá con 'a' o 'b' o 'c'. [-\w] coincidrá con el caracter '-' o con cualquier letra.</p> + </td> + </tr> + </tbody> +</table> + +<p>¡La mayoría de los caracteres restantes se pueden tomar literalmente!</p> + +<p>Consideremos algunos ejemplos reales de patrones:</p> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Patrón</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><strong>r'^book/(?P<pk>\d+)$'</strong></td> + <td> + <p>Esta es la RE usada en nuestro mapeador url. Concide con una cadena que tiene <code>book/</code> al inicio de la línea (<strong>^book/</strong>), luego tiene uno o más dígitos (<code>\d+</code>), y luego termina (sin ningún caracter que no sea un dígito antes del marcador de fin de línea).</p> + + <p>También captura todos los dígitos <strong>(?P<pk>\d+)</strong> y los envía a la vista como un parámetro llamado 'pk'. <strong>¡Los valores capturados siempre se envían como cadena!</strong></p> + + <p>Por ejemplo, esto coincidiría con <code>book/1234</code>, y enviaría una variable <code>pk='1234'</code> a la vista.</p> + </td> + </tr> + <tr> + <td><strong>r'^book/(\d+)$'</strong></td> + <td> + <p>Esta expresión coincide con las mismas URLs que el caso anterior. La información capturada se enviaría a la vista como un argumento sin nombre.</p> + </td> + </tr> + <tr> + <td><strong>r'^book/(?P<stub>[-\w]+)$'</strong></td> + <td> + <p>Esta expresión coincide con una cadena que tiene <code>book/</code> al inicio de la línea (<strong>^book/</strong>), luego tiene uno o más caracteres que son <em>o bien</em> '-' o una letra (<strong>[-\w]+</strong>), y luego termina. También captura este conjunto de caracteres y los envía a la vista como un parámetro llamado 'stub'.</p> + + <p>Este es un patrón bastante típico para un "talón". Estos talones representan claves primarias en URLs amigables basadas en palabras para la información. Podrías usar un talón si quisieras que la URL de un libro sea más informativa. Por ejemplo, <code>/catalog/book/the-secret-garden</code> en lugar de <code>/catalog/book/33</code>.</p> + </td> + </tr> + </tbody> +</table> + +<p>Puedes capturar múltiples patrones en una sola comparación, y por tanto codificar bastantes datos diferentes en una URL.</p> + +<div class="note"> +<p><strong>Nota</strong>: Como reto, considera cómo podrías codificar una url para listar todos los libros publicados en un año, mes y día en particular, y la RE que podría usarse para la comparación.</p> +</div> + +<h4 id="Enviado_opciones_adicionales_en_tus_mapeos_URL">Enviado opciones adicionales en tus mapeos URL</h4> + +<p>Una característica que no hemos usado aquí, pero que te puede resultar valiosa, es que puedes declarar y enviar <a href="https://docs.djangoproject.com/en/1.10/topics/http/urls/#views-extra-options">opciones adicionales</a> a la vista. Las opciones se declaran como un diccionario que envías como el tercer argumento sin nombre a la función <code>url()</code>. Esta estrategia puede resultar útil si quiere usar la misma vista para múltiples recursos, y enviar información para configurar su comportamiento en cada caso (abajo suministramos una plantilla diferente en cada caso).</p> + +<pre class="brush: python">url(r'^/url/$', views.my_reused_view, {'my_template_name': 'some_path'}, name='aurl'), +url(r'^/anotherurl/$', views.my_reused_view, {'my_template_name': 'another_path'}, name='anotherurl'), + +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Tanto las opciones extra como los patrones capturados con nombre se envían a la vista como argumentos <em>con nombre</em>. Si usas el <strong>mismo nombre</strong> tanto para un patrón capturado como para una opción extra, solo el valor del patrón capturado será enviado a la vista (el valor especificado para la opción extra será eliminado).</p> +</div> + +<h3 id="Vista_(basada_en_clases)_2">Vista (basada en clases)</h3> + +<p>Abre <strong>catalog/views.py</strong> y copia el siguiente código al final del archivo:</p> + +<pre class="brush: python">class BookDetailView(generic.DetailView): + model = Book</pre> + +<p>¡Eso es todo! Lo único que necesitas hacer ahora es crear una plantilla llamada <strong>/locallibrary/catalog/templates/catalog/book_detail.html</strong>, y la vista enviará la información en la base de datos para el registro del libro específico, extraído por el mapeador URL. Dentro de la plantilla puedes acceder a la lista de libros mediante la variable de plantilla llamada <code>object</code> o <code>book</code> (esto es, genéricamente, "<em><code>el_nombre_del_modelo</code></em>").</p> + +<p>Si lo necesitas puedes cambiar la plantilla usada y el nombre del objeto de contexto usado para referenciar al libro en la plantilla. Puedes también sobreescribir métodos para, por ejemplo, añadir información adicional al contexto.</p> + +<h4 id="¿Qué_sucede_si_el_registro_no_existe">¿Qué sucede si el registro no existe?</h4> + +<p>Si un registro solicitado no existe, la vista de detalle genérica basada en clases lanzará automáticamente por tí una excepción de tipo Http404 -- en producción, esto desplegará automáticamente una página apropiada de "recurso no encontrado", que puedes personalizar si lo deseas.</p> + +<p>Solo para darte una idea sobre cómo funciona esto, el fragmento de código de abajo demuestra cómo implementarías la vista basada en clases como una función, si <strong>no</strong> estuvieras usando la vista de detalle genérica basada en clases.</p> + +<pre class="brush: python">def book_detail_view(request,pk): + try: + book_id=Book.objects.get(pk=pk) + except Book.DoesNotExist: + raise Http404("Book does not exist") + + #book_id=get_object_or_404(Book, pk=pk) + + return render( + request, + 'catalog/book_detail.html', + context={'book':book_id,} + ) +</pre> + +<p>Primero, la vista intenta recuperar el registro del libro específico desde el modelo. Si esto falla, la vista debería lanzar una excepción de tipo <code>Http404</code> para indicar que el libro "no se encuentra". El último paso es, como de costumbre, llamar a <code>render()</code> con el nombre de la plantilla y la información del libro en el parámetro <code>context</code> (como un diccionario).</p> + +<div class="note"> +<p><strong>Nota</strong>: <code>get_object_or_404()</code> (que se muestra comentado arriba), es un atajo conveniente para lanzar una excepción de tipo <code>Http404</code> si el registro no se encuentra.</p> +</div> + +<h3 id="Creando_la_plantilla_de_Vista_de_Detalle">Creando la plantilla de Vista de Detalle</h3> + +<p>Crea el archivo HTML <strong>/locallibrary/catalog/templates/catalog/book_detail.html</strong> y ponle el contenido de abajo. Como se discutió antes, este es el nombre de archivo por defecto esperado por la vista de detalle genérica basada en clases (para un modelo llamado <code>Book</code> en una aplicación llamada <code>catalog</code>).</p> + +<pre class="brush: html">{% extends "base_generic.html" %} + +{% block content %} + <h1>Title: \{{ book.title }}</h1> + + <p><strong>Author:</strong> <a href="">\{{ book.author }}</a></p> <!-- author detail link not yet defined --> + <p><strong>Summary:</strong> \{{ book.summary }}</p> + <p><strong>ISBN:</strong> \{{ book.isbn }}</p> + <p><strong>Language:</strong> \{{ book.language }}</p> + <p><strong>Genre:</strong> {% for genre in book.genre.all %} \{{ genre }}{% if not forloop.last %}, {% endif %}{% endfor %}</p> + + <div style="margin-left:20px;margin-top:20px"> + <h4>Copies</h4> + + {% for copy in book.bookinstance_set.all %} + <hr> + <p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}text-danger{% else %}text-warning{% endif %}">\{{ copy.get_status_display }}</p> + {% if copy.status != 'a' %}<p><strong>Due to be returned:</strong> \{{copy.due_back}}</p>{% endif %} + <p><strong>Imprint:</strong> \{{copy.imprint}}</p> + <p class="text-muted"><strong>Id:</strong> \{{copy.id}}</p> + {% endfor %} + </div> +{% endblock %}</pre> + +<ul> +</ul> + +<div class="note"> +<p>El enlace <code>author</code> en la plantilla de arriba tiene una URL vacía porque no hemos creado aún una página de detalle de autor. Una vez que esta exista, deberías actualizar la URL así:</p> + +<pre><a href="<strong>{% url 'author-detail' book.author.pk %}</strong>">\{{ book.author }}</a> +</pre> +</div> + +<p>Aunque es un poco más larga, casi todo lo que existe en esta plantilla se ha descrito previamente:</p> + +<ul> + <li>Extendemos nuestra plantilla base y sobreescribimos el bloque "content"</li> + <li>Usamos procesamiento condicional para determinar si desplegar o no contenidos específicos</li> + <li>Usamos lazos <code>for</code> para iterar a través de listas de objetos.</li> + <li>Accedemos a los campos de contexto usando la notación de puntos (como hemos usado la vista de detalle genérica, el contexto se llama <code>book</code>; podríamos también usar "<code>object</code>")</li> +</ul> + +<p>Lo interesante que no hemos visto previamente es la función <code>book.bookinstance_set.all()</code>. Este método es "automágicamente" creado por Django para devolver el conjunto de registros de <code>BookInstance</code> asociado con un <code>Book</code> en particular.</p> + +<pre class="brush: python">{% for copy in book.bookinstance_set.all %} +<!-- code to iterate across each copy/instance of a book --> +{% endfor %}</pre> + +<p>Este método es necesario porque has declarado un campo <code>ForeignKey</code> (uno-a-muchos) únicamente en la lado "uno" de la relación. Como no haces nada para declarar la relación en el otro modelo ("muchos"), este no tiene ningún campo para obtener el conjunto de registros asociados. Para superar este problema, Django construye una función apropiadamente llamada "búsqueda reversa" que puedes usar. El nombre de la función se construye convirtiendo a minúsculas el nombre del modelo donde la <code>ForeignKey</code> fue declarada, seguido por <code>_set</code> (así, la función creada en <code>Book</code> es <code>bookinstance_set()</code>).</p> + +<div class="note"> +<p><strong>Nota</strong>: Aquí usamos <code>all()</code> para obtener todos los registros (la opción por defecto). A pesar de que puedes usar el método <code>filter()</code> para obtener un subconjunto de registros en el código, no puedes hacerlo directamente en las plantillas porque no puedes especificar argumentos para las funciones.</p> + +<p>Ten también cuidado de que si no defines un orden (en tu vista o modelo basado en clases), verás errores arrojados por el servidor de dearrollo como este:</p> + +<pre>[29/May/2017 18:37:53] "GET /catalog/books/?page=1 HTTP/1.1" 200 1637 +/foo/local_library/venv/lib/python3.5/site-packages/django/views/generic/list.py:99: UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered object_list: <QuerySet [<Author: Ortiz, David>, <Author: H. McRaven, William>, <Author: Leigh, Melinda>]> + allow_empty_first_page=allow_empty_first_page, **kwargs) +</pre> + +<p>Eso sucede porque el <a href="https://docs.djangoproject.com/en/1.10/topics/pagination/#paginator-objects">objeto paginador</a> espera ver una cláusula ORDER BY siendo ejecutada en tu base de datos subyacente. Sin ella, ¡no puede estar seguro de que los registros devueltos están en el orden correcto!</p> + +<p>Este tutorial no llegó a la <strong>Paginación</strong> (aún, pero pronto lo hará), pero como no puedes uar <code>sort_by()</code> y enviar un parámetro (el mismo con <code>filter()</code> descrito arriba) tendrás que escoger entre tres opciones:</p> + +<ol> + <li>Añadir un <code>ordering</code> dentro de una declaración <code>class Meta</code> en tu modelo.</li> + <li>Añadir un atributo <code>queryset</code> en tu vista basada en clases personalizada, especificando un <code>order_by()</code>.</li> + <li>Añadir un método <code>get_queryset</code> a tu vista basada en clases pesonalizada y también especificar el <code>order_by()</code>.</li> +</ol> + +<p>Si te decides por la opción <code>class Meta</code> para el modelo Author (probablemente no tan flexible como personalizar la vista basada en clases, pero lo suficientemente fácil), terminarás con algo como esto:</p> + +<pre>class Author(models.Model): + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + date_of_birth = models.DateField(null=True, blank=True) + date_of_death = models.DateField('Died', null=True, blank=True) + + def get_absolute_url(self): + return reverse('author-detail', args=[str(self.id)]) + + def __str__(self): + return '%s, %s' % (self.last_name, self.first_name) + +<strong> class Meta: + ordering = ['last_name']</strong></pre> + +<p>Por supuesto, el campo no tiene que ser <code>last_name</code>: podría ser cualquier otro.</p> +Y por último, pero no menos importante, deberías ordenar por un atributo/columna que tenga un índice real (único o no) en tu base de datos para evitar problemas de rendimiento. Por supuesto, esto no será necesario aquí (y probablemente nos estemos adelantando mucho) para la pequeña cantidad de libros (¡y usuarios!), pero es algo a tener en cuenta para proyectos futuros.</div> + +<h2 id="¿Cómo_se_ve_2">¿Cómo se ve?</h2> + +<p>En este punto deberíamos haber creado todo lo necesario para desplegar tanto la lista de libros como las páginas de detalles de libros. Ejecuta el servidor (<code>python3 manage.py runserver</code>) y dirígete en tu navegador a <a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>.</p> + +<div class="warning"> +<p><strong>Advertencia</strong>: No hagas click aún en ningún enlace de autor o de detalles de autores -- ¡los crearás en el reto!</p> +</div> + +<p>Haz click en el enlace <strong>All books</strong> para desplegar la lista de libros.</p> + +<p><img alt="Book List Page" src="https://mdn.mozillademos.org/files/14049/book_list_page_no_pagination.png" style="border-style: solid; border-width: 1px; display: block; height: 216px; margin: 0px auto; width: 823px;"></p> + +<p>Luego haz click en un enlace a uno de tus libros. Si todo está correcto, deberías ver algo como la siguiente pantalla.</p> + +<p><img alt="Book Detail Page" src="https://mdn.mozillademos.org/files/14051/book_detail_page_no_pagination.png" style="border-style: solid; border-width: 1px; display: block; height: 783px; margin: 0px auto; width: 926px;"></p> + +<h2 id="Paginación">Paginación</h2> + +<p>Si apenas tienes unos pocos registros, nuestra página de lista de libros se verá bien. Sin embargo, cuando llegues a las decenas o centenas de registros la página tomará progresivamente más tiempo en cargar (y tendrá demasiado contenido para navegar adecuadamente). La solución a este problema es añadir paginación a tus vistas de lista, reduciendo el número de Ítems desplegados en cada página.</p> + +<p>Django incluye un excelente soporte para paginación. Mejor aún, este está incluído en las vistas de lista genéricas basadas en clases, ¡así que no tienes que hacer mucho para habilitarlo!</p> + +<h3 id="Vistas">Vistas</h3> + +<p>Abre <strong>catalog/views.py</strong>, y añadie la línea <code>paginate_by</code> que se muestra abajo en negrita.</p> + +<pre class="brush: python">class BookListView(generic.ListView): + model = Book + <strong>paginate_by = 10</strong></pre> + +<p>Con esta adición, apenas tengas más de 10 registros la vista comenzará a paginar la información que envía a la plantilla. A las diferentes páginas se accede usando parámetros GET -- para acceder a la página 2 usarías la URL: <code>/catalog/books/?<strong>page=2</strong></code>.</p> + +<h3 id="Plantillas">Plantillas</h3> + +<p>Ahora que la información está paginada, necesitamos añadir soporte a la plantilla para desplazarse a través del conjunto de resultados. Como podríamos querer hacer lo mismo en todas las vistas de lista, lo haremos de una forma en la que puede ser añadida a la plantilla base.</p> + +<p>Abre <strong>/locallibrary/catalog/templates/<em>base_generic.html </em></strong>y copia el siguiente bloque <code>pagination</code> debajo de nuestro bloque <code>content</code> (resaltado abajo en negrita). El código primero revisa si la paginación está habilitada en la página actual. Si lo está, añade enlaces <code>next</code> y <code>previous</code> apropiados (y el número de la página actual).</p> + +<pre class="brush: python"><strong>{% block content %}{% endblock %}</strong> + +{% block pagination %} + {% if is_paginated %} + <div class="pagination"> + <span class="page-links"> + {% if page_obj.has_previous %} + <a href="\{{ request.path }}?page=\{{ page_obj.previous_page_number }}">previous</a> + {% endif %} + <span class="page-current"> + Page \{{ page_obj.number }} of \{{ page_obj.paginator.num_pages }}. + </span> + {% if page_obj.has_next %} + <a href="\{{ request.path }}?page=\{{ page_obj.next_page_number }}">next</a> + {% endif %} + </span> + </div> + {% endif %} +{% endblock %} </pre> + +<p><code>page_obj</code> es un objeto <a href="https://docs.djangoproject.com/en/1.10/topics/pagination/#paginator-objects">Paginator</a> que existirá si se usa la paginación en la página actual. Te permite obtener toda la información sobre la página actual, páginas anteriores, cuántas páginas hay, etc.</p> + +<p>Usamos <code>\{{ request.path }}</code> para obtener la URL de la página actual para crear a su vez los enlaces de paginación. Esto es útil, porque es independiente del objeto que estamos paginando.</p> + +<p>¡Eso es todo!</p> + +<h3 id="¿Cómo_se_ve_3">¿Cómo se ve?</h3> + +<p>La captura de pantalla de abajo muestra cómo se ve la paginación -- si no has ingresado más de 10 títulos en tu base de datos, puedes probarlo más fácilmente reduciendo el número especificado en la línea <code>paginate_by</code> en tu archivo <strong>catalog/views.py</strong>. Para obtener el resultado de abajo lo cambiamos a <code>paginate_by = 2</code>.</p> + +<p>Los enlaces de paginación se muestran en la parte de abajo, con enlaces de next/previous desplegados dependiendo de en qué página estés</p> + +<p><img alt="Book List Page - paginated" src="https://mdn.mozillademos.org/files/14057/book_list_paginated.png" style="border-style: solid; border-width: 1px; display: block; height: 216px; margin: 0px auto; width: 924px;"></p> + +<h2 id="Rétate_a_tí_mismo">Rétate a tí mismo</h2> + +<p>El reto en este artículo es crear las vistas de lista y detalle para autores, que se requieren para completar el proyecto. Estas deberían estar disponibles en las siguientes URLs:</p> + +<ul> + <li><code>catalog/authors/</code> — La lista de todos los autores.</li> + <li><code>catalog/author/<em><id></em></code><em> </em>— La vista de detalle para el autor específico con un valor en el campo de clave primaria de <em><code><id></code></em></li> +</ul> + +<p>El código requerido para los mapeadores URL y las vistas debería ser virtualmente idéntico a las vistas de lista y detalle para <code>Book</code> que creamos arriba. Las plantillas serán diferentes, pero tendrán un comportamiento similar.</p> + +<div class="note"> +<p><strong>Nota</strong>:</p> + +<ul> + <li>Una vez que has creado el mapeador URL para la página de lista de autores, necesitarás también actualizar el enlace <strong>All authors</strong> en la plantilla base. Sigue el <a href="#Update_the_base_template">mismo proceso</a> que hicimos cuando actualizamos el enlace <strong>All books</strong>.</li> + <li>Una vez que has creado el mapeador URL para la página de detalle de autores, deberías también actualizar la <a href="#Creating_the_Detail_View_template">plantilla de vista de detalle de libros </a>(<strong>/locallibrary/catalog/templates/catalog/book_detail.html</strong>) de modo que el enlace de autor apunte a tu nueva página de detalle de autor (en lugar de ser una URL vacía). La línea cambiará para añadir la etiqueta de plantilla que se muestra en negrita abajo.</li> +</ul> + +<pre class="brush: html"><p><strong>Author:</strong> <a href="<strong>{% url 'author-detail' book.author.pk %}</strong>">\{{ book.author }}</a></p> </pre> +</div> + +<p>Cuando termines, tus páginas deberían lucir similares a las capturas de pantalla de abajo.</p> + +<p><img alt="Author List Page" src="https://mdn.mozillademos.org/files/14053/author_list_page_no_pagination.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<ul> +</ul> + +<p><img alt="Author Detail Page" src="https://mdn.mozillademos.org/files/14055/author_detail_page_no_pagination.png" style="border-style: solid; border-width: 1px; display: block; height: 358px; margin: 0px auto; width: 825px;"></p> + +<ul> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>Felicitaciones, ¡la funcionalidad de nuestra biblioteca básica está ahora completa!</p> + +<p>En este artículo hemos aprendido cómo usar las vistas genéricas basadas en clases de lista y detalle, y las hemos usado para crear páginas para ver nuestros libros y autores. Sobre la marcha hemos aprendido sobre coincidencia de patrones con expresiones regulares, y cómo puedes enviar información desde las URLs a tus vistas. Hemos también aprendido unos cuantos trucos más para usar plantillas. Por último hemos mostrado cómo paginar vistas de lista, de modo que nuestras listas sean manejables incluso si tenemos muchos registros.</p> + +<p>En los siguientes artículos extenderemos esta biblioteca para añadir soporte para cuentas de usuario, y así demostrar la autenticación de usuarios, permisos, sesiones y formularios.</p> + +<h2 id="Mira_también">Mira también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/class-based-views/generic-display/">Vistas genéricas basadas en clases incluídas</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/class-based-views/generic-display/">Vistas genéricas de despliegue</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/class-based-views/intro/">Introducción a las vistas basadas en clases</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/templates/builtins">Etiquetas de plantilla y filtros incluídos</a> (Django docs).</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/pagination/">Paginación</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Home_page", "Learn/Server-side/Django/Sessions", "Learn/Server-side/Django")}}</p> + +<p> </p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/home_page/index.html b/files/es/learn/server-side/django/home_page/index.html new file mode 100644 index 0000000000..4c849e8917 --- /dev/null +++ b/files/es/learn/server-side/django/home_page/index.html @@ -0,0 +1,403 @@ +--- +title: 'Tutorial de Django Parte 5: Creación de tu página de inicio' +slug: Learn/Server-side/Django/Home_page +translation_of: Learn/Server-side/Django/Home_page +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django")}}</div> + +<p class="summary">Estamos listos ahora para añadir el código para mostrar nuestra primera página entera — una página de inicio del sitio web de la <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">BibliotecaLocal</a> que muestra cuántos registros tenemos de cada tipo de modelo y proporciona una barra lateral con enlaces de navegación a nuestras otras páginas. Por el camino ganaremos experiencia práctica en escritura básica de mapeos de URL y vistas, obtención de resgistros de la base de datos y uso de plantillas.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td>Lee la <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Introducci%C3%B3n">Introducción a Django</a>. Completa los tópicos previos del tutorial (incluyendo <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a>).</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Entender cómo crear mapas url y vistas simples (sin información codificada en la URL), y cómo obtener información desde los modelos y crear plantillas.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Visión_General">Visión General</h2> + +<p>Ahora que hemos definindo nuestros modelos y hemos creado los primeros registros en la librería para trabajar, es hora de escribir código para presentar información a los usuarios. Lo primero que necesitamos es determinar que información queremos mostrar en nuestras páginas, y definir una URL apropiada hacia estos recursos. Vamos a necesitar crear el mapeador de URLs, las vistas y plantillas para mostrar estas páginas.</p> + +<p>El siguiente diagrama es un recordatorio del principal flujo de datos y cosas necesarias para ser implementadas cuando se maneja una respuesta/petición en HTTP.<br> + Los principales elementos que necesitamos crear son:</p> + +<ul> + <li>Mapeadores URL para reenviar las URLs admitidas (y cualquier información codificada en las URLs) a las funciones de vista apropiadas.</li> + <li>Funciones de vista para obtener los datos solicitados desde los modelos, crear una página HTML que muestre los datos, y devolverlo al usuario para que lo vea en el navegador.</li> + <li>Plantillas usadas por las vistas para renderizar los datos.</li> +</ul> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13931/basic-django.png" style="display: block; margin: 0px auto;"></p> + +<p>Como verás en la siguiente sección, vamos a tener 5 páginas para mostrar, que es mucho que documentar en un artículo. Por lo tanto, en la mayor parte de este artículo nos concentraremos en mostrar como implementar solo la página de inicio (nos moverermos a otras páginas en un artículo subsecuente). Esto debe darte un buen entendimiento de extremo a extremo sobre como los mapeadores URL, vistas y modelos funcionan en la práctica.</p> + +<h2 id="Definiendo_el_recurso_URL">Definiendo el recurso URL</h2> + +<p>Como esta versión de <em>LocalLibrary</em> es escencialmente solo de lectura para usuarios finales, debemos proveer una página de llegada para el sitio (una página de inicio), y páginas que <em>desplieguen</em> listas y vistas detalladas para libros y autores. </p> + +<p>Las URL que vamos a necesitar para nuestras páginas son:</p> + +<ul> + <li><code>catalog/</code> — La página home/index.</li> + <li><code>catalog/books/</code> — La lista de todos los libros.</li> + <li><code>catalog/authors/</code> — La lista de todos los autores.</li> + <li><code>catalog/book/<em><id></em></code> — La vista detallada para el libro específico con un campo de clave primaria de <code><em><id></em></code> (el valor por defecto). Así por ejemplo, <code>/catalog/book/3</code>, para el tercer libro añadido.</li> + <li><code>catalog/author/<em><id></em></code><em> </em>— La vista detallada para el autor específico con un campo de clave primaria llamada <em><code><id>. </code></em>Así por ejemplo, <code>/catalog/author/11</code>, para el 11vo autor añadido.</li> +</ul> + +<p>La tres primeras URLs son usadas para listar el índice, los libros y autores. Esto no codifica ninguna información adicional, y mientras los resultados retornados dependerán del contenido en la base de datos, las consultas que se ejecutan para obtener la información siempre serán las mismas.</p> + +<p>En contraste las 2 URLs finales son usadas para mostrar información detallada sobre un libro o autor específico — estas codifican la identidad de los ítemes a mostrar en la URL (mostrado arriba como <code><em><id></em></code> ). El mapeador URL puede extraer la información codificada y pasársela a la vista, donde se detarminará que información extraer de la base de datos. Al codificar la información en nuestra URL solo necesitamos un mapeador de URL, una vista, y un plantilla para manejar cada libro (o autor). </p> + +<div class="note"> +<p><strong>Nota</strong>: Django te permite construir tus URLs de cualquier forma que quieras — puedes codificar información en el cuerpo de la URL como se muestra arriba o usando la obtención de parámetros <code>GET</code> de la URL(e.j. <code>/book/?id=6</code>). Culquier enfoque que uses, las URLs deben mantenerse limpias, lógicas y legibles (<a href="https://www.w3.org/Provider/Style/URI">observa el consejo del W3C aquí</a>).<br> + <br> + La documentación Django tiende a recomendar la codificación de información en el cuerpo de la URL, una práctica que ellos creen que promueve mejores diseños de URL.</p> +</div> + +<p>Como discutimos en la introducción, el resto de este articulo describe como construimos la página index.</p> + +<h2 id="Creando_la_página_index">Creando la página index</h2> + +<p>La primera página que crearemos será la página index (<code>catalog/</code>). Esto desplegará un pequeño HTML estático, junto con algunos "contadores" calculados de diferentes registros en la base de datos. Para hacer este trabajo tendremos que crear un mapeador URL, una vista y una plantilla. </p> + +<div class="note"> +<p><strong>Nota</strong>: Vale la pena prestar un poco de atención extra en esta sección. La mayoría del contenido es común para todas las páginas.</p> +</div> + +<h3 id="Mapeador_URL">Mapeador URL</h3> + +<p>Hemos creado un archivo básico <strong>/catalog/urls.py</strong> para nuestra aplicación catálogo cuando creamos el <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">esqueleto del sitio Web</a>. Las URLs de la aplicación catálogo fueron incluidas dentro del proyecto con un mapeador a <code>catalog/</code>, entonces las URLs que llegan a este mapeador deben empezar con<code> catalog/</code> (el mapeador funciona sobre todos los string en la URL después de la barra diagonal).</p> + +<p>Abra <strong>urls.py</strong> y pegue la línea en negrita que aparece a continuación. </p> + +<pre class="brush: python">urlpatterns = [ +<strong> url(r'^$', views.index, name='index'),</strong> +]</pre> + +<p>Esta función <code>url()</code> define un patrón URL (<code>r'^$'</code>), y una función vista que será llamada si el patrón es detectado (<code>views.index</code> — una función llamada <code>index()</code> en <strong>views.py</strong>). El patrón URL es una <a href="https://docs.python.org/3/library/re.html">expresión regular de Python</a> (ER). Hablaremos un poco más sobre ERs más adelante en este tutorial, pero para este caso todo lo que necesitas saber es que en una ER de ^$ el patrón coincidirá con una cadena vacía (^ es un marcador de inicio de cadena y $ es un marcador de fin de cadena). </p> + +<div class="note"> +<p><strong>Nota: </strong>Nota que en <strong>/locallibrary/locallibrary/urls.py</strong> </p> + +<pre><code>urlpatterns += [ + url(r'^catalog/', include('catalog.urls')), +]</code></pre> + +<p>La expresión regular en este caso no tienen un <code>$</code> (caracter asignado a fin-de-cadena) pero incluye una barra diagonal. Siempre cuando Django se encuentra con <code>include()</code> (<a href="https://docs.djangoproject.com/en/1.11/ref/urls/#django.conf.urls.include" title="django.conf.urls.include"><code>django.conf.urls.include()</code></a>), corta cualquier parte de la URL que coincida hasta este punto y envía el resto de la cadena para incluir la configuración URL para el siguiente procesamiento.</p> + +<p>La URL coincidente es en realidad <code>catalog/</code> + <cadena vacía> ( <code>/catalog/</code> es asumida ya que include() fue el método usado). Nuestra primera función vista será llamada si recibimos una consulta HTTP con una URL de <code>/catalog/</code>.</p> +</div> + +<p>La función <code>url()</code> también especifica un parámetro <code>name</code>, que identifica de manera única <em>este</em> mapeador de URL particular. Puedes usar este nombre para "revertir" el mapeador — para crear dinámicamente una URL que apunta al el recurso que el mapeador esta diseñado para manejar. Por ejemplo, con esto hecho ahora podemos enlazar nuestra página inicio creando el siguiente enlace en nuestra plantilla:</p> + +<pre class="brush: html"><a href="<strong>{% url 'index' %}</strong>">Home</a>.</pre> + +<div class="note"> +<p><strong>Nota</strong>: Por su puesto podemos codificar a fuerza bruta el link anterior (e.j. <code><a href="<strong>/catalog/</strong>">Home</a></code>), pero entonces si cambiamos el patrón para nuestra página de inicio (e.j. a <code>/catalog/index</code>) la plantilla no podrá seguir enlazando correctamente. Usar un mapeador de url es mucho más flexible y robusto!</p> +</div> + +<h3 id="Vista_basada-en-funciones">Vista (basada-en-funciones)</h3> + +<p>Una vista es una función que procesa una consulta HTTP, trae datos desde la base de datos cuando los necesita, genera una página HTML renderizando estos datos unando una plantilla HTML, y luego retorna el HTML en una respuesta HTTP para ser mostrada al usuario. La vista del índice sigue este modelo — extrae información sobre cuantos <code>Book</code>, <code>BookInstance</code>, <code>BookInstance</code> disponibles y registros <code>Author</code> tenemos en la base de datos, y los pasa a una plantilla para mostrarlos.</p> + +<p>Abre <strong>catalog/views.py</strong>, y nota que el archivo ya importa el atajo de la función <a href="https://docs.djangoproject.com/en/1.10/topics/http/shortcuts/#django.shortcuts.render">render()</a> que genera archivos HTML usando una plantilla y datos. </p> + +<pre class="brush: python">from django.shortcuts import render + +# Create your views here. +</pre> + +<p>Copia el siguiente código al final del archivo. La primera linea importa las clases de los modelos que usaremos para acceder a los datos en todas nuestras vistas.</p> + +<pre class="brush: python">from .models import Book, Author, BookInstance, Genre + +def index(request): + """ + Función vista para la página inicio del sitio. + """ + # Genera contadores de algunos de los objetos principales + num_books=Book.objects.all().count() + num_instances=BookInstance.objects.all().count() + # Libros disponibles (status = 'a') + num_instances_available=BookInstance.objects.filter(status__exact='a').count() + num_authors=Author.objects.count() # El 'all()' esta implícito por defecto. + + # Renderiza la plantilla HTML index.html con los datos en la variable contexto + return render( + request, + 'index.html', + context={'num_books':num_books,'num_instances':num_instances,'num_instances_available':num_instances_available,'num_authors':num_authors}, + )</pre> + +<p>La primera parte de la función vista extrae contadores de registros usando el atributo <code>objects.all()</code> en las clases del modelo. Tambien obtiene una lista de los objetos <code>BookInstance</code> que tienen un valor del campo status de 'a' (Disponible). Puedes encontrar un poco más sobre cómo acceder desde modelos en nuestro tutorial previo (<a href="/en-US/docs/Learn/Server-side/Django/Models#Searching_for_records">Django Tutorial Part 3: Usando modelos > Buscando registros</a>).</p> + +<p>Al final de la función invocamos a la función <code>render()</code> para crear y retornar una página HTML como una respuesta (esta función atajo envuelve una serie, simplicando este caso de uso muy común). Esta recibe como parametros el objeto <code>request original</code> (una <code>ConsultaHttp</code>), una plantilla HTML con marcadores para los datos, y una variable de <code>contexto</code> (un diccionario Python que contiene los datos que serán insertados en esos marcadores). </p> + +<p>Hablaremos más sobre la plantilla y la variable de contexto en la siguiente sección; vamos a crear nuestra plantilla para así de hecho mostrarle algo al usuario!</p> + +<h3 id="Plantilla">Plantilla</h3> + +<p>Una plantilla es un archivo de texto que determina la estructura o diseño de un archivo (como una página HTML), con marcadores usados para representar el contenido real. Django automaticamente buscará plantillas en un directorio llamado '<strong>templates</strong>' de su aplicación. Así por ejemplo, en la vista índice que acabamos de agregar, la función <code>render()</code> esperará poder encontrar el archivo <strong>/locallibrary/catalog/templates/<em>index.html</em></strong>, y entregará un error si el archivo no puede ser encontrado. Puede ver esto si guarda los cambios anteriores y vuelve a su navegador — accediendo a <code>127.0.0.1:8000</code> ahora le entregará un mensaje de error bastante intuitivo "TemplateDoesNotExist at /catalog/", más otros detalles.</p> + +<div class="note"> +<p><strong>Nota</strong>: Django buscará en una serie de lugares por plantillas, basandose en su archivo de configuraciones de proyectos (buscar en su aplicación instalada es una configuración por defecto!). Puede encontrar más sobre como Django encuentra plantillas y qué formatos de plantillas soporta <a href="https://docs.djangoproject.com/en/1.10/topics/templates/">Templates</a> (Django docs).</p> +</div> + +<h4 id="Plantillas_extendidas">Plantillas extendidas</h4> + +<p>La plantilla índice va a necesitar marcado HTML estándar para la cabecera y el cuerpo, junto con secciones para navegar (a otras páginas en el sitio que todavía no hemos creado) y para mostrar algún texto introductorio y nuestros datos de libro. La mayoría de este texto (el HTML y la estructura de navegación) será el mismo para cada página en nuestro sitio. En lugar de obligar a los desarrolladores a duplicar este texto en cada página, el lenguaje de plantillas de Django le permite declarar una plantilla base y luego extenderla, reemplazando solo las porciones que son distintos para cada página específica. </p> + +<p>Por ejemplo, un plantilla base <strong>base_generic.html</strong> podría verse como el texto de abajo. Como puedes ver, este contiene algo de HTML "común" y secciones para el título, barra lateral, y contendio marcados usando las etiquetas de plantillas llamadas <code>block</code> y <code>endblock</code> (mostradas en negrita). Los bloques pueden estar vacíos, o tener contenido que será usado "por defecto" para páginas derivadas.</p> + +<div class="note"> +<p><strong>Nota</strong>: Las etiquetas de plantilla son como funciones que puede usar en una plantilla para recorrer listas, realizar operaciones condicionales basadas en el valor de una variable, etc. Además de las etiquetas de plantilla, la sintaxis de plantilla te permite referenciar variables de plantilla (que son pasadas en la plantilla desde la vista) y usar <em>filtros de plantilla</em>, que reformatean las variables (por ejemplo, establecer una cadena en minúsculas).</p> +</div> + +<pre class="brush: html"><!DOCTYPE html> +<html lang="en"> +<head> + <strong>{% block title %}</strong><title>Local Library</title><strong>{% endblock %}</strong> +</head> + +<body> + <strong>{% block sidebar %}</strong><!-- insert default navigation text for every page --><strong>{% endblock %}</strong> + <strong>{% block content %}</strong><!-- default content text (typically empty) --><strong>{% endblock %}</strong> +</body> +</html> +</pre> + +<p>Cuando queremos definir una plantilla para una vista en particular, primero especificamos la plantila base (con la etiqueta de plantilla <code>extends</code> — vea el código siguiente). Si ahí hay alguna seccón que queremos reemplazar en la plantilla declaramos esto, usando secciones <code>block</code>/<code>endblock</code> idénticas a las usadas en la plantilla base.</p> + +<p>Por ejemplo, el fragmento de código que sigue muestra como usar la etiqueta de plantilla <code>extends</code>, y sobrescribe el bloque <code>content</code>. El HTML final producido tendrá todo el HTML y la estructura defininda en la plantilla base (incluyendo el contenido por defecto que ha definido dentro del bloque <code>title</code>), pero con tu nuevo bloque <code>content</code> insertado en lugar del que venía por defecto.</p> + +<pre class="brush: html">{% extends "base_generic.html" %} + +{% block content %} +<h1>Local Library Home</h1> +<p>Welcome to <em>LocalLibrary</em>, a very basic Django website developed as a tutorial example on the Mozilla Developer Network.</p> +{% endblock %}</pre> + +<h4 id="La_plantilla_base_de_LocalLibrary">La plantilla base de LocalLibrary</h4> + +<p>La plantilla base que pensamos usar para el siito web <em>LocalLibrary </em>se muestra abajo. Como puedes ver, contiene algo de HTML y bloques definidos para <code>title</code>, <code>sidebar</code> y <code>content</code>. Tenemos un título por defecto (que podríamos querer cambiar) y una barra lateral por defecto con enlaces a listas de todos los libros y autores (que probablemente no querramos cambiar, pero hemos dejado abierta la posibilidad de hacerlo si es necesario, poniéndolo en un bloque).</p> + +<div class="note"> +<p><strong>Nota</strong>: También introducimos dos etiquetas de plantilla adicionales: <code>url</code> y <code>load static</code>. Se discute sobre ellas en secciones posteriores.</p> +</div> + +<p>Crea un nuevo archivo -- <strong>/locallibrary/catalog/templates/<em>base_generic.html</em></strong> -- y pon en él el siguiente contenido:</p> + +<pre class="brush: html"><!DOCTYPE html> +<html lang="en"> +<head> + + {% block title %}<title>Local Library</title>{% endblock %} + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"> + <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script> + <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script> + + <!-- Add additional CSS in static file --> + {% load static %} + <link rel="stylesheet" href="{% static 'css/styles.css' %}"> +</head> + +<body> + + <div class="container-fluid"> + + <div class="row"> + <div class="col-sm-2"> + {% block sidebar %} + <ul class="sidebar-nav"> + <li><a href="{% url 'index' %}">Home</a></li> + <li><a href="">All books</a></li> + <li><a href="">All authors</a></li> + </ul> + {% endblock %} + </div> + <div class="col-sm-10 "> + {% block content %}{% endblock %} + </div> + </div> + + </div> +</body> +</html></pre> + +<p>La plantilla usa (e incluye) JavaScript y CSS desde <a href="http://getbootstrap.com/">Bootstrap</a> para mejorar el diseño y la presentación de la página HTML. Usar Bootstrap u otro framework web del lado del cliente es una manera rápida de crear una página atractiva que puede escalarse bien en diferentes tamaños de navegador, y también nos permite concentrarnos en la presentación de la página sin tener que entrar en ninguno de los detalles -- ¡queremos enfocarnos nada más en el código del lado del servidor aquí!</p> + +<p>La plantilla base también hace referencia a un archivo css local (<strong>styles.css</strong>) que brinda algo más de estilo. Crea <strong>/locallibrary/catalog/static/css/styles.css</strong> y pon en él el siguiente contenido:</p> + +<pre class="brush: css">.sidebar-nav { + margin-top: 20px; + padding: 0; + list-style: none; +}</pre> + +<h4 id="La_plantilla_index">La plantilla index</h4> + +<p>Crea el archivo HTML <strong>/locallibrary/catalog/templates/<em>index.html</em></strong> y pon en él el contenido que se muestra abajo. Como puedes ver, extendemos nuestra plantilla base en la primera línea, y luego reemplazamos el bloque <code>content</code> por defecto con uno nuevo para esta plantilla.</p> + +<pre class="brush: html">{% extends "base_generic.html" %} + +{% block content %} +<h1>Local Library Home</h1> + + <p>Welcome to <em>LocalLibrary</em>, a very basic Django website developed as a tutorial example on the Mozilla Developer Network.</p> + +<h2>Dynamic content</h2> + + <p>The library has the following record counts:</p> + <ul> + <li><strong>Books:</strong> <strong>\{{ num_books }}</strong></li> + <li><strong>Copies:</strong> <strong>\{{ num_instances }}</strong></li> + <li><strong>Copies available:</strong> <strong>\{{ num_instances_available }}</strong></li> + <li><strong>Authors:</strong> <strong>\{{ num_authors }}</strong></li> + </ul> + +{% endblock %}</pre> + +<p>En la sección <em>Dynamic content</em> hemos declarado marcadores de posición (<em>variables de plantilla</em>) para la información que quisimos incluir desde la vista. Las variables se marcan usando la sintaxis de "doble corchete" o "llaves" (ver lo que está en negrita arriba).</p> + +<div class="note"> +<p><strong>Nota:</strong> Puedes reconocer fácilmente si estás trabajando con variables de plantilla o con etiquetas de plantilla (funciones) porque las variables tienen llaves dobles (<code>\{{ num_books }}</code>) mientras que las etiquetas están encerradas entre llaves simples con signos de porcentaje (<code>{% extends "base_generic.html" %}</code>).</p> +</div> + +<p>Lo importante de todo esto es que estas variables se nombran con las claves que enviamos dentro del diccionario <code>context</code> en la función <code>render()</code> de nuestra vista (mira abajo); estas variables serán reemplazadas por sus valores asociados cuando la plantilla sea renderizada.</p> + +<pre class="brush: python">return render( + request, + 'index.html', + context={'<strong>num_books</strong>':num_books,'<strong>num_instances</strong>':num_instances,'<strong>num_instances_available</strong>':num_instances_available,'<strong>num_authors</strong>':num_authors}, +)</pre> + +<h4 id="Referenciando_archivos_estáticos_en_las_plantillas">Referenciando archivos estáticos en las plantillas</h4> + +<p>Es probable que uses recursos estáticos en tu proyecto, incluyendo JavaScript, CSS e imágenes. Debido a que la ubicación de estos archivos podría ser desconocida (o podría cambiar), Django te permite especificar la ubicación de los mismos dentro de tus plantillas de forma relativa al parámetro global <code>STATIC_URL</code> (el sitio web esqueleto por defecto establece el valor de <code>STATIC_URL</code> a '<code>/static/</code>', pero puedes elegir alojar los archivos en una red de distribución de contenidos o en cualquier otro lugar).</p> + +<p>Dentro de la plantilla, primero llamas a la etiqueta de plantilla <code>load</code> especificando "static" para añadir esta biblioteca de plantilla (como se muestra abajo). Luego de que static se carga, puedes usar la etiqueta de plantilla <code>static</code> especificando la URL relativa del archivo de interés.</p> + +<pre class="brush: html"> <!-- Add additional CSS in static file --> +{% load static %} +<link rel="stylesheet" href="{% static 'css/styles.css' %}"></pre> + +<p>Si quisieras podrías añadir una imagen a la página de forma similar. Por ejemplo:</p> + +<pre class="brush: html">{% load static %} +<img src="{% static 'catalog/images/local_library_model_uml.png' %}" alt="My image" style="width:555px;height:540px;"/> +</pre> + +<div class="note"> +<p><strong>Nota:</strong> Los cambios de arriba especifican dónde se localizan los archivos, pero Django no los sirve por defecto. Si bien habilitamos este servicio para el servidor web de desarrollo en el mapeador URL global (<strong>/locallibrary/locallibrary/urls.py</strong>) cuando <a href="https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&cad=rja&uact=8&ved=0ahUKEwiq2o-V3PXbAhVM0FMKHcNzAkcQFggnMAA&url=https%3A%2F%2Fdeveloper.mozilla.org%2Fes%2Fdocs%2FLearn%2FServer-side%2FDjango%2Fskeleton_website&usg=AOvVaw2VIIkwGelK5OnECR-4u4sU">creamos el esqueleto del sitio web</a>, aún necesitarás configurar este servicio para producción. Hablaramos de esto más tarde.</p> +</div> + +<p>Para mayor información sobre el trabajo con archivos estáticos revisa <a href="https://docs.djangoproject.com/en/1.10/howto/static-files/">Managing static files</a> (Django docs).</p> + +<h4 id="Enlazando_con_URLs">Enlazando con URLs</h4> + +<p>En la plantilla base de arriba se introdujo la etiqueta de plantilla <code>url</code>.</p> + +<pre class="brush: python"><li><a href="{% url 'index' %}">Home</a></li> +</pre> + +<p>Esta etiqueta toma el nombre de una función <code>url()</code> llamada en tu archivo <strong>urls.py,</strong> y valores para cualquier argumento que la vista asociada recibirá desde tal función, y devuelve una URL que puedes usar para enlazar con el recurso.</p> + + + +<h4 id="Configurando_adonde_buscar_las_plantillas">Configurando adonde buscar las plantillas</h4> + +<p>Para que Django encuentre los archivos de plantillas es necesario editar el archivo settings.py agregando el directorio donde creamos nuestras plantillas en el objeto TEMPLATES, como indica la linea en negrita a continuación:</p> + +<pre class="brush: python">TEMPLATES = [ + { + 'BACKEND': 'django.template.backends.django.DjangoTemplates', + 'DIRS': [ +<strong> os.path.join(BASE_DIR, 'templates'), +</strong> ], + 'APP_DIRS': True, + 'OPTIONS': { + 'context_processors': [ + 'django.template.context_processors.debug', + 'django.template.context_processors.request', + 'django.contrib.auth.context_processors.auth', + 'django.contrib.messages.context_processors.messages', + ], + }, + }, +]</pre> + +<h2 id="¿Cómo_se_ve">¿Cómo se ve?</h2> + +<p>En este punto deberíamos haber creado todo lo necesario para desplegar la página index. Corre el servidor (<code>python3 manage.py runserver</code>) y dirige tu navegador a <a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>. Si todo se configuró correctamente, tu sitio debería verse similar a la siguiente captura de pantalla.</p> + +<p><img alt="Index page for LocalLibrary website" src="https://mdn.mozillademos.org/files/14045/index_page_ok.png" style="border-style: solid; border-width: 1px; display: block; height: 356px; margin: 0px auto; width: 874px;"></p> + +<div class="note"> +<p><strong>Nota:</strong> Aún no podrás usar los enlaces <strong>All books</strong> y <strong>All authors</strong> porque las URLs, vistas y plantillas para dichas páginas no se han definido (al momento solo hemos insertado marcadores de posición para esos enlaces en la plantilla <code>base_generic.html</code>).</p> +</div> + +<h2 id="Rétate_a_tí_mismo">Rétate a tí mismo</h2> + +<p>Aquí hay un par de tareas para probar tu familiaridad con consultas a modelos, vistas y plantillas.</p> + +<ol> + <li>Declara un nuevo bloque <em>title</em> en la plantilla <em>index</em> y cambia el título de la página para coincidir con esta página en particular.</li> + <li>Modifica la vista para generar un conteo de géneros y otro de libros que contengan una palabra en particular (no sensible a mayúsculas y minúsculas) y luego añade estos campos a la plantilla.</li> +</ol> + +<ul> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>Hemos creado la página de inicio para nuestro sitio -- una página HTML que despliega algunos conteos de registros de la base de datos y contiene enlaces a otras de nuestras páginas que aún nos faltan por crear. Sobre la marcha hemos adquirido mucha información fundamental sobre mapeadores URL, vistas, consultas a la base de datos usando nuestros modelos, cómo enviar información a una plantilla desde nuestra vista, y cómo crear y extender plantillas.</p> + +<p>En nuestro siguiente artículo nos basaremos en nuestro conocimiento para crear las otras cuatro páginas.</p> + +<h2 id="Mira_también">Mira también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/intro/tutorial03/">Escribiendo tu primera aplicación Django, parte 3: Vistas y Plantillas</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/http/urls/">Despachador URL</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/http/views/">Funciones de vista</a> (DJango docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/templates/">Plantillas</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/howto/static-files/">Administrando archivos estáticos</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/http/shortcuts/#django.shortcuts.render">Funciones atajo de Django</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django")}}</p> + + + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a><a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog"> </a></li> +</ul> diff --git a/files/es/learn/server-side/django/index.html b/files/es/learn/server-side/django/index.html new file mode 100644 index 0000000000..6a33f3e0be --- /dev/null +++ b/files/es/learn/server-side/django/index.html @@ -0,0 +1,66 @@ +--- +title: Framework Web Django (Python) +slug: Learn/Server-side/Django +tags: + - Aprendizaje + - Codificación de scripts + - Principiante + - Programación lado servidor + - Python + - django + - introducción +translation_of: Learn/Server-side/Django +--- +<div>Django es un framework web extremadamente popular y completamente funcional, escrito en Python. El módulo muestra por qué Django es uno de los frameworks de servidores web más populares, cómo configurar un entorno de desarrollo y cómo empezar a usarlo para crear tus propias aplicaciones web.</div> + +<h2 id="Requisitos_Previos">Requisitos Previos</h2> + +<p>Antes de comenzar este módulo no es necesario tener ningún conocimiento de Django. Tendrás que entender que son la programación web de lado servidor y los frameworks web, idealmente leyendo los temas en nuestro módulo <a href="/en-US/docs/Learn/Server-side/First_steps">Primeros pasos en la programación de lado servidor de sitios web.</a></p> + +<p>Se recomienda un conocimiento general de los conceptos de programación y <a href="/en-US/docs/Glossary/Python">Python</a>, pero no es esencial para entender los conceptos básicos</p> + +<div class="note"> +<p><strong>Nota</strong>: Python es uno de los lenguajes de programación más fáciles de leer y entender para los principiantes. Dicho esto, si desea comprender mejor este módulo, hay numerosos libros y tutoriales gratuitos disponibles en Internet (los nuevos programadores pueden querer ver la página de <a href="https://wiki.python.org/moin/BeginnersGuide/NonProgrammers">Python for Non Programmers</a> en el wiki de python.org.</p> +</div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="/es/docs/Learn/Server-side/Django/Introducci%C3%B3n">Introducción a Django</a></dt> + <dd>En este primer artículo de Django respondemos a la pregunta "¿Qué es Django?" y te dará una visión general de lo que hace a este framework web especial. Vamos a esbozar las principales características incluyendo algunas de las funciones avanzadas que no tendremos tiempo de cubrir en detalle en este módulo. También te mostraremos algunos de los principales bloques de construcción de una aplicación de Django, para darte una idea de lo que puedes hacer antes de que continúes configurándolo y comiences a jugar.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/development_environment">Puesta en marcha de un entorno de desarrollo de Django</a></dt> + <dd>Ahora que sabes qué es y para qué sirve Django, te mostraremos cómo configurar y probar un entorno de desarrollo Django en Windows, Linux(Ubuntu), y Mac OS X. Cualquiera que sea el sistema operativo común que estés utilizando, este articulo deberia de ofrecerte lo necesario para iniciarte en el desarrollo de aplicaciones en Django.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: Sitio web "Biblioteca Local"</a></dt> + <dd>El primer articulo de nuestra serie de tutoriales explica lo que se aprenderá y proporciona una descripcion general del sitio web de ejemplo "Biblioteca Local" en el cual trabajaremos y evolucionaremos en articulos posteriores.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creación del esqueleto de un sitio web</a></dt> + <dd>Este artículo muestra cómo crear el "esqueleto" de un proyecto de sitio web como base, que luego se puede rellenar con configuraciones, urls, modelos, vistas y plantillas específicas del sitio.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Uso de modelos</a></dt> + <dd>Este artículo muestra cómo definir modelos para el sitio web de la <em>Biblioteca Local</em> <span style='background-color: transparent; color: #333333; display: inline !important; float: none; font-family: "Open Sans",arial,x-locale-body,sans-serif; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal;'>— los modelos representan las estructuras en las que queremos almacenar los datos de nuestra app, y también permiten a Django almacenar datos en una base por nosotros (y modificarlos más tarde). Se explica qué es un modelo, cómo se declara y alguno de los principales tipos de campo. También se muestra brevemente unas pocas de las múltiples formas con las que puedes acceder al modelo de datos.</span></dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de Administración de Django</a></dt> + <dd>Ahora que hemos creado modelos para el sitio web de la <em>Biblioteca Local</em>, usaremos el sito de administración <span style='background-color: transparent; border-bottom-style: none; border-bottom-width: 0px; border-left-style: none; border-left-width: 0px; border-right-style: none; border-right-width: 0px; border-top-style: none; border-top-width: 0px; color: #333333; display: inline; float: none; font-family: "Open Sans",arial,x-locale-body,sans-serif; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 0px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal;'>de Django </span>para añadir algunos datos "reales" de libros. Primero te mostraremos cómo registrar los modelos con el sitio de administración, a continuación te mostraremos cómo iniciar sesión y crear algunos datos. Al final te mostramos algunas formas en las que puedes mejorar la presentación del sitio de administración.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creación de tu página de inicio</a></dt> + <dd>Ahora estamos listos para añadir el código para presentar nuestra primera página completa — una página de inicio para la <em>Biblioteca Local</em> que muestra cuántos registros tenemos de cada tipo de modelo y proporciona una barra lateral con enlaces de navegación a otras páginas. A medida que avanzamos ganaremos experiencia práctica en la escritura de mapas URL y vistas, obtención de registros de la base de datos y la utilización de plantillas.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></dt> + <dd>Este tutorial extiende el sitio web de nuestra <em>Biblioteca Local</em> añadiendo listas y páginas de detalle de libros y autores. Aquí aprenderemos sobre vistas genéricas basadas en clases y se mostrará cómo pueden reducir la cantidad de código que tienes que escribir para casos de uso común. También nos adentraremos en la gestión de URL en gran detalle, mostrando cómo realizar un emparejamiento básico de patrones.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></dt> + <dd>Este tutorial extiende nuestro sitio web de <em>Biblioteca Local</em> añadiendo a nuestra página de inicio un contador de visitas basado en sesión. Este es un ejemplo relativamente simple, pero muestra de verdad cómo puedes usar el framework de sesión para proporcionar un comportamiento presistente para usuarios anónimos en tus propios sitios.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación y permisos de Usuario</a></dt> + <dd>En este tutorial te mostraremos cómo permitir a los usuarios iniciar sesión en tu sitio con sus propias cuentas y cómo controlar lo que pueden hacer y ver, basado en si han iniciado sesión o no y en sus <em>permisos</em>. Como parte de esta demostración extenderemos el sitio web de la <em>Biblioteca Local</em>, añadiendo páginas de inicio y cierre de sesión, y páginas específicas de usuario - y de personal - para ver libros que han sido prestados.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajo con formularios</a></dt> + <dd>En este tutorial te mostraremos cómo trabajar con <a href="/en-US/docs/Web/Guide/HTML/Forms">Formularios HTML</a> en Django, y en particular la forma más fácil de escribir formularios para crear, actualizar y borrar instancias de modelos. Como parte de esta demostración extenderemos el sitio web de la <em>Biblioteca Local</em> de manera que los bibliotecarios puedan renovar libros, y crear, actualizar y borrar autores usando sus propios formularios (en vez de usar la aplicación de administración).</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web Django</a></dt> + <dd>A medida que crecen los sitios web se vuelven más difíciles de probar a mano — no sólo hay más para probar, sino que además, a medida que las interacciones entre los componentes se vuelven más complejas, un pequeño cambio en un área puede suponer muchas pruebas adicionales para verificar su impacto en otras áreas. Una forma de mitigar estos problemas es escribir tests automatizados, que pueden ser ejecutados de manera fácil y fiable cada vez que hagas un cambio. Este tutorial muestra cómo automatizar la <em>unidad de pruebas</em> de tu sitio web usando el framework de pruebas de Django.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Desplegando Django a producción</a></dt> + <dd>Ahora que has creado (y probado) un impresionante sitio web para la <em>Biblioteca Local</em>, vas a querer instalarlo en un servidor web público de manera que pueda ser accedido por el personal y los miembros de la biblioteca a través de Internet. Este artículo proporciona una visión general de cómo podrías ir buscando un host para desplegar tu sitio web y lo que necesitas hacer para conseguir que tu sitio esté listo en producción.</dd> + <dt><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad de las aplicaciones web Django</a></dt> + <dd>Proteger los datos de los usuarios es una parte esencial de cualquier diseño de un sitio web. Previamente ya explicamos algunas de las amenazas de seguridad más comunes en el artículo <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Seguridad Web</a> — este artículo proporciona una demostración práctica de cómo las protecciones integradas de Django gestionan estas amenazas.</dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<p>La siguiente evaluación comprobará tu comprensión de cómo crear un sitio web usando Django, como se describe en las guías listadas arriba.</p> + +<dl> + <dt><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">Mini Blog Django Hazlo tu mismo</a></dt> + <dd>En esta evaluación usarás algo del conocimiento que has aprendido en este módulo para crear tu propio blog.</dd> +</dl> diff --git a/files/es/learn/server-side/django/introducción/index.html b/files/es/learn/server-side/django/introducción/index.html new file mode 100644 index 0000000000..484b311a2c --- /dev/null +++ b/files/es/learn/server-side/django/introducción/index.html @@ -0,0 +1,282 @@ +--- +title: Introducción a Django +slug: Learn/Server-side/Django/Introducción +tags: + - Aprendizaje + - CodigoScript + - Principiante + - Programación lado servidor + - Python + - django + - introducción +translation_of: Learn/Server-side/Django/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}}</div> + +<p class="summary">En este primer artículo de Django responderemos la pregunta ¿Qué es Django? y daremos una visión general de lo que hace que este framework sea tan especial. Vamos a delinear las características principales, incluidas algunas de las funcionalidades avanzadas que no tendremos tiempo de cubrir con detalle en este módulo. Tambien mostraremos algunos de los componentes principales de una aplicación de Django. (aunque en este momento no cuentes con un entorno de desarrollo en el cual probarlo).</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre requisitos:</th> + <td>Conocimientos basicos en informatica. Una comprensión general de <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps">programación del lado del servidor</a>, y en particular de los mecanimos de <a href="/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">interacciones cliente-servidor en los sitios web</a>.</td> + </tr> + <tr> + <th scope="row">Objetivos:</th> + <td>Familiarizarse con lo que es Django, que funcionalidad proporciona y los componentes principales de una aplicación Django.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_Django">¿Qué es Django?</h2> + +<p>Django es un framework web de alto nivel que permite el desarrollo rápido de sitios web seguros y mantenibles. Desarrollado por programadores experimentados, Django se encarga de gran parte de las complicaciones del desarrollo web, por lo que puedes concentrarte en escribir tu aplicación sin necesidad de reinventar la rueda. Es gratuito y de código abierto, tiene una comunidad próspera y activa, una gran documentación y muchas opciones de soporte gratuito y de pago.</p> + +<p>Django te ayuda a escribir software que es:</p> + +<dl> + <dt>Completo</dt> + <dd>Django sigue la filosofía "Baterías incluidas" y provee casi todo lo que los desarrolladores quisieran que tenga "de fábrica". Porque todo lo que necesitas es parte de un único "producto", todo funciona a la perfección, sigue principios de diseño consistentes y tiene una amplia y<a href="https://docs.djangoproject.com/en/1.10/"> actualizada documentación</a>.</dd> + <dt>Versátil</dt> + <dd>Django puede ser (y ha sido) usado para construir casi cualquier tipo de sitio web — desde sistemas manejadores de contenidos y wikis, hasta redes sociales y sitios de noticias. Puede funcionar con cualquier framework en el lado del cliente, y puede devolver contenido en casi cualquier formato (incluyendo HTML, RSS feeds, JSON, XML, etc). ¡El sitio que estás leyendo actualmente está basado en Django!<br> + <br> + Internamente, mientras ofrece opciones para casi cualquier funcionalidad que desees (distintos motores de base de datos , motores de plantillas, etc.), también puede ser extendido para usar otros componentes si es necesario.</dd> + <dt>Seguro</dt> + <dd>Django ayuda a los desarrolladores evitar varios errores comunes de seguridad al proveer un framework que ha sido diseñado para "hacer lo correcto" para proteger el sitio web automáticamente. Por ejemplo, Django, proporciona una manera segura de administrar cuentas de usuario y contraseñas, evitando así errores comunes como colocar informaciones de sesión en cookies donde es vulnerable (en lugar de eso las cookies solo contienen una clave y los datos se almacenan en la base de datos) o se almacenan directamente las contraseñas en un hash de contraseñas.<br> + <br> + <em>Un hash de contraseña es un valor de longitud fija creado al enviar la contraseña a una <a href="https://en.wikipedia.org/wiki/Cryptographic_hash_function">cryptographic hash function</a>. Django puede validar si la contraseña ingresada es correcta enviándola a través de una función hash y comparando la salida con el valor hash almacenado. Sin embargo debido a la naturaleza "unidireccional" de la función, incluso si un valor hash almacenado se ve comprometido es difícil para un atacante resolver la contraseña original.</em><br> + <br> + Django permite protección contra algunas vulnerabilidades de forma predeterminada, incluida la inyección SQL, scripts entre sitios, falsificación de solicitudes entre sitios y clickjacking (consulte <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Website_security">Seguridad de sitios web</a> para obtener más detalles sobre dichos ataques).</dd> + <dt>Escalable</dt> + <dd>Django usa un componente basado en la arquitectura “<a href="https://en.wikipedia.org/wiki/Shared_nothing_architecture">shared-nothing</a>” (cada parte de la arquitectura es independiente de las otras, y por lo tanto puede ser reemplazado o cambiado si es necesario). Teniendo en cuenta una clara separación entre las diferentes partes significa que puede escalar para aumentar el tráfico al agregar hardware en cualquier nivel: servidores de cache, servidores de bases de datos o servidores de aplicación. Algunos de los sitios más concurridos han escalado a Django para satisfacer sus demandas (por ejemplo, Instagram y Disqus, por nombrar solo dos).</dd> + <dt>Mantenible</dt> + <dd>El código de Django está escrito usando principios y patrones de diseño para fomentar la creación de código mantenible y reutilizable. En particular, utiliza el principio No te repitas "Don't Repeat Yourself" (DRY) para que no exista una duplicación innecesaria, reduciendo la cantidad de código. Django también promueve la agrupación de la funcionalidad relacionada en "aplicaciones" reutilizables y en un nivel más bajo, agrupa código relacionado en módulos (siguiendo el patrón <a href="/en-US/Apps/Fundamentals/Modern_web_app_architecture/MVC_architecture">Model View Controller (MVC)</a>).</dd> + <dt>Portable</dt> + <dd>Django está escrito en Python, el cual se ejecuta en muchas plataformas. Lo que significa que no está sujeto a ninguna plataforma en particular, y puede ejecutar sus aplicaciones en muchas distribuciones de Linux, Windows y Mac OS X. Además, Django cuenta con el respaldo de muchos proveedores de alojamiento web, y que a menudo proporcionan una infraestructura específica y documentación para el alojamiento de sitios de Django.</dd> +</dl> + +<h2 id="¿De_dónde_vino">¿De dónde vino?</h2> + +<p>Django fue desarrollado inicialmente entre 2003 y 2005 por un equipo que era responsable de crear y mantener sitios web de periódicos. Después de crear varios sitios, el equipo empezó a tener en cuenta y reutilizar muchos códigos y patrones de diseño comunes. Este código común se convirtió en un framework web genérico, que fue de código abierto, conocido como proyecto "Django" en julio de 2005.</p> + +<p>Django ha continuado creciendo y mejorando desde su primer hito, el lanzamiento de la versión (1.0) en septiembre de 2008, hasta el reciente lanzamiento de la versión 1.11 (2017). Cada lanzamiento ha añadido nuevas funcionalidades y solucionado errores, que van desde soporte de nuevos tipos de bases de datos, motores de plantillas, caching, hasta la adición de funciones genéricas y clases de visualización (que reducen la cantidad de código que los desarrolladores tiene que escribir para numerosas tareas de programación).</p> + +<div class="note"> +<p><strong>Nota</strong>: Consulte las <span style="line-height: 1.5;"><a href="https://docs.djangoproject.com/en/1.10/releases/">notas de lanzamiento</a></span><span style="line-height: 1.5;"> en el sitio web de Django para ver qué ha cambiado en las versiones recientes y cúanto trabajo se lleva a cabo para mejorar Django.</span></p> +</div> + +<p>Django es ahora un próspero proyecto colaborativo de código abierto, con miles de usuarios y contribuidores. Mientras que todavía presenta algunas características que reflejan su origen, Django ha evolucionado en un framework versátil que es capaz de desarrollar cualquier tipo de sitio web.</p> + +<h2 id="¿Qué_tan_Popular_es_Django">¿Qué tan Popular es Django?</h2> + +<p>No hay una medida de popularidad definitiva y disponible de inmediato de "frameworks de lado servidor" (aunque sitios como <a href="http://hotframeworks.com/">Hot Frameworks</a> intentan evaluar la popularidad usando mecanismos como contar el número de proyectos en Github y preguntas en StackOverflow de cada plataforma). Una pregunta mejor es si Django es lo "suficientemente popular" para evitar los problemas de las plataformas menos populares. ¿Continúa evolucionando? ¿Puedes conseguir la ayuda que necesitas? ¿Hay alguna posibilidad de que consigas un trabajo pagado si aprendes Django?</p> + +<p>De acuerdo con el número de sitios que usan Django, el número de gente que contribuye al código base, y el número de gente que proporciona soporte tanto libre como pagado, podemos entonces decir que sí, !Django es un framework popular!</p> + +<p>Los sitios de alto nivel que usan Django incluyen: Disqus, Instagram, Knight Foundation, MacArthur Foundation, Mozilla, National Geographic, Open Knowledge Foundation, Pinterest y Open Stack (fuente: <a href="https://www.djangoproject.com/">Página de inicio de Django</a>).</p> + +<h2 id="¿Es_Django_dogmático">¿Es Django dogmático?</h2> + +<p>Los frameworks web frecuentemente se refieren a sí mismos como "dogmáticos" ("<em>opinionated</em>") o "no dogmáticos" ("<em>unopinionated</em>").</p> + +<p>Los frameworks dogmáticos son aquellos que opinan acerca de la "manera correcta" de gestionar cualquier tarea en particular. Ofrecen soporte para el desarrollo rápido en un <em>dominio en particular</em> (resolver problemas de un tipo en particular) porque la manera correcta de hacer cualquier cosa está generalmente bien comprendida y bien documentada.</p> + +<p>Sin embargo pueden ser menos flexibles para resolver problemas fuera de su dominio principal, y tienden a ofrecer menos opciones para elegir qué componentes y enfoques pueden usarse.</p> + +<p>Los framewoks no dogmáticos, por contra, tienen muchas menos restricciones sobre el modo mejor de unir componentes para alcanzar un objetivo, o incluso qué componentes deberían usarse. Hacen más fácil para los desarrolladores usar las herramientas más adecuadas para completar una tarea en particular, si bien al coste de que necesitas encontrar esos componentes por tí mismo.</p> + +<p>Django es "dogmático pero no del todo" y por tanto entrega "lo mejor de ambos mundos". Proporciona un conjunto de componentes para gestionar la mayoría de las tareas de desarrollo web y una (o dos) maneras preferidas de usarlos. Sin embargo, la arquitectura desacoplada de Django implica que puedes normalmente escoger y seleccionar de entre numerosas opciones diferentes o añadir soporte para otras completamente nuevas, si lo deseas.</p> + +<h2 id="¿Qué_pinta_tiene_el_código_de_Django">¿Qué pinta tiene el código de Django?</h2> + +<p>En un sitio web tradicional basado en datos, una aplicación web espera peticiones HTTP del explorador web (o de otro cliente). Cuando se recibe una petición la aplicación elabora lo que se necesita basándose en la URL y posiblemente en la información incluida en los datos <code>POST</code> o <code>GET</code>. Dependiendo de qué se necesita quizás pueda entonces leer o escribir información desde una base de datos o realizar otras tareas requeridas para satisfacer la petición. La aplicación devolverá a continuación una respuesta al explorador web, con frecuencia creando dinámicamente una página HTML para que el explorador la presente insertando los datos recuperados en marcadores de posición dentro de una plantilla HTML.</p> + +<p>Las aplicaciones web de Django normalmente agrupan el código que gestiona cada uno de estos pasos en ficheros separados:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/13931/basic-django.png" style="border-style: solid; border-width: 1px; display: block; margin: 0px auto;"></p> + +<ul> + <li><strong>URLs: </strong>Aunque es posible procesar peticiones de cada URL individual vía una función individual, es mucho más sostenible escribir una función de visualización separada para cada recurso. Se usa un mapeador URL para redirigir las peticiones HTTP a la vista apropiada basándose en la URL de la petición. El mapeador URL se usa para redirigir las peticiones HTTP a la vista apropiada basándose en la URL de la petición. El mapeador URL puede también emparejar patrones de cadenas o dígitos específicos que aparecen en una URL y los pasan a la función de visualización como datos.</li> + <li><strong>Vista (View):</strong> Una vista es una función de gestión de peticiones que recibe peticiones HTTP y devuelve respuestas HTTP. Las vistas acceden a los datos que necesitan para satisfacer las peticiones por medio de <em>modelos</em>, y delegan el formateo de la respuesta a las <em>plantillas</em> (<em>"templates"</em>).</li> + <li><strong>Modelos (Models):</strong> Los Modelos son objetos de Python que definen la estructura de los datos de una aplicación y proporcionan mecanismos para gestionar (añadir, modificar y borrar) y consultar registros en la base de datos.</li> + <li><strong>Plantillas (Templates):</strong> una plantilla (template) es un fichero de texto que define la estructura o diagrama de otro fichero (tal como una página HTML), con marcadores de posición que se utilizan para representar el contenido real. Una <em>vista</em> puede crear dinámicamente una página usando una plantilla, rellenandola con datos de un <em>modelo</em>. Una plantilla se puede usar para definir la estructura de cualquier tipo de fichero; ¡no tiene porqué ser HTML!</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: Django se refiere a este tipo de organización como arquitectura Modelo Vista Plantilla "Model View Template (MVT)". Tiene muchas similaridades con la arquitectura más familiar <a href="/en-US/docs/Web/Apps/Fundamentals/Modern_web_app_architecture/MVC_architecture">Model View Controller</a>. </p> +</div> + +<ul> +</ul> + +<p>Las secciones de más abajo te darán una idea de la pinta que tienen estas partes principales de una aplicación Django (entraremos en más detalles más adelante en el curso, una vez que hallamos configurado un entorno de desarrollo).</p> + +<h3 id="Enviar_la_petición_a_la_vista_correcta_urls.py">Enviar la petición a la vista correcta (urls.py)</h3> + +<p>Un mapeador URL está normalmente almacenado en un fichero llamado <strong>urls.py</strong>. En el ejemplo más abajo el mapeador (<code>urlpatterns</code>) define una lista de mapeos entre <em>patrones</em> URL específicos y sus correspondientes funciones de visualización. Si se recibe una Petición HTTP que tiene una URL que empareja un patrón específico (ej. <code>r'^$'</code>, más abajo) se realizará una llamada y se pasará la petición a la función de visualización asociada (ej. <code>views.index</code>).</p> + +<pre>urlpatterns = [ + <strong>url(r'^$', views.index),</strong> + url(r'^([0-9]+)/$', views.best), +] +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Un poco de Python:</p> + +<ul> + <li>El objeto <code>urlpatterns</code> es una lista de funciones <code>url()</code>. En Python, las listas se definen usando using corchetes. Los elementos se separan con comas y pueden tener una <a href="https://docs.python.org/2/faq/design.html#why-does-python-allow-commas-at-the-end-of-lists-and-tuples">coma colgante opcional</a>. Por ejemplo: <code>[item1, item2, item3,]</code>.</li> + <li>La extraña sintaxis de los patrones se conoce como <em>"expresión regular"</em>. ¡Hablaremos sobre ellas en un artículo posterior!.</li> + <li>El segundo argumento de <code>url()</code> es otra función a la que se llamará cuando se encuentre un patrón que coincida. La notación <code>views.index</code> indica que la función se llama <code>index()</code> y se puede encontrar en un módulo llamado <code>views</code> (es decir, dentro del fichero llamado <code>views.py</code>).</li> +</ul> +</div> + +<h3 id="Manejar_la_petición_views.py">Manejar la petición (views.py)</h3> + +<p>Las vistas son el corazón de la aplicación web, recibiendo peticiones HTTP de los clientes web y devolviendo respuestas HTTP. Entre éstas, organizan los otros recursos del framework para acceder a las bases de datos, consolidar plantillas, etc.</p> + +<p>El ejemplo más abajo muestra una mínima función de visualización <code>index()</code>, que podría ser llamada por nuestro mapeador de URL de la sección anterior. Al igual que todas las funciones de visualización, recibe un objeto <code>HttpRequest</code> como parámetro (<code>request</code>) y devuelve un objeto <code>HttpResponse</code>. En este caso no hacemos nada con la petición y nuestra respuesta simplemente devuelve una cadena insertada de forma fija en el código. Te mostraremos una petición que hace algo más interesante en la siguiente sección.</p> + +<pre class="brush: python">## fichero: views.py (funciones de visualizacion de Django) +from django.http import HttpResponse + +def index(request): + # Obtener un HttpRequest - el parametro peticion + # Realizar operaciones usando la infomracion de la peticion. + # Devolver una HttpResponse + return HttpResponse('!Hola desde Django!') +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Un poco de Python:</p> + +<ul> + <li><a href="https://docs.python.org/3/tutorial/modules.html">Módulos Python</a> son "bibliotecas" de funciones, almacenadas en ficheros separados, que podríamos querer usar en nuestro código. Aquí importamos sólo el objeto <code>HttpResponse</code> desde el módulo <code>django.http</code> de manera que podamos usarlo en nuestra vista: <code>from django.http import HttpResponse</code>. Hay también otras formas de importar algunos o todos los objetos de un módulo.</li> + <li>Las funciones se declaran usando la plabra clave <code>def</code> tal como se muestra arriba, con parámetros con nombre listados entre paréntesis después del nombre de la función; la línea entera termina con dos puntos. Fíjate como las líneas siguientes están todas ellas <strong>indentadas</strong>. La indentación es importante, ya que especifica que las líneas de código están dentro de ese bloque en particular (la indentación obligatoria es una característica clave de Python, y es una razón por la que el código de Python es tan fácil de leer.</li> +</ul> +</div> + +<ul> +</ul> + +<p>Las vistas se almacenan normalmente en un fichero llamado <strong>views.py</strong>.</p> + +<h3 id="Definir_modelos_de_datos_models.py">Definir modelos de datos (models.py)</h3> + +<p>Las aplicaciones web Django manejan y consultan datos a través de objetos Python referidos como modelos. Los modelos definen la estructura de los datos almacenados, incluyendo los <em>tipos</em> de campos y posiblemente también su tamaño máximo, los valores por defecto, la lista de selección de opciones, texto de ayuda para documentación, etiquetas de texto para formularios, etc. La definición del modelo es independiente de la base de datos subyacente — puedes elegir una entre varias como parte de la configuración de tu proyecto. Una vez que has seleccionado qué base de datos quieres usar, no necesitas en absoluto comunicarte con ella directamente — sólo hay que escribir la estructura de la base y otro código y Django se encarga por tí de todo el trabajo sucio de comunicarse con la base de datos.</p> + +<p>El fragmento de código de más abajo muestra un modelo de Django muy simple para un objeto <code>Team</code>. La clase <code>Team</code> deriva de la clase de django <code>models.Model</code>. Define el nombre de un equipo y su nivel como campos de tipo carácter y especifica un número máximo de caracteres que pueden ser almacenados en cada registro. El <code>team_level</code> puede ser un valor de entre varios, de manera que lo definimos como un campo de opciones y proporcionamos un mapeo entre opciones para mostrar y datos para almacenar, junto con un valor por defecto.</p> + +<pre class="brush: python"># filename: models.py + +from django.db import models + +class Team(models.Model): + team_name = models.CharField(max_length=40) + + TEAM_LEVELS = ( + ('U09', 'Under 09s'), + ('U10', 'Under 10s'), + ('U11', 'Under 11s'), + ... #list other team levels + ) + team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11') +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Un poco de Python:</p> + +<ul> + <li>Python soporta "programación orientada a objetos", un estilo de programación donde organizamos nuestro código en objetos, que incluyen datos relacionados y funciones para operar con los datos. Los objetos también pueden heredarse/extenderse/derivarse de otros objetos, permitiendo que se comparta un comportamiento común entre objetos relacionados. En Python usamos la palabra clave <code>class</code> para definir el "prototipo" de un objeto. Podemos crear múltiples <em>instancias</em> específicas de ese tipo de objeto basado en el modelo especificado en la clase.<br> + Así por ejemplo, aquí tenemos una clase <code>Team</code>, que deriva de la clase <code>Model</code>. Esto significa que es un modelo y que contendrá los métodos de un modelo, pero también podemos darle características especializadas propias. En nuestro modelo definimos los campos de nuestra base que necesitaremos para almacenar nuestros datos, dándoles nombres específicos. Django usa estas definiciones, incluídos los nombres de los campos para crear la base subyacente.</li> +</ul> +</div> + +<h3 id="Consultar_datos_views.py">Consultar datos (views.py)</h3> + +<p>El modelo de Django proporciona una API de consulta simple para buscar en la base de datos. Esta puede buscar concidencias contra varios campos al mismo tiempo usando diferentes criterios (ej. exacto, insensible a las mayúsculas, mayor que, etc.), y puede soportar sentencias complejas (por ejemplo, puedes especificar que se busque equipos U11 que tengan un nombre de equipo que empiece por "Fr" o termine con "al").</p> + +<p>El fragmento de código de más abajo muestra una función de visualización (manejador de recursos) para presentar en pantalla todos nuestros equipos U09. La línea en negrilla muestra como podemos usar la API de consulta del modelo para filtrar todos los registros donde el campo <code>team_level</code> tenga exactamente el texto 'U09' (fíjate como este criterio se pasa como argumento a la función<code> filter()</code> con el nombre del campo y tipo de coincidencia separados por un doble guion bajo: <strong>team_level__exact</strong>).</p> + +<pre class="brush: python">## filename: views.py + +from django.shortcuts import render +from .models import Team + +def index(request): + <strong>list_teams = Team.objects.filter(team_level__exact="U09")</strong> + context = {'youngest_teams': list_teams} + return render(request, '/best/index.html', context) +</pre> + +<dl> +</dl> + +<p>Esta función utiliza la función <code>render()</code> para crear la <code>HttpResponse</code> que se envía de vuelta al explorador. Esta función es un <em>atajo</em>; crea un fichero HTML mediante la combinación de una plantilla HTML específica y algunos datos para insertar en ella (proporcionados en la variable "<code>context</code>"). En la siguiente sección mostramos como la plantilla tiene los datos insertados en ella para crear el HTML.</p> + +<h3 id="Renderización_de_los_datos_plantillas_HTML">Renderización de los datos (plantillas HTML)</h3> + +<p>Los sistemas de plantillas permiten especificar la estructura de un documento de salida usando marcadores de posición para los datos que serán rellenados cuando se genere la página. Las plantillas se usan con frecuencia para crear HTML, también pueden crear otros tipos de documentos. Django soporta de fábrica tanto su sistema de plantillas nativo como otra biblioteca Python popular llamada <strong>Jinja2</strong> (y se puede hacer que soporte otros sistemas si hace falta).</p> + +<p>El fragmento de código de más abajo muestra el aspecto que podría tener la plantilla HTML llamada por la función <code>render()</code> de la sección anterior. Esta plantilla ha sido escrita bajo la suposición de que cuando sea renderizada tendrá acceso a una variable tipo lista llamada <code>youngest_teams</code> (contenida en la variable <code>context</code> dentro de la función <code>render()</code> de más arriba). Dentro del esqueleto HTML tenemos una expresión que primero comprueba que existe la variable <code>youngest_teams</code>, y luego itera sobre ella en un bucle <code>for</code>. En cada iteración la plantilla presenta cada valor del campo <code>team_name</code> del equipo en un elemento {{htmlelement("li")}}.</p> + +<pre class="brush: python">## filename: best/templates/best/index.html + +<!DOCTYPE html> +<html lang="en"> +<body> + + {% if youngest_teams %} + <ul> + {% for team in youngest_teams %} + <li>\{\{ team.team_name \}\}</li> + {% endfor %} + </ul> +{% else %} + <p>No teams are available.</p> +{% endif %} + +</body> +</html></pre> + +<h2 id="¿Qué_más_puedes_hacer">¿Qué más puedes hacer?</h2> + +<p>Las secciones prededentes muestran las principales características que usarás en casi todas las aplicaciones web: mapeo de URLs, vistas, modelos y plantillas. Sólo unas pocas de las otras cosas que Django proporciona y que incluyen:</p> + +<ul> + <li><strong>Formularios</strong>: Los formularios HTML se usan para recolectar datos de los usuarios para su procesamiento en el servidor. Django simplifica la creación, validación y procesamiento de los formularios.</li> + <li><strong>Autenticación y permisos de los usuarios</strong>: Django incluye un sistema robusto de autenticación y permisos que ha sido construido con la seguridad en mente.</li> + <li><strong>Cacheo</strong>: La creación dinámica de contenido es mucho más intensiva computacionalmente (y lenta) que un servico de contenido estático. Django proporciona un cacheo flexible de forma que puedes almacenar todo o parte de una página renderizada para que no sea re-renderizada nada más que cuando sea necesario.</li> + <li><strong>Sitio de Administracion</strong>: el sitio de administración de Django está incluido por defecto cuando creas una app usando el esqueleto básico. Esto hace que sea trivialmente fácil proporcionar una página de adminsitración para que los administradores puedan crear, editar y visualizar cualquiera de los modelos de datos de su sitio.</li> + <li><strong>Serialización de datos</strong>: Django hace fácil el serializar y servir tus datos como XML o JSON. Esto puede ser útil cuando se está creando un servicio web (un sitio web que sólo sirve datos para ser consumidos por otras aplicaciones o sitios, y que no presenta en pantalla nada por sí mismo), o cuando se crea un sitio web en el que el código del lado cliente maneja toda la renderización de los datos.</li> +</ul> + +<h2 id="Sumario">Sumario</h2> + +<p>¡Felicidades, has completado el primer paso en tu viaje por Django! Deberías ahora ser consciente de los principales beneficios de Django, algo de su historia y a groso modo la pinta que tienen cada una de las partes principales de una de sus apps. Deberías también haber aprendido unas pocas cosas acerca del lenguaje de programación Python, incluyendo la sintaxis para las listas, funciones y clases.</p> + +<p>Has visto ya algo de código real de Django más arriba, pero a diferencia del código de lado cliente, necesitas configurar un entorno de desarrollo para hacerlo funcionar. Ese será nuestro siguiente paso.</p> + +<div>{{NextMenu("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django")}} +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Introducci%C3%B3n">Introducción a Django</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/development_environment">Puesta en marcha de un entorno de desarrollo de Django</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: Sitio web "Biblioteca Local"</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creación del esqueleto de un sitio web</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Uso de modelos</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de Administración de Django</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creación de tu página de inicio</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación y permisos de Usuario</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajo con formularios</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web Django</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Desplegando Django a producción</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/web_application_security">Seguridad de las aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> +</div> diff --git a/files/es/learn/server-side/django/models/index.html b/files/es/learn/server-side/django/models/index.html new file mode 100644 index 0000000000..95b6c670ea --- /dev/null +++ b/files/es/learn/server-side/django/models/index.html @@ -0,0 +1,490 @@ +--- +title: 'Tutorial Django Parte 3: Uso de modelos' +slug: Learn/Server-side/Django/Models +tags: + - Aprender + - Artículo + - Datos + - Modelo + - Principiante + - Tutorial + - django + - lado-servidor +translation_of: Learn/Server-side/Django/Models +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}</div> + +<p class="summary">Este artículo muestra cómo definir modelos para el sitio web de la <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">BibliotecaLocal</a>. En él se explica lo que es un modelo, cómo se declara, y cuáles son algunos de los principales tipos de campos de un modelo. También veremos, brevemente, cuáles son algunas de las maneras en que puede accederse a los datos del modelo.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial Django Parte 2: Creación del esqueleto del sitio web</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Ser capaz de diseñar y crear tus propios modelos, eligiendo de forma apropiada los campos.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Visión_general">Visión general</h2> + +<p>Las aplicaciones web de Django acceden y administran los datos a través de objetos de Python a los que se hace referencia como modelos. Los modelos definen la<em> estructura</em> de los datos almacenados, incluidos los <em>tipos</em> de campo y los atributos de cada campo, como su tamaño máximo, valores predeterminados, lista de selección de opciones, texto de ayuda para la documentación, texto de etiqueta para formularios, etc. La definición del modelo es independiente de la base de datos subyacente. puede elegir una de entre varias como parte de la configuración de su proyecto. Una vez que haya elegido la base de datos que desea usar, no necesita hablar directamente con ella. Simplemente escriba la estructura de su modelo y algo de código, y Django se encargará de todo el trabajo sucio, al comunicarse con la base de datos por usted.</p> + +<p>Este tutorial muestra cómo definir y acceder a los modelos para el ejemplo del <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">sitio web LocalLibrary</a>.</p> + +<h2 id="Diseñando_los_modelos_de_LocalLibrary">Diseñando los modelos de LocalLibrary</h2> + +<p>Antes de dar el salto y comenzar a codificar los modelos, vale la pena tomarse unos minutos para pensar qué datos necesitamos almacenar y cuáles serán las relaciones entre los diferentes objetos.</p> + +<p>Sabemos que tenemos que almacenar información sobre libros (título, resumen, autor, idioma escrito, categoría, ISBN) y que podríamos tener varias copias disponibles (con id único global, estado de disponibilidad, etc.). Es posible que necesitemos almacenar más información sobre el autor que solo su nombre, y puede haber varios autores con el mismo nombre o nombres similares. Queremos poder ordenar la información según el título del libro, el autor, el idioma escrito y la categoría.</p> + +<p>Al diseñar sus modelos, tiene sentido tener modelos separados para cada "objeto" (grupo de información relacionada). En este caso, los objetos obvios son libros, instancias de libros y autores.</p> + +<p>También es posible que desee utilizar modelos para representar las opciones de la lista de selección (por ejemplo, como una lista desplegable de opciones), en lugar de codificar las opciones en el sitio web en sí; esto se recomienda cuando no se conocen de antemano todas las opciones posibles o éstas están sujetas a cambios. Los candidatos obvios para las modelos, en este caso, incluyen el género del libro (por ejemplo, ciencia ficción, poesía francesa, etc.) y el idioma (inglés, francés, japonés).</p> + +<p>Una vez que hayamos decidido cuáles serán nuestros modelos y sus campos, debemos pensar en la relación que existe entre ellos. Django le permite definir relaciones de uno a uno (<span style='font-family: "Courier New";'>OneToOneField</span>), de uno a muchos (<span style='font-family: "Courier New";'>ForeignKey</span>) y de muchos a muchos (<span style='font-family: "Courier New";'>ManyToManyField</span>).</p> + +<p>Con esto en mente, el diagrama de asociación UML a continuación muestra los modelos que definiremos en este caso (como recuadros). Como se mencionó anteriormente, hemos creado modelos para el libro (los detalles genéricos del libro), instancia del libro (estado de copias físicas específicas del libro disponible en el sistema) y autor. También hemos decidido tener un modelo para el género, para que los valores se puedan crear/seleccionar a través de la interfaz admin. Hemos decidido no tener un modelo para el <span style='font-family: "Courier New";'>BookInstance:status</span>, en su lugar, hemos especificado directamente, en el código, los valores (<span style='font-family: "Courier New";'>LOAN_STATUS</span>) porque no esperamos que cambien. Dentro de cada uno de los cuadros, puede ver el nombre del modelo, los nombres y tipos de campo, y también los métodos y sus tipos de devolución.</p> + +<p>El diagrama también muestra las relaciones entre los modelos, incluida su <em>cardinalidad</em>. La cardinalidad expresa la cantidad de instancias (máximo y mínimo) de cada modelo que pueden estar presentes en la relación. Por ejemplo, la línea de conexión entre los cuadros muestra que <em>Book</em> y <em>Genre</em> están relacionados. Los números cercanos al modelo <em>Book</em> muestran que un libro debe tener uno o más <em>Genres</em> (tantos como desee), mientras que los números al otro lado de la línea al lado de <em>Genre</em> muestran que puede tener cero o más libros asociados.</p> + +<p><img alt="LocalLibrary Model UML" src="https://mdn.mozillademos.org/files/15646/local_library_model_uml.png" style="height: 660px; width: 977px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: La siguiente sección proporciona un manual básico que explica cómo se definen y utilizan los modelos. Mientras lo lees, considera cómo construiremos cada uno de los modelos en el diagrama de arriba.</p> +</div> + +<h2 id="Cartilla_del_Modelo">Cartilla del Modelo</h2> + +<p>Esta sección provee una vista resumida de cómo se define un modelo y algunos de los campos más importantes y argumentos de campo. </p> + +<h3 id="Definición_de_modelo">Definición de modelo</h3> + +<p>Los modelos están definidos, normalmente, en el archivo <strong>models.py</strong> de la aplicación. Son implementados como subclases de <code>django.db.models.Model</code>, y pueden incluir campos, métodos y metadata. El fragmento de código más abajo muestra un modelo "típico", llamado <code>MyModelName</code>:</p> + +<pre class="notranslate">from django.db import models + +class MyModelName(models.Model): + """ + Una clase típica definiendo un modelo, derivado desde la clase Model. + """ + + # Campos + my_field_name = models.CharField(max_length=20, help_text="Enter field documentation") + ... + + # Metadata + class Meta: + ordering = ["-my_field_name"] + + # Métodos + def get_absolute_url(self): + """ + Devuelve la url para acceder a una instancia particular de MyModelName. + """ + return reverse('model-detail-view', args=[str(self.id)]) + + def __str__(self): + """ + Cadena para representar el objeto MyModelName (en el sitio de Admin, etc.) + """ + return self.field_name</pre> + +<p>En las secciones de abajo exploraremos cada una de las características interiores de un modelo en detalle:</p> + +<h4 id="Campos">Campos</h4> + +<p>Un modelo puede tener un número arbitrario de campos, de cualquier tipo. Cada uno representa una columna de datos que queremos guardar en nuestras tablas de la base de datos. Cada registro de la base de datos (fila) consistirá en uno de cada posible valor del campo. Echemos un vistazo al ejemplo visto arriba:</p> + +<pre class="brush: js notranslate">my_field_name = models.CharField(max_length=20, help_text="Enter field documentation")</pre> + +<p>Nuestro ejemplo de arriba tiene un único campo llamado <code>my_field_name</code>, de tipo <code>models.CharField</code> — lo que significa que este campo contendrá una cadena de caracteres alfanuméricos. Los tipos de campo son asignados usando clases específicas, que determinan el tipo de registro que se usa para guardar el dato en la base, junto con un criterio de evaluación que se usará cuando se reciban los valores de un formulario HTML (es decir, qué constituye un valor válido). Los tipos de campo pueden también tomar argumentos que especifican además cómo se guarda o cómo se puede usar. En este caso le damos a nuestro campo dos argumentos:</p> + +<ul> + <li><code>max_length=20</code> — Establece que la longitud máxima del valor de este campo es 20 caracteres.</li> + <li><code>help_text="Enter field documentation"</code> — proporciona una etiqueta de texto para mostrar que ayuda a los usuarios a saber qué valor proporcionar cuando un usuario ha de introducirlo via un formulario HTML.</li> +</ul> + +<p>El nombre del campo se usa para referirnos a él en consultas (<em>queries</em>) y plantillas (<em>templates</em>). Los campos también tienen una etiqueta, que puede ser especificada como argumento (<code>verbose_name</code>) o inferida automáticamente, a partir del nombre de variable que identifica al campo, capitalizando la primera letra y reemplazando los guiones bajos por espacios (por ejemplo <code>my_field_name</code> tendría la etiqueta por defecto de <em>My field name</em>). El orden en que los campos son declarados afectará su orden por defecto si un modelo es renderizado en un formulario (ej. en el sitio de Administración), aunque este comportamiento se puede anular.</p> + +<h5 id="Argumentos_comunes_de_los_campos">Argumentos comunes de los campos</h5> + +<p>Los siguientes argumentos son comunes a la mayoría de los tipos de campo y pueden usarse al declararlos:</p> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#help-text">help_text</a>: Proporciona una etiqueta de texto para formularios HTML (ej. en el sitio de Administración), tal como se describe arriba.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#verbose-name">verbose_name</a>: Nombre de fácil lectura que se usa en etiquetas para el campo. Si no se especifica, Django inferirá el valor por defecto del verbose name a partir del nombre del campo.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#default">default</a>: Valor por defecto para el campo. Puede ser un valor o un <em>callable object</em> (objeto que puede ser llamado como una función), en cuyo caso el objeto será llamado cada vez que se cree un nuevo registro.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#null">null</a>: Si es <code>True</code>, Django guardará valores en blanco o vacíos como <code>NULL</code> en la base de datos para campos donde sea apropiado (un <code>CharField</code> guardará una cadena vacía en su lugar). Por defecto es <code>False</code>.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#blank">blank</a>: Si es <code>True</code>, se permite que el campo quede en blanco en tus formularios. El valor por defecto es <code>False</code>, lo que significa que la validación de formularios de Django te forzará a introducir un valor. Con frecuencia se usa con <code>null=True</code>, porque si vas a permitir valores en blanco, también querrás que la base de datos sea capaz de representarlos de forma apropiada.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#choices">choices</a>: Un grupo de valores de selección para este campo. Si se proporciona, el widget correspondiente por defecto del formulario será una caja de selección con estos valores de selección en vez del campo de texto estándar.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#primary-key">primary_key</a>: Si es <code>True</code>, establece el campo actual como clave primaria para el modelo (Una clave primaria es una columna especial de la base de datos, diseñada para identificar de forma única todos los diferentes registros de una tabla). Si no se especifica ningún campo como clave primaria, Django añadirá automáticamente un campo para este propósito.</li> +</ul> + +<p>Hay muchas otras opciones — puedes ver la <a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#field-options">lista completa de opciones aquí</a>.</p> + +<h5 id="Tipos_comunes_de_campos">Tipos comunes de campos</h5> + +<p>La lista siguiente describe algunos de los tipos de campo más comunmente usados. </p> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.CharField">CharField</a> se usa para definir cadenas de longitud corta a media. Debes especificar la <code>max_length</code> (longitud máxima) de los datos que se guardarán.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.TextField">TextField</a> se usa para cadenas de longitud grande o arbitraria. Puedes especificar una <code>max_length</code> para el campo, pero sólo se usa cuando el campo se muestra en formularios (no se fuerza al nivel de la base de datos).</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#django.db.models.IntegerField" title="django.db.models.IntegerField">IntegerField</a> es un campo para almacenar valores de números enteros y para validar los valores introducidos como enteros en los formularios.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#datefield">DateField</a> y <a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#datetimefield">DateTimeField</a> se usan para guardar/representar fechas e información fecha/hora (como en los objetos Python <code>datetime.date</code> y <code>datetime.datetime</code>, respectivamente). Estos campos pueden adicionalmente declarar los parámetros (mutuamente excluyentes) <code>auto_now=True</code> (para establecer el campo a la fecha actual cada vez que se guarda el modelo), <code>auto_now_add</code> (para establecer sólo la fecha cuando se crea el modelo por primera vez), y <code>default</code> (para establecer una fecha por defecto que puede ser sobreescrita por el usuario).</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#emailfield">EmailField</a> se usa para validar direcciones de correo electrónico.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#filefield">FileField</a> e <a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#imagefield">ImageField</a> se usan para subir ficheros e imágenes respectivamente (el <code>ImageField</code> añade simplemente una validación adicional de que el fichero subido es una imagen). Éstos tienen parámetros para definir cómo y donde se guardan los ficheros subidos.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#autofield">AutoField</a> es un tipo especial de <code>IntegerField</code> que se incrementa automáticamente. Cuando no especificas una clave primaria para tu modelo, se añade -automáticamente- una de éste tipo.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#foreignkey">ForeignKey</a> se usa para especificar una relación uno a muchos con otro modelo de la base de datos (ej. un coche tiene un fabricante, pero un fabricante puede hacer muchos coches). El lado "uno" de la relación es el modelo que contiene la clave.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#manytomanyfield">ManyToManyField</a> se usa para especificar una relación muchos a muchos (ej. un libro puede tener varios géneros, y cada género puede contener varios libros). En nuestra aplicación de la biblioteca usaremos ésta de forma muy similar a <code>ForeignKeys</code>, pero pueden usarse de formas más complicadas para describir las relaciones entre grupos. Éstas tienen el parámetro <code>on_delete</code> para definir que ocurre cuando un registro asociado se borra (ej. un valor de <code>models.SET_NULL</code> establecería simplemente el valor a <code>NULL</code>).</li> +</ul> + +<p>Hay muchos otros tipos de campos, incluyendo campos para diferentes tipos de números (enteros grandes, enteros pequeños, en coma flotante), boleanos, URLs, slugs, identificadores únicos, y otra información relacionada con el tiempo (duración, hora, etc..). Puedes ver la <a href="https://docs.djangoproject.com/en/1.10/ref/models/fields/#field-types">lista completa aquí</a>.</p> + +<h4 id="Metadatos">Metadatos</h4> + +<p>Puedes declarar metadatos a nivel de modelo para tu Modelo declarando <code>class Meta</code>, tal como se muestra.</p> + +<pre class="brush: python notranslate">class Meta: + ordering = ["-my_field_name"] + ...</pre> + +<p>Una de las características más útiles de estos metadatos es controlar el <em>orden por defecto</em> de los registros que se devuelven cuando se consulta el tipo de modelo. Se hace especificando el orden de comprobación en una lista de nombres de campo en el atributo <code>ordering</code>, como se muestra arriba. La ordenación dependerá del tipo de campo (los campos de caracteres de ordenan alfabéticamente, mientras que los campos de fechas están clasificados por orden cronológico). Como se muestra arriba, se puede invertir el orden de clasificación añadiendo el símbolo (-) como prefijo del nombre del campo.</p> + +<p>Así como ejemplo, si elegimos clasificar los libros de esta forma por defecto:</p> + +<pre class="brush: python notranslate">ordering = ["title", "-pubdate"]</pre> + +<p>los libros serán clasificados alfabéticamente por título, de la A al a Z, y luego por fecha de publicación dentro de cada título, desde el más reciente al más antiguo.</p> + +<p>Otro atributo común es <code>verbose_name</code>, un nombre descriptivo para la clase en forma singular y plural:</p> + +<pre class="brush: python notranslate">verbose_name = "BetterName"</pre> + +<p>Otros atributos útiles te permiten crear y aplicar nuevos "permisos de acceso" para el modelo (los permisos por defecto se aplican automáticamente), te permiten la ordenación basado en otro campo, o declarar que la clase es "abstracta" (una clase base para la que no vas a crear registros, y que en cambio se derivará para crear otros modelos).</p> + +<p>Muchas de las otras opciones de metadatos controlan qué base datos debe usarse para el modelo y cómo se guardan los datos (éstas son realmente útiles si necesitas mapear un modelo a una base datos existente).</p> + +<p>La lista completa de opciones de metadatos está disponible aquí: <a href="https://docs.djangoproject.com/es/2.0/ref/models/options/">Opciones de metadatos de Modelos</a> (Django docs).</p> + +<h4 id="Metodos">Metodos</h4> + +<p>Un modelo puede tener también métodos</p> + +<p>Minimamente, en cada modelo deberías definir el método estándar de las clases de Python <code>__str__()</code> para devolver una cadena de texto legible por humanos para cada objeto. Esta cadena se usa para representar registros individuales en el sitio de administración (y en cualquier otro lugar donde necesites referirte a una instancia del modelo). Con frecuencia éste devolverá un título o nombre de campo del modelo.</p> + +<pre class="brush: python notranslate">def __str__(self): + return self.field_name</pre> + +<p>Otro método común a incluir en los modelos de Django es <code>get_absolute_url()</code>, que devuelve un URL para presentar registros individuales del modelo en el sitio web (si defines este método, Django añadirá automáticamente un botón "Ver en el sitio" en la ventana de edición del registro del modelo en el sitio de Administración). Un patrón típico para <code>get_absolute_url()</code> se muestra abajo.</p> + +<pre class="brush: python notranslate">def get_absolute_url(self): + """ + Devuelve la url para acceder a una instancia particular del modelo. + """ + return reverse('model-detail-view', args=[str(self.id)]) +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Asumiendo que usarás URLs tipo <code>/myapplication/mymodelname/2</code> para presentar registros individuales para tu modelo (donde "2" es el <code>id</code> de un registro en particular), necesitarás crear un mapeador URL para pasar la respuesta e id a la "vista detallada del modelo (model detail view)" (que hará el trabajo requerido para presentar el registro). La función <code>reverse()</code> de arriba es capaz de "invertir" tu mapeador url (llamado <em>'model-detail-view' </em>en el caso de arriba) para crear una URL del formato correcto.</p> + +<p>Por supuesto para hacer este trabajo ¡tienes aún que escribir el mapeo URL, la vista y la plantilla!</p> +</div> + +<p>Puedes también definir todos los métodos que te apetezca y llamarlos desde tu código o plantillas (siempre y cuando no reciban ningún parámetro).</p> + +<h3 id="Gestión_de_Modelos">Gestión de Modelos</h3> + +<p>Una vez que has definido tus clases de modelos puedes usarlas para crear, actualizar o borrar registros, y ejecutar consultas para obtener todos los registros o subconjuntos particulares de registros. Te mostraremos cómo hacer eso en el tutorial cuando definamos nuestras vistas, pero aquí va un breve resumen.</p> + +<h4 id="Creación_y_modificación_de_registros">Creación y modificación de registros</h4> + +<p>Para crear un registro puedes definir una instancia del modelo y llamar a <code>save()</code>.</p> + +<pre class="brush: python notranslate"># Creación de un nuevo registro usando el constructor del modelo. +a_record = MyModelName(my_field_name="Instancia #1") + +# Guardar el objeto en la base de datos. +a_record.save() +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Si no has declarado ningún campo como <code>primary_key</code>, al nuevo registro se le proporcionará una automáticamente, con el nombre de campo <code>id</code>. Puedes consultar este campo después de guardar el registro anterior y debería tener un valor de 1.</p> +</div> + +<p>Puedes acceder a los campos de este nuevo registro usando la sintaxis de puntos y cambiar los valores. Tienes que llamar a <code>save()</code> para almacenar los valores modificados en la base de datos.</p> + +<pre class="brush: python notranslate"># Accesso a los valores de los campos del modelo usando atributos Python. +print(a_record.id) # Debería devolver 1 para el primer registro. +print(a_record.my_field_name) # Debería imprimir 'Instancia #1' + +# Cambio de un registro modificando los campos llamando a save() a continuación. +a_record.my_field_name="Nuevo Nombre de Instancia" +a_record.save()</pre> + +<h4 id="Búsqueda_de_registros">Búsqueda de registros</h4> + +<p>Puedes buscar registros que coincidan con un cierto criterio usando el atributo <code>objects</code> del modelo (proporcionado por la clase base).</p> + +<div class="note"> +<p><strong>Nota</strong>: Explicar cómo buscar registros usando un modelo y nombres de campo "abstractos" puede resultar un poco confuso. En la exposición de abajo nos referiremos a un modelo <code>Book</code> con campos <code>title</code> y <code>genre</code>, donde genre (género) es también un modelo con un solo campo <code>name</code>.</p> +</div> + +<p>Podemos obtener todos los registros de un modelo como <code>QuerySet</code>, usando <code>objects.all()</code>. El <code>QuerySet</code> es un objeto iterable, significando que contiene un número de objetos por los que podemos iterar/hacer bucle.</p> + +<pre class="brush: python notranslate">all_books = Book.objects.all() +</pre> + +<p>El método de Django <code>filter()</code> nos permite filtrar el <code>QuerySet</code> devuelto para que coincida un campo de <strong>texto</strong> o <strong>numérico</strong> con un criterio particular. Por ejemplo, para filtrar libros que contengan la palabra "wild" en el título y luego contarlos, podemos hacer lo siguiente:</p> + +<pre class="brush: python notranslate">wild_books = Book.objects.filter(title__contains='wild') +number_wild_books = Book.objects.filter(title__contains='wild').count() +</pre> + +<p>Los campos a buscar y el tipo de coincidencia son definidos en el nombre del parámetro de filtro, usando el formato: <code>field_name__match_type</code> (ten en cuenta el <em>doble guión bajo</em> entre <code>title</code> y <code>contains</code> anterior). En el ejemplo anterior estamos filtrando <code>title</code> por un valor sensible a mayúsculas y minúsculas. Puedes hacer otros muchos tipos de coincidencias: <code>icontains</code> (no sensible a mayúsculas ni minúsculas), <code>iexact</code> (coincidencia exacta no sensible a mayúsculas ni minúsculas), <code>exact</code> (coincidencia exacta sensible a mayúsculas y minúsculas) e <code>in</code>, <code>gt</code> (mayor que), <code>startswith</code>, etc. Puede ver la <a href="https://docs.djangoproject.com/en/1.10/ref/models/querysets/#field-lookups">lista completa aquí</a>.</p> + +<p>En algunos casos, necesitarás filtrar por un campo que define una relación uno-a-muchos con otro modelo (por ejemplo, una <code>ForeignKey</code>). En estos casos puedes "referenciar" a campos dentro del modelo relacionado con un doble guión bajo adicional. Así, por ejemplo, para filtrar los libros de un género específico tienes que referenciar el <code>name</code> a través del campo <code>genre</code> como se muestra más abajo:</p> + +<pre class="brush: python notranslate">books_containing_genre = Book.objects.filter(genre<strong>__</strong>name<strong>__</strong>icontains='fiction') # Will match on: Fiction, Science fiction, non-fiction etc. +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Puedes usar guiones bajos (__) para navegar por tantos niveles de relaciones (<code>ForeignKey</code>/<code>ManyToManyField</code>) como quieras. Por ejemplo, un Book que tuviera diferentes "types", definidos usando una relación adicional "cover", podría tener un nombre de parámetro: <code>type__cover__name__exact='hard'.</code></p> +</div> + +<p>Puedes hacer muchas más cosas con las consultas, incluyendo búsquedas hacia atrás de modelos relacionados, filtros encadenados, devolver un conjunto de valores más pequeño, etc. Para más información, puedes consultar <a href="https://docs.djangoproject.com/en/1.10/topics/db/queries/">Elaborar consultas</a> (Django Docs).</p> + +<h2 id="Definiendo_los_Modelos_de_LocalLybrary">Definiendo los Modelos de LocalLybrary</h2> + +<p>En esta sección comenzaremos a definir los modelos para nuestra biblioteca. Abre <em>models.py (en /locallibrary/catalog/)</em>. El código de más arriba importa el módulo <code>models</code> que contiene la clase <code>models.Model</code>, que servirá de base para nuestros modelos:</p> + +<pre class="brush: python notranslate">from django.db import models + +# Create your models here.</pre> + +<h3 id="Modelo_Genre">Modelo 'Genre'</h3> + +<p>Copia el código del modelo <code>Genre</code> que se muestra abajo y pégalo al final de tu archivo <code>models.py</code>. Este modelo nos servirá para almacenar información relativa a la categoría del libro (por ejemplo, si es ficción o no, si es un romancero o es un libro de historia, etc.) Como se dijo más arriba, preferimos modelar el género (Genre) como una entidad, en vez de utilizar un campo de texto o una lista de opciones, porque de esta manera es posible manejar los valores a través de nuestra base de datos, en vez de fijarlo en el código (<em>hard-coding</em>)</p> + +<pre class="brush: python notranslate">class Genre(models.Model): + """ + Modelo que representa un género literario (p. ej. ciencia ficción, poesía, etc.). + """ + name = models.CharField(max_length=200, help_text="Ingrese el nombre del género (p. ej. Ciencia Ficción, Poesía Francesa etc.)") + + def __str__(self): + """ + Cadena que representa a la instancia particular del modelo (p. ej. en el sitio de Administración) + """ + return self.name</pre> + +<p>El modelo tiene un único campo (<code>name</code>), de tipo <code>CharField</code>, que usaremos para describir el género literario. Este campo tiene un tamaño máximo (<code>max_length</code>) de 200 caracteres y, además, posee un <code>help_text</code>. Al final de la clase, hemos declarado el método <code>__str__()</code>, que simplemente devuelve el nombre de un género definido por un registro en particular. Como no hemos definido un nombre explicativo (<code>verbose_name</code>) para nuestro campo, éste se establecerá en <code>Name</code> y se mostrará de esa manera en los formularios.</p> + +<h3 id="Modelo_Book">Modelo 'Book'</h3> + +<p>Copia el código del modelo <code>Book</code> que aparece más abajo y pégalo al final de tu archivo. El modelo Libro representa la información que se tiene sobre un libro, en sentido general, pero no sobre un libro particular que se encuentre disponible en la biblioteca. Este modelo utiliza campos de tipo <code>CharField</code> para representar el título (<code>title)</code> y el <code>isbn</code> del libro (nota que el campo <code>isbn</code> especifica su etiqueta como "ISBN" utilizando el primer parámetro posicional, ya que la etiqueta por defecto hubiera sido "Isbn"). Además tenemos un campo para la sinopsis (<code>summary</code>), de tipo <code>TextField</code>, ya que este texto podría ser bastante largo.</p> + +<pre class="brush: python notranslate">from django.urls import reverse #Used to generate URLs by reversing the URL patterns + +class Book(models.Model): + """ + Modelo que representa un libro (pero no un Ejemplar específico). + """ + + title = models.CharField(max_length=200) + + author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True) + # ForeignKey, ya que un libro tiene un solo autor, pero el mismo autor puede haber escrito muchos libros. + # 'Author' es un string, en vez de un objeto, porque la clase Author aún no ha sido declarada. + + summary = models.TextField(max_length=1000, help_text="Ingrese una breve descripción del libro") + + isbn = models.CharField('ISBN',max_length=13, help_text='13 Caracteres <a href="https://www.isbn-international.org/content/what-isbn">ISBN number</a>') + + genre = models.ManyToManyField(Genre, help_text="Seleccione un genero para este libro") + # ManyToManyField, porque un género puede contener muchos libros y un libro puede cubrir varios géneros. + # La clase Genre ya ha sido definida, entonces podemos especificar el objeto arriba. + + def __str__(self): + """ + String que representa al objeto Book + """ + return self.title + + + def get_absolute_url(self): + """ + Devuelve el URL a una instancia particular de Book + """ + return reverse('book-detail', args=[str(self.id)]) +</pre> + +<p>El género es un campo de tipo <code>ManyToManyField</code>, de manera tal que un mismo libro podrá abarcar varios géneros y un mismo género podrá abarcar muchos libros. El autor es declarado como <code>ForeignKey</code>, de modo que cada libro podrá tener un sólo autor, pero un autor podrá tener muchos libros (en la vida real, un mismo libro puede tener varios autores, pero en nuestra implementación no).</p> + +<p>En la declaración de ambos campos, el modelo relacionado se ingresa como primer parámetro posicional, usando el nombre la clase que lo implementa o, bien, el nombre del modelo como string, si éste no ha sido implementado en el archivo, antes de la declaración del campo. Otros parámetros interesantes que podemos observar, en el campo <code>author</code>, son <code>null=True</code>, que permite a la base de datos almacenar <code>null</code> si el autor no ha sido seleccionado, y <code>on_delete=models.SET_NULL</code>, que pondrá en <code>null</code> el campo si el registro del autor relacionado es eliminado de la base de datos.</p> + +<p>El modelo también define <code>__str__()</code>, usando el campo <code>title</code> para representar un registro de la clase <code>Book</code>. El último método, <code>get_absoulte_url()</code> devuelve un URL que puede ser usado para acceder al detalle de un registro particular (para que esto funcione, debemos definir un mapeo de URL que tenga el nombre <code>book-detail</code> y una vista y una plantilla asociadas a él)</p> + +<h3 id="Modelo_BookInstance">Modelo 'BookInstance'</h3> + +<p>A continuación, copie el model <code>BookInstance</code> (mostrado a continuación) debajo de los otros modelos. <code>BookInstance</code> representa una copia específica de un libro que alguien pueda pedir prestado, en incluye información sobre si la copia esta disponible o sobre cual es la fecha que se espera sea devuelto, "imprenta" o detalles de versión, y un id único para el libro en la biblioteca.</p> + +<p>Algunos de los campos y métodos ahora serán familiares. El modelo usa</p> + +<ul> + <li><code>ForeignKey</code> para identificar el Libro asociado (cada libro puede tener muchas copias, pero una copia solo puede tener un <code>Book</code>).</li> + <li><code>CharField</code> para representar la imprenta (publicación específica) del libro.</li> +</ul> + +<pre class="brush: python notranslate">import uuid # Requerida para las instancias de libros únicos + +class BookInstance(models.Model): + """ + Modelo que representa una copia específica de un libro (i.e. que puede ser prestado por la biblioteca). + """ + id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text="ID único para este libro particular en toda la biblioteca") + book = models.ForeignKey('Book', on_delete=models.SET_NULL, null=True) + imprint = models.CharField(max_length=200) + due_back = models.DateField(null=True, blank=True) + + LOAN_STATUS = ( + ('m', 'Maintenance'), + ('o', 'On loan'), + ('a', 'Available'), + ('r', 'Reserved'), + ) + + status = models.CharField(max_length=1, choices=LOAN_STATUS, blank=True, default='m', help_text='Disponibilidad del libro') + + class Meta: + ordering = ["due_back"] + + + def __str__(self): + """ + String para representar el Objeto del Modelo + """ + return '%s (%s)' % (self.id,self.book.title)</pre> + +<p>Adicionalmente hemos declarado algunos tipos nuevos de campos:</p> + +<ul> + <li><code>UUIDField</code> es usado para establecer el campo <code>id</code> como una <code>primary_key</code> para este modelo. Este tipo de campo asigna un único valor global para cada instancia ( uno para cada libro que puedes encontrar en la biblioteca).</li> + <li><code>DateField</code> es usado para la fecha <code>due_back</code> (en la que se espera que el libro este diponible despues de ser prestado o estar en mantenimiento). Este valor puede ser <code>blank</code> o <code>null</code> (necesario cuando el libro esta disponible). El patrón metadata (<code>Class Meta</code>) usa este campo para ordenar registros cuando se retornan en una consulta.</li> + <li><code>status</code> es un <code>CharField</code> que define una lista de elección/selección. Como puedes ver, hemos definido una tupla que contiene tuplas de pares clave-valor y los pasamos a los argumentos de choice. El valor en un par clave/valor es un valor desplegable que el usuario puede seleccionar, mientras las claves son valores que en realidad son guardados en la opción seleccionada. Tambien establecemos un valor por defecto de 'm' (maintenance) ya que los libros inicialmente se crearán como no disponibles antes de que esten almacenados en los estantes.</li> +</ul> + +<p>El patrón <code>__str__()</code> representa el objeto <code>BookInstance</code> usando una combinación de su id único y el título del <code>Book</code> asociado.</p> + +<div class="note"> +<p><strong>Note</strong>: Un poco de Python:</p> + +<ul> + <li>El valor retornado por <code>__str__()</code> es una <em>cadena formateada</em>. Dentro de la cadena usamos <code>%s</code> para declarar "marcadores de posición". Después de la cadena ponemos <code>%</code> y después una tupla que contiene los valores que serán puestos en los marcadores de posición. Si solo tienes un marcador de posición entonces puedes omitir la tupla — e.j. <code>'Mi valor: %s' % variable.</code><br> + <br> + Note que aunque este enfoque es perfectamente válido, sea conciente que ya no es preferido. Desde Python 3 debes usar en su lugar el método <strong>format</strong>, ej. <code>'{0} ({1})'.format(self.id,self.book.title)</code>. Puedes leer más sobre esto <a href="https://www.python.org/dev/peps/pep-3101/">aquí</a>. A partir de Python 3.6 también puedes usar la sintaxis de interpolación de cadena, e.j. <code>f'{self.id} ({self.book.title})'</code>.</li> +</ul> +</div> + +<h3 id="Modelo_Author">Modelo 'Author'</h3> + +<p>Copia el modelo <code>Author</code> (mostrado abajo) bajo el código existente en <strong>models.py</strong>.</p> + +<p>Todos los campos/métodos ahora deben ser familiares. El modelo define a un autor que tiene un primer nombre, apellido, fecha de nacimiento, y (opcional) fecha de fallecimiento. Especifica que de forma predeterminada el <code>__str__()</code> retorna el nombre en el <em>orden apellido</em>, <em>primer nombre</em>. El método <code>get_absolute_url()</code> invierte el mapeo URL <code>author-detail</code> para obtener el URL para mostrar un autor individual.</p> + +<pre class="brush: python notranslate">class Author(models.Model): + """ + Modelo que representa un autor + """ + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + date_of_birth = models.DateField(null=True, blank=True) + date_of_death = models.DateField('Died', null=True, blank=True) + + def get_absolute_url(self): + """ + Retorna la url para acceder a una instancia particular de un autor. + """ + return reverse('author-detail', args=[str(self.id)]) + + + def __str__(self): + """ + String para representar el Objeto Modelo + """ + return '%s, %s' % (self.last_name, self.first_name) +</pre> + +<h2 id="Reiniciar_las_migraciones_a_la_base_de_datos">Reiniciar las migraciones a la base de datos</h2> + +<p>Todos tus modelos han sido creados. Para añadirlos a tu base de datos, vuelve a ejecutar las migraciones de tu base de datos.</p> + +<pre class="notranslate"><code>python3 manage.py makemigrations +python3 manage.py migrate</code></pre> + +<h2 id="Modelo_Language_-_desafío">Modelo 'Language' - desafío</h2> + +<p>Imagina que un benefactor local dona un número de libros nuevos escritos en otro lenguaje (digamos, Farsi). El desafío es averiguar como estos pueden ser bien representados en tu sitio Web, y luego agregarlos a los modelos.</p> + +<p>Algunas cosas a considerar:</p> + +<ul> + <li>¿Debe asociarse un "lenguaje" a un <code>Book</code>, <code>BookInstance</code>, o algún otro objeto?</li> + <li>¿Deberian representarse los diferentes idiomas usando un modelo, un campo de texto libre o una lista de seleccion codificada?</li> +</ul> + +<p>Después que hayas decidido, agrega el campo. Puedes ver que decidimos nostros en Github <a href="https://github.com/mdn/django-locallibrary-tutorial/blob/master/catalog/models.py">aquí</a>.</p> + +<p>No olvides que después de un cambio en tu modelo, debes volver a hacer las migraciones para que se apliquen los cambios en tu base de datos.</p> + +<pre class="brush: bash notranslate"><code>python3 manage.py makemigrations</code><code> +python3 manage.py migrate</code></pre> + +<ul> +</ul> + +<ul> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p>En este artículo hemos aprendido como son definidos los modelos, y luego usar esta información para diseñar e implementar modelos apropiados para el sitio Web <em>LocalLibrary</em>.</p> + +<p>En este punto nos desviaremos brevemente de la creación del sitio, y miraremos el <em>sitio de Administración de </em><em>Django</em>. Este sitio nos permitirá añadir algunos datos a la biblioteca, los cuales podemos mostrar usando nuestras (aún por crear) vistas y plantillas.</p> + +<h2 id="Vea_también">Vea también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/intro/tutorial02/">Escribiendo tu primera aplicación Django, parte 2</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/db/queries/">Realizando consultas</a> (Django Docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/models/querysets/">Referencia del API QuerySet</a> (Django Docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django/Admin_site", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/sessions/index.html b/files/es/learn/server-side/django/sessions/index.html new file mode 100644 index 0000000000..f5b751c115 --- /dev/null +++ b/files/es/learn/server-side/django/sessions/index.html @@ -0,0 +1,200 @@ +--- +title: 'Tutorial de Django Parte 7: Framework de sesiones' +slug: Learn/Server-side/Django/Sessions +tags: + - Artículo + - Principiante + - Python + - Servidor + - Sesion + - Sesiones + - Tutorial + - aprende + - django + - lado-servidor +translation_of: Learn/Server-side/Django/Sessions +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/authentication", "Learn/Server-side/Django")}}</div> + +<p class="summary">Este tutorial extiende nuestro sitio web de la <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">BibliotecaLocal</a>, añadiendo un contador de visitas a tu página de inicio basado en sesiones. Es un ejemplo relativamente simple, pero muestra cómo puedes usar el framework de sesión para proporcionar persistencia a usuarios anónimos en tus propios sitios.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Completar todos los tópicos anteriores del tutorial, incluyendo <a href="/en-US/docs/Learn/Server-side/Django/Generic_views">Django Tutorial Part 6: Generic list and detail views</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender como emplear las sesiones.</td> + </tr> + </tbody> +</table> + +<h2 id="Resumen">Resumen</h2> + +<p>El sitio web de la <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">BibliotecaLocal</a> que creamos en los tutoriales previos permite a los usuarios explorar los libros y autores en el catálogo. Mientras que el contenido se genera dinámicamente desde la base de datos, todos los usuarios básicamente tendrán acceso a las mismas páginas y tipos de información cuando usan el sitio.</p> + +<p>En una biblioteca "real" podrías querer dar a cada usuario individual una experiencia personalizada, basada en su uso previo del sitio, preferencias, etc. Por ejemplo, podrías ocultar los mensajes de advertencia que el usuario ya ha aceptado previamente la próxima vez que visite el sitio, o guardar y respetar sus preferencias (ej. el número de resultados de búsqueda que quiere desplegar en cada página).</p> + +<p>El framework de sesiones te permite implementar este tipo de comportamiento, pudiendo guardar y recuperar información arbitraria en base a cada visitante particular del sitio.</p> + +<h2 id="¿Qué_son_las_sesiones">¿Qué son las sesiones?</h2> + +<p>Toda comunicación entre los navegadores web y los servidores se da a través del protocolo HTTP, que es <em>sin estado</em>. El hecho de que el protocolo sea sin estado significa que los mensajes entre el cliente y el servidor son completamente independientes entre sí -- no existe una noción de "secuencia" o comportamiento basado en mensajes previos. Como resultado, si quieres tener un sitio que guarde registro de la relación que tiene lugar con un cliente, necesitas implementarlo tú mismo.</p> + +<p>Las sesiones son el mecanismo que usa Django (y la mayor parte de Internet) para guardar registro del "estado" entre el sitio y un navegador en particular. Las sesiones te permiten almacenar información arbitraria por navegador, y tener esta información disponible para el sitio cuando el navegador se conecta. Cada pieza individual de información asociada con una sesión se conoce como "clave", que se usa tanto para guardar como para recuperar la información.</p> + +<p>Django usa una cookie que contiene un <em>id de sesión</em> específica para identificar cada navegador y su sesión asociada con el sitio. La información real de la sesión se guarda por defecto en la base de datos del sitio (esto es más seguro que guardar la información en una cookie, donde es más vulnerable para los usuarios maliciosos). Puedes configurar Django para guardar la información de sesión en otros lugares (caché, archivos, cookies "seguras"), pero la opción por defecto es una buena opción y relativamente segura.</p> + +<h2 id="Habilitando_las_sesiones">Habilitando las sesiones</h2> + +<p>Las sesiones fueron automáticamente habilitadas cuando <a href="/es/docs/Learn/Server-side/Django/skeleton_website">creamos el sitio web esqueleto</a> (en el tutorial 2).</p> + +<p>La configuración está establecida en las secciones <code>INSTALLED_APPS</code> y <code>MIDDLEWARE</code> del archivo del proyecto (<strong>locallibrary/locallibrary/settings.py</strong>), como se muestra abajo:</p> + +<pre class="brush: python notranslate">INSTALLED_APPS = [ + ... +<strong> 'django.contrib.sessions',</strong> + .... + +MIDDLEWARE = [ + ... +<strong> 'django.contrib.sessions.middleware.SessionMiddleware',</strong> + ....</pre> + +<h2 id="Usando_las_sesiones">Usando las sesiones</h2> + +<p>Puedes usar el atributo <code>session</code> en la vista desde el parámetro <code>request</code> (una <code>HttpRequest</code> que se envía como el primer argumento a la vista). Este atributo de sesión representa la conección específica con el usuario actual (o para ser más preciso, la conección con el <em>navegador</em> actual, como se identifica mediante la id de sesión en la cookie del navegador para este sitio).</p> + +<p>El atributo <code>session</code> es un objeto tipo diccionario que puedes leer y escribir tantas veces como quieras en tu vista, modificándolo como desees. Puedes realizar todas las operaciones normales de diccionario, incluyendo eliminar toda la información, probar si una clave está presente, iterar a través de la información, etc. Sin embargo, la mayor parte del tiempo solo usarás la API estándar de "diccionario" para recuperar y establecer valores.</p> + +<p>Los fragmentos de código de abajo te muestran cómo puedes recuperar, establecer o eliminar información con la clave "<code>my_car</code>", asociada con la sesión actual (del navegador).</p> + +<div class="note"> +<p><strong>Nota</strong>: Una de las cosas grandiosas de Django es que no necesitas pensar sobre los mecanismos que relacionan la sesión con tu solicitud actual en tu vista. Si fuéramos a usar los fragmentos de abajo en nuestra vista, sabríamos que la información sobre <code>my_car</code> está asociada solo con el navegador que envió la solicitud.</p> +</div> + +<pre class="brush: python notranslate"># Obtener un dato de la sesión por su clave (ej. 'my_car'), generando un KeyError si la clave no existe +my_car = request.session['my_car'] + +# Obtener un dato de la sesión, estableciendo un valor por defecto ('mini') si el dato requerido no existe +my_car = request.session.get('my_car', 'mini') + +# Asignar un dato a la sesión +request.session['my_car'] = 'mini' + +# Eliminar un dato de la sesión +del request.session['my_car'] +</pre> + +<p>La API ofrece también una cantidad de métodos adicionales que se usan mayoritariamente para administrar la cookie de sesión asociada. Por ejemplo, hay métodos para probar si el navegador cliente soporta cookies, establecer y revisar las fechas de expiración de las cookies, y para eliminar sesiones expiradas del almacén de datos. Puedes encontrar información sobre la API completa en <a href="https://docs.djangoproject.com/en/1.10/topics/http/sessions/">Cómo usar sesiones</a> (Django docs).</p> + +<h2 id="Guardando_la_información_de_la_sesión">Guardando la información de la sesión</h2> + +<p>Por defecto, Django solo guarda información en la base de datos de sesión y envía la cookie de sesión al cliente cuando la sesión ha sido <em>modificada</em> (asignada) o <em>eliminada</em>. Si estás actualizando algún dato usando su clave de sesión como se mostró en la sección previa, ¡no necesitas preocuparte por esto! Por ejemplo:</p> + +<pre class="brush: python notranslate"># Esto es detectado como un cambio en la sesión, así que la información de la sesión es guardada. +request.session['my_car'] = 'mini'</pre> + +<p>Si estás actualizando algún dato <em>dentro</em> de la información de sesión, Django no reconocerá que has hecho un cambio en la sesión y guardado la información (por ejemplo, si fueras a cambiar el dato "<code>wheels</code>" dentro de tu dato "<code>my_car</code>", como se muestra abajo). En este caso, necesitarás marcar explícitamente la sesión como que ha sido modificada.</p> + +<pre class="brush: python notranslate"># Objeto de sesión no directamente modificada, solo información dentro de la sesión. +# ¡Cambios no guardados! +request.session['my_car']['wheels'] = 'alloy' + +# Establecer la sesión como modificada para forzar a que se guarden los cambios. +<code>request.session.modified = True</code> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Puedes cambiar el comportamiento para que el sitio actualice la base de datos y envíe la cookie en cada solicitud añádiendo <code>SESSION_SAVE_EVERY_REQUEST = True</code> a la configuración de tu proyecto (<strong>locallibrary/locallibrary/settings.py</strong>).</p> +</div> + +<h2 id="Ejemplo_simple_--_obteniendo_conteos_de_visitas">Ejemplo simple -- obteniendo conteos de visitas</h2> + +<p>Como un ejemplo simple del mundo real, actualizaremos nuestra biblioteca para decirle al usuario actual cuántas veces ha visitado la página principal de <em>BibliotecaLocal</em>.</p> + +<p>Abre <strong>/locallibrary/catalog/views.py</strong>, y aplica los cambios que se muestran con negrita abajo.</p> + +<pre class="brush: python notranslate">def index(request): + ... + + num_authors=Author.objects.count() # El 'all()' se obvia en este caso. + +<strong> # Numero de visitas a esta view, como está contado en la variable de sesión. + num_visits = request.session.get('num_visits', 0) + request.session['num_visits'] = num_visits + 1</strong> + + <strong>context = { + 'num_books':num_books, + 'num_instances':num_instances, + 'num_instances_available':num_instances_available, + 'num_authors':num_authors, + 'num_visits':num_visits, + } </strong> + + # Carga la plantilla index.html con la información adicional en la variable context. + return render(request, 'index.html', context=context)</pre> + +<p>Aquí primero obtenemos el valor de la clave de sesión <code>'num_visits'</code>, estableciendo el valor a 0 si no había sido establecido previamente. Cada vez que se recibe la solicitud, incrementamos el valor y lo guardamos de vuelta en la sesión (para la siguiente vez que el usuario visita la página). La variable <code>num_visits</code> se envía entonces a la plantilla en nuestra variable de contexto.</p> + +<div class="note"> +<p><strong>Nota</strong>: Aquí podríamos incluso revisar si el navegador soporta cookies (mira <a href="/es/docs/https://docs.djangoproject.com/en/1.10/topics/http/sessions/">Cómo usar sesiones</a> para ejemplos) o diseñar nuestra UI de modo que no importe si el navegador soporta cookies o no.</p> +</div> + +<p>Añade la línea que se ve al final del siguiente bloque a tu plantilla HTML principal (<strong>/locallibrary/catalog/templates/index.html</strong>) al final de la sección "Dynamic content" para desplegar la variable de contexto:</p> + +<pre class="brush: html notranslate"><h2>Dynamic content</h2> + +<p>The library has the following record counts:</p> +<ul> + <li><strong>Books:</strong> \{{ num_books }}</li> + <li><strong>Copies:</strong> \{{ num_instances }}</li> + <li><strong>Copies available:</strong> \{{ num_instances_available }}</li> + <li><strong>Authors:</strong> \{{ num_authors }}</li> +</ul> + +<strong><p>You have visited this page \{{ num_visits }}{% if num_visits == 1 %} time{% else %} times{% endif %}.</p></strong> +</pre> + +<p>Guarda tus cambios y reinicia el servidor de pruebas. Cada vez que refresques la página, el número se debería actualizar.</p> + +<ul> +</ul> + +<h2 id="Resumen_2">Resumen</h2> + +<p>Ahora sabes lo fácil que es usar sesiones para mejorar tu interacción con usuarios <em>anónimos</em>.</p> + +<p>En nuestros siguientes artículos explicaremos el framework de autenticación y autorización (permisos), y te mostraremos cómo soportar cuentas de usuario.</p> + +<h2 id="Mira_también">Mira también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/http/sessions/">Cómo usar sesiones</a> (Django docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Generic_views", "Learn/Server-side/Django/Authentication", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/skeleton_website/index.html b/files/es/learn/server-side/django/skeleton_website/index.html new file mode 100644 index 0000000000..96c8b0d3b0 --- /dev/null +++ b/files/es/learn/server-side/django/skeleton_website/index.html @@ -0,0 +1,397 @@ +--- +title: 'Tutorial Django Parte 2: Creación del esqueleto del sitio web' +slug: Learn/Server-side/Django/skeleton_website +tags: + - Aprendizaje + - Artículo + - Codificación de scripts + - Guía + - Principiante + - Tutorial + - django + - introducción + - lado servidor +translation_of: Learn/Server-side/Django/skeleton_website +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}</div> + +<p class="summary">Este segundo artículo de nuestro <a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a> muestra cómo puedes crear un proyecto de "esqueleto" de sitio web como base, que puedes continuar luego llenado de configuraciones específicas del sitio, urls, modelos, vistas y plantillas.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/development_environment">Poner en marcha un entorno de desarrollo Django</a>. Repasar el <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial Django</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Ser capaz de usar las herramientas de Django para empezar tus propios proyectos de sitios web nuevos.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Visión_general">Visión general</h2> + +<p>Este artículo muestra como puedes crear un sitio web "esqueleto", que puedes luego llenar con configuraciones específicas del sitio, urls, modelos, vistas y plantillas (trataremos ésto en artículos posteriores).</p> + +<p>El proceso es sencillo:</p> + +<ol> + <li><span style="line-height: 1.5;">Usar la herramienta </span><code style="font-style: normal; font-weight: normal; line-height: 1.5;">django-admin</code><span style="line-height: 1.5;"> para crear la carpeta del proyecto, los ficheros de plantillas básicos y el script de gestión del proyecto </span><span style="line-height: 1.5;"> (</span><strong style="line-height: 1.5;">manage.py</strong><span style="line-height: 1.5;">).</span></li> + <li><span style="line-height: 1.5;">Usar </span><strong style="line-height: 1.5;">manage.py</strong><span style="line-height: 1.5;"> para crear una o más <em>aplicaciones</em></span><span style="line-height: 1.5;">.</span> + <div class="note"> + <p><strong>Nota</strong>: Un sitio web puede consistir de una o más secciones, ej. sitio principal, blog, wiki, area de descargas, etc. Django te recomienda encarecidamente que desarrolles estos componentes como <em>aplicaciones</em> separadas que podrían ser reutilizadas, si se desea, en otros proyectos. </p> + </div> + </li> + <li><span style="line-height: 1.5;">Registrar las nuevas aplicaciones para incluirlas en el proyecto. </span></li> + <li><span style="line-height: 1.5;">Conectar el mapeador url de cada aplicación</span><span style="line-height: 1.5;">.</span></li> +</ol> + +<p>Para el <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">sitio web de la BibliotecaLocal</a> la carpeta del sitio y la carpeta de su proyecto se llamarán <em>locallibrary</em>, y tendremos sólo una aplicación llamada <em>catalog</em>. El nivel más alto de la estructura de carpetas quedará por tanto como sigue:</p> + +<pre class="brush: bash"><em>locallibrary/ # Carpeta del sitio web</em> + <strong>manage.py </strong># Script para ejecutar las herramientas de Django para este proyecto (creadas usando django-admin) + <em>locallibrary/ # Carpeta del Sitio web/Proyecto </em>(creada usando django-admin) + <em>catalog/ # Carpeta de la Aplicación </em>(creada usando manage.py) +</pre> + +<p><span style="line-height: 1.5;">Las siguientes secciones abordan los pasos del proceso en detalle, y muestran cómo puedes comprobar los cambios. Al final de cada artículo trataremos alguna de los otros ajustes aplicables al sitio entero que deberías también efectuar en esta etapa</span><span style="line-height: 1.5;">.</span></p> + +<h2 id="Creación_del_proyecto">Creación del proyecto</h2> + +<p>En primer lugar abre una ventana de comandos/terminal, navega hasta donde quieres almacenar tus apps Django (hazlo en algún lugar que sea fácil de encontrar, como dentro de la carpeta de tus <span style="line-height: 1.5;"><em>documentos</em>), y crea una carpeta para tu nuevo sitio web (en este caso </span><span style="line-height: 1.5;">: </span><em>locallibrary</em>). Entra en el directorio a continuación usando el comando cd:</p> + +<pre class="brush: bash">mkdir locallibrary +cd locallibrary</pre> + +<p>Crear el nuevo proyecto usando el comando <code>django-admin startproject</code> como se muestra, y navega luego dentro de la carpeta.</p> + +<pre class="brush: bash">django-admin startproject locallibrary . +cd locallibrary</pre> + +<p>La herramienta <code>django-admin</code> crea una estructura de carpetas/ficheros como se muestra abajo:</p> + +<pre class="brush: bash"><em>locallibrary/</em> + <strong>manage.py</strong> + <em>locallibrary/</em> + settings.py + urls.py + wsgi.py</pre> + +<p>La subcarpeta del proyecto <em>locallibrary</em> es el punto de entrada al sitio web: </p> + +<ul> + <li><strong>settings.py</strong> contiene todos los ajustes del sitio. Es donde registramos todas las aplicaciones que creamos, la localización de nuestros ficheros estáticos, los detalles de configuración de la base de datos, etc.</li> + <li><strong>urls.py</strong> define los mapeos url-vistas. A pesar de que éste podría contener <span style="line-height: 1.5;"><em>todo</em> el código del mapeo url, es más común delegar algo del mapeo a las propias aplicaciones, como verás más tarde</span><span style="line-height: 1.5;">. </span></li> + <li><strong style="line-height: 1.5;">wsgi.py</strong><span style="line-height: 1.5;"> se usa para ayudar a la aplicación Django a comunicarse con el servidor web. Puedes tratarlo como código base que puedes utilizar de plantilla</span><span style="line-height: 1.5;">.</span></li> +</ul> + +<p>El script <strong>manage.py</strong> se usa para crear aplicaciones, trabajar con bases de datos y empezar el desarrollo del servidor web.</p> + +<h2 id="Creación_de_la_aplicación_catalog">Creación de la aplicación catalog</h2> + +<p>A continuación, ejecuta el siguiente comando para crear la aplicación <em>catalog</em> que vivirá dentro de nuestro proyecto locallibrary (éste debe ejecutarse en la misma carpeta que el <strong>manage.py</strong> de tu proyecto):</p> + +<pre class="brush: bash">python3 manage.py startapp catalog</pre> + +<div class="note"> +<p><strong>Nota</strong>: el comando de arriba es para Linux/Mac OS X. En Windows el comando debería ser: <code>py -3 manage.py startapp catalog</code></p> + +<p>Si estás trabajando en Windows, reemplaza <code>python3</code> por <code>py -3</code> a lo largo de este módulo o simplemente python: <code>python manage.py startapp catalog</code>.</p> +</div> + +<p>La herramienta crea una nueva carpeta y la rellena con ficheros para las diferentes partes de la aplicación (mostradas en negrilla abajo). La mayoría de los ficheros se nombran de acuerdo a su propósito, para que sea má útil (ej. las vistas se deberán guardar en <strong>views.py</strong>, los Modelos en <strong>models.py</strong>, las pruebas en <strong>tests.py</strong>, la configuración del sitio de administración en <strong>admin.py</strong>, el registro de aplicaciones en <strong>apps.py</strong>) y contienen algo de código base mínimo para trabajar con los objetos asociados.</p> + +<p>El directorio actualizado del proyecto debería tener ahora el aspecto siguiente:</p> + +<pre class="brush: bash"><em>locallibrary/</em> + manage.py + <em>locallibrary/ +</em><strong> <em>catalog/</em> + admin.py + apps.py + models.py + tests.py + views.py + __init__.py + <em>migrations/</em></strong> +</pre> + +<p>Además ahora tenemos:</p> + +<ul> + <li>Una carpeta <em>migrations</em> que se utiliza para guardar las "migraciones"— ficheros que te permiten actualizar tus bases de datos a medida que modificas tus modelos. </li> + <li><strong>__init__.py</strong> — Un fichero vacío creado aquí para que Django/Python reconozca la carpeta como un <a href="https://docs.python.org/3/tutorial/modules.html#packages">Paquete Python</a> y te permita usar sus objetos dentro de otras partes del proyecto.</li> +</ul> + +<div class="note"> +<p><strong>Nota</strong>: ¿Te has dado cuenta qué es lo que falta en la lista de ficheros de arriba? Si bien hay un lugar para que coloques tus vistas y modelos, no hay nada para que pongas los mapeos url, las plantillas y los ficheros estáticos. Te mostraremos cómo crearlos más adelante (éstos no se necesitan en todos los sitios web pero se necesitan en este ejemplo).</p> +</div> + +<h2 id="Registro_de_la_aplicación_catalog">Registro de la aplicación catalog</h2> + +<p>Ahora que se ha creado la aplicación tenemos que registrarla en el proyecto de manera que sea incluida cuando cualquiera de las herramientas se ejecute (por ejemplo, para añadir modelos a la base de datos). Las aplicaciones se registran añadiéndolas a la lista de <code>INSTALLED_APPS</code> en los ajustes del proyecto.</p> + +<p>Abre el fichero de ajustes del proyecto <strong>locallibrary/locallibrary/settings.py</strong> y encuentra la definición de la lista <code>INSTALLED_APPS</code>. Añade a continuación una nueva linea al final de la lista, como se muestra en negrilla abajo.</p> + +<pre class="brush: bash">INSTALLED_APPS = [ + 'django.contrib.admin', + 'django.contrib.auth', + 'django.contrib.contenttypes', + 'django.contrib.sessions', + 'django.contrib.messages', + 'django.contrib.staticfiles', +<strong> 'catalog.apps.CatalogConfig', </strong> +]</pre> + +<p>La nueva linea especifica el objeto de configuración de la aplicación (<code>CatalogConfig</code>) que se generó para tí en <strong>/locallibrary/catalog/apps.py</strong> cuando creaste la aplicación.</p> + +<div class="note"> +<p><strong>Nota</strong>: Te habrás fijado que hay ya un montón de otras <code>INSTALLED_APPS</code> (y <code>MIDDLEWARE</code>, más abajo en el fichero de ajustes). Éstas habilitan en soporte para el <a href="/es/docs/Learn/Server-side/Django/Admin_site">Sitio de admistración Django</a> y como consecuencia el motón de la funcionalidad que usa (incluyendo sesiones, autenticación, etc).</p> +</div> + +<h2 id="Especificación_de_la_base_de_datos">Especificación de la base de datos</h2> + +<p>Éste es también el punto donde normalmente especificarías la base de datos a utilizar en el proyecto — tiene sentido usar la misma base datos para desarrollo y producción donde sea posible, para evitar diferencias menores en el comportamiento. Puedes encontrar información sobre las diferentes opciones de bases de datos en <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#databases">Databases</a> (Django docs). </p> + +<p>Nosotros usaremos la base de datos SQLite para este ejemplo, porque no esperamos que se requiera un montón de accesos concurrentes en una base de datos de demostración, y también ¡porque no requiere trabajo adicional para ponerla en marcha! Puedes ver cómo está configurada en <strong>settings.py</strong> (más información también se incluye abajo):</p> + +<pre class="brush: python">DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} +</pre> + +<p>Debido a que usamos SQLite, no necesitamos hacer ningún ajuste adicional aquí. ¡Sigamos!</p> + +<h2 id="Otros_ajustes_del_proyecto">Otros ajustes del proyecto</h2> + +<p>El fichero <strong>settings.py</strong> se usa para configurar muchos otros ajustes, pero en este punto probablemente sólo querrás cambiar la <a href="https://docs.djangoproject.com/en/2.0/ref/settings/#std:setting-TIME_ZONE">TIME_ZONE</a> — ésta debería ser igual a una cadena de la <a href="https://en.wikipedia.org/wiki/List_of_tz_database_time_zones">Lista de base de datos tz de time zones</a> (la columna TZ column de la tabla contiene los valores que quieres). Cambia tu <code>TIME_ZONE</code> al valor de entre estas cadenas que sea apropiado para tu zona de tiempo, por ejemplo:</p> + +<pre class="brush: python">TIME_ZONE = 'Europe/Madrid'</pre> + +<p>Hay otros dos otros ajustes que no cambiarás ahora, pero de los que deberías ser consciente:</p> + +<ul> + <li><code>SECRET_KEY</code>. Ésta es una clave secreta que se usa como parte de la estrategia de seguridad del sitio web de Django. Si no vas a proteger este código durante el desarrollo, necesitarás usar un código diferente (quizás leyendo de una variable de entorno o un fichero) cuando lo pongas en producción. </li> + <li><code>DEBUG</code>. Ésto habilita que los registros (logs) de depuración se muestren en caso de error, en vez de las respuestas con los códigos de estado HTTP. Éste debería ajustarse a <code>false</code> en producción, ya que la información de depuración es útil a los atacantes. </li> +</ul> + +<h2 id="Conectar_el_mapeador_URL">Conectar el mapeador URL</h2> + +<p>El sitio web se crea con un fichero mapeador de URLs (<strong>urls.py</strong>) en la carpeta del proyecto. Aunque puedes usar este fichero para gestionar todos tus mapeos URL, es más usual deferir los mapeos a su aplicación asociada.</p> + +<p>Abre <strong>locallibrary/locallibrary/urls.py</strong> y fíjate en el texto educativo que explica algunas formas de usar el mapeador URL. </p> + +<pre class="brush: python">"""locallibrary URL Configuration + +The `urlpatterns` list routes URLs to views. For more information please see: + https://docs.djangoproject.com/en/2.0/topics/http/urls/ +Examples: +Function views + 1. Add an import: from my_app import views + 2. Add a URL to urlpatterns: path('', views.home, name='home') +Class-based views + 1. Add an import: from other_app.views import Home + 2. Add a URL to urlpatterns: path('', Home.as_view(), name='home') +Including another URLconf + 1. Import the include() function: from django.urls import include, path + 2. Add a URL to urlpatterns: path('blog/', include('blog.urls')) +""" +from django.contrib import admin +from django.urls import path + +urlpatterns = [ + path('admin/', admin.site.urls), +] +</pre> + +<p>Los mapeos URL se gestionan a través de la variable <code>urlpatterns</code>, que es una <em>lista</em> Python de funciones <code>path()</code>. Cada función <code>path()</code> o asocia un patrón URL a una <em>vista específica</em>, que se presentará cuando el patrón se empareja o con otra lista de código de comprobación de patrones URL (en este segundo caso, los patrones se convierten en la "URL base" de patrones definidos en el módulo destino). La lista <code>urlpatterns</code> define inicialmente una función que mapea todos los URLs con el patrón <em>admin/</em> al módulo <code>admin.site.urls</code> , que contiene las definiciones de mapeos URL propios de la aplicación de Administración.</p> + +<div class="note"> +<p><strong>Nota</strong>: La ruta en <code>path()</code> es una cadena que define un patrón URL para emparejar. Esta cadena podría incluir una variable nombrada (entre paréntesis angulares), ej. <code>'catalog/<id>/'</code>. Este patrón emparejará con una URL como <strong>/catalog/</strong><em>any_chars</em><strong>/</strong> y pasará a la vista <em>any_chars</em> como cadena asociada al parámetro de nombre <code>id</code>). Trataremos de los métodos de caminos y rutas de patrones más adelante en los últimos temas.</p> +</div> + +<p>Añade las lineas de abajo al final del fichero para añadir un nuevo elemento a la lista <code>urlpatterns</code>. Este nuevo elemento incluye un <code>path()</code> que redirige las peticiones con el patrón <code>catalog/</code> al módulo<code>catalog.urls</code> (el fichero con el URL relativo <strong>/catalog/urls.py</strong>).</p> + +<pre class="brush: python"># Use include() to add paths from the catalog application +from django.urls import include + +urlpatterns += [ + path('catalog/', include('catalog.urls')), +] +</pre> + +<p>Ahora redirijamos la URL raíz de nuestro sitio (ej. <code>127.0.0.1:8000</code>) al URL <code>127.0.0.1:8000/catalog/</code>; esta es la única app que usaremos en este proyecto, así que es lo que deberíamos hacer. Para hacer esto, usaremos una función especial (<code>RedirectView</code>), que toma como su primer argumento la nueva URL relativa a redirigir a (<code>/catalog/</code>) cuando el patrón URL especificado en la función <code>path()</code> se empareja (la URL raíz, en este caso).</p> + +<p>Añade las siguientes líneas, otra vez al final del fichero:</p> + +<pre class="brush: python">#Add URL maps to redirect the base URL to our application +from django.views.generic import RedirectView +urlpatterns += [ + path('', RedirectView.as_view(url='/catalog/', permanent=True)), +]</pre> + + + +<p>Deja el primer parámetro de la función path vacío, para implicar '/'. Si escribes el primer parámetro como '/' Django te dará la siguiente advertencia cuando arranque el servidor de desarrollo:</p> + +<p><em>La comprobación del sistema encontró algunos problemas:</em></p> + +<pre><em>WARNINGS: +?: (urls.W002) Tu patrón URL '/' tiene una ruta que empieza con una '/'. +Quita esta barra invertida ya que es inncesaria. +Si este patrón figura como destino en un include(), asegúrate que el patrón include() tiene un '/' final.</em></pre> + + + +<p>Django no sirve ficheros estáticos como CSS, JavaScript e imágenes por defecto, pero puede ser útil para el servidor web de desarrollo hacerlo así mientras creas tu sitio. Como adición final a este mapeador URL, puedes habilitar el servicio de ficheros estáticos durante el desarrollo añadiendo las líneas siguientes.</p> + +<p>Añade ahora el siguiente bloque final al final del fichero:</p> + +<pre><code># Use static() to add url mapping to serve static files during development (only) +from django.conf import settings +from django.conf.urls.static import static + +urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)</code> +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Hay numerosas formas de extender la lista <code>urlpatterns</code> (arriba hemos añadido simplemente un nuevo elemento a la lista usando el operador<span style="font-size: 1.125rem;"> </span><code>+=</code><span style="font-size: 1.125rem;"> para separar claramente el código antiguo y el nuevo</span><span style="font-size: 1.125rem;">). En vez de ello podríamos haber simplemente incluido este nuevo patrón de mapeo en la definición de la lista original:</span></p> + +<pre class="brush: python">urlpatterns = [ + path('admin/', admin.site.urls), + path('catalog/', include('catalog.urls')), + path('/', RedirectView.as_view(url='/catalog/', permanent=True)), +] + <code>static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)</code> +</pre> + +<p>Además, hemos incluido la linea import (<code>from django.urls import include</code>) con el código que la usa (de manera que sea fácil ver qué hemos añadido), pero es común incluir todas tus líneas import al principio del fichero Python.</p> +</div> + +<p>Como paso final, crea un fichero dentro de tu carpeta catalog llamado <strong>urls.py</strong>, y añade el siguiente texto para definir la <code>urlpatterns</code> importada (vacía). Éste es donde añadimos nuestros patrones a medida que construimos la aplicación. </p> + +<pre class="brush: python">from django.conf.urls import url + +from . import views + + +urlpatterns = [ + +] +</pre> + +<h2 id="Prueba_del_framework_del_sitio_web">Prueba del framework del sitio web</h2> + +<p>En este punto tenemos un proyecto de esqueleto completo. El sitio web <em>no hace</em> realmente nada todavía, pero merece la pena ejecutarlo para estar seguros de que ninguno de nuestros cambios no han roto nada.</p> + +<p>Antes de hacerlo, deberíamos primero ejecutar una <em>migración de la base de datos</em>. Ésto actualiza nuestra base de datos para incluir todos los modelos de nuestras aplicaciones instaladas (y eliminar algunas advertencias de construcción).</p> + +<h3 id="Ejecución_de_migraciones_de_la_base_de_datos">Ejecución de migraciones de la base de datos</h3> + +<p>Django usa un Object-Relational-Mapper (ORM) para mapear las definiciones de Modelos en el código Django con la estructura de datos utilizada por la base de datos subyacente. A medida que cambiamos nuestras definiciones de modelos, Django sigue la pista a los cambios y puede crear scripts de migración de la base de datos (en <strong>/locallibrary/catalog/migrations/</strong>) para migrar automáticamente la estructura de datos subyacente en el base de datos para igualarse al modelo.</p> + +<p>Cuando creamos el sitio web de Django añadimos automáticamente unos cuantos modelos para que ser usados por la sección de administración del sitio (al que echaremos un vistazo más tarde). Ejecuta los siguientes comandos para definir tablas para esos modelos de la base (asegúrate que estás en el directorio que contiene <strong>manage.py</strong>):</p> + +<pre class="brush: bash">python3 manage.py makemigrations +python3 manage.py migrate +</pre> + +<div class="warning"> +<p><strong>Importante</strong>: Necesitarás ejecutar los comandos de arriba cada vez que cambien tus modelos de una manera que afecte a la estructura de datos y necesite ser guardada (incluyendo tanto la adicción como la eliminación de modelos enteros o campos individuales).</p> +</div> + +<p>El comando <code>makemigrations</code> <em>crea</em> (pero no aplica) las migraciones para todas las aplicaciones instaladas en tu proyecto (también puedes especificar el nombre de una aplicación para ejecutar una migración para un sólo proyecto). Ésto te da la opoortunidad de comprobar el código para estas migraciones antes de que se apliquen — cuando seas un experto en Django ¡podrás elegir modificarlos ligeramente!</p> + +<p>El comando <code>migrate</code> aplica realmente las migraciones a tu base de datos (Django lleva la cuenta de cuáles han sido añadidas a la base de datos actual).</p> + +<div class="note"> +<p><strong>Nota</strong>: Mira en <a href="https://docs.djangoproject.com/en/2.0/topics/migrations/">Migrations</a> (Django docs) para obtener información adicional sobre los comandos de migración menos usados.</p> +</div> + +<h3 id="Arrancando_el_sitio_web">Arrancando el sitio web</h3> + +<p>Durante el desarrollo puedes probar el sitio web usando para servirlo el <em>servidor de desarrollo web</em>, y visualizádolo en tu explorador web local. </p> + +<div class="note"> +<p><strong>Nota</strong>: el servidor web de desarrollo no es robusto y sin suficientes prestaciones para su uso en producción, pero es una manera muy fácil de tener levantado y funcionando tu sitio web Django durante el desarrollo para hacerle una prueba rápida y conveniente. Por defecto servirá el sitio a tu computadora local <span style="font-size: 1.125rem;">(</span><code>http://127.0.0.1:8000/)</code><span style="font-size: 1.125rem;">, pero puedes también especificar que se sirva a otras computdoras en tu red.</span><span style="font-size: 1.125rem;"> Para más información ver </span><a href="https://docs.djangoproject.com/en/2.0/ref/django-admin/#runserver" style="font-size: 1.125rem;">django-admin y manage.py: runserver</a><span style="font-size: 1.125rem;"> (Django docs).</span></p> +</div> + +<p>Ejecuta el <em>servidor web de desarrollo</em> llamando al comando <code>runserver</code> (en el mismo directorio donde está <strong>manage.py</strong>):</p> + +<pre class="brush: bash">python3 manage.py runserver + + Performing system checks... + + System check identified no issues (0 silenced). + September 22, 2016 - 16:11:26 + Django version 1.10, using settings 'locallibrary.settings' + Starting development server at http://127.0.0.1:8000/ + Quit the server with CTRL-BREAK. +</pre> + +<p>Una vez que el servidor está funcionando puedes ver el sitio navegando a <code>http://127.0.0.1:8000/</code> en tu explorador local. Deberías ver una página de error del sitio que tiene el siguiente aspecto:</p> + +<p><img alt="Django Debug page for Django 2.0" src="https://mdn.mozillademos.org/files/15729/django_404_debug_page.png"></p> + +<p>¡No te preocupes! Esta página de error es lo esperado porque no tenemos ninguna página/url definidas en el módulo <code>catalogs.urls</code> (que es al que nos redirigimos cuando obtenemos la URL a la raíz del sitio). </p> + +<div class="note"> +<p><strong>Nota</strong>: La página superior demuestra una gran característica de Django— El registro de depuración automático. Cada vez que una página no pueda ser encontrada, o el código provoque un error cualquiera, se mostrará una pantalla de error con información útil. En este caso vemos que la URL que hemos suministrado no empareja con ninguno de nuestros patrones de URL (como los listados). El resgistro de depuración puede desconectarse durante la producción (cuando colocamos el sitio en vivo en la Web), en cuyo caso se servirá una página menos informativa pero más amigable.</p> +</div> + +<p>¡En este punto ya sabemos que Django está funcionando!</p> + +<div class="note"> +<p><strong>Nota</strong>: Deberías volver a ejecutar las migraciones y volver a probar el sitio cada vez que hagas cambios significativos. ¡No lleva tanto tiempo!</p> +</div> + +<h2 id="Desafíate_a_tí_mismo">Desafíate a tí mismo</h2> + +<p>El directorio <strong>catalog/</strong> contiene ficheros para las vistas, modelos y otras partes de la aplicación. Abre estos ficheros e inspecciona el código base. </p> + +<p>Como has visto arriba, se ha añadido ya un mapeo de URLs para el sitio de administración en el fichero del proyecto <strong>urls.py</strong>. Navega al área de adminsitración en tu explorador y mira qué sucede (puedes inferir el URL correcto de los mapeos de arriba).</p> + +<ul> +</ul> + +<h2 id="Sumario">Sumario</h2> + +<p>ahora ya has creado un proyecto de esqueleto completo de sitio web, con el que puedes continuar rellenando con urls, modelos, vistas y plantillas.</p> + +<p>Ahora que el esqueleto del <a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">sitio web de la BibliotecaLocal</a> está completo y funcionando, es hora de empezar a escribir el código que hace que este sitio haga lo que se supone que debe hacer. </p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/2.0/intro/tutorial01/">Escribiendo tu primera aplicación Django - parte 1</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/2.0/ref/applications/#configuring-applications">Aplicaciones</a> (Django Docs). Contiene información sobre cómo configurar aplicaciones.</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Tutorial_local_library_website", "Learn/Server-side/Django/Models", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/testing/index.html b/files/es/learn/server-side/django/testing/index.html new file mode 100644 index 0000000000..54055b2780 --- /dev/null +++ b/files/es/learn/server-side/django/testing/index.html @@ -0,0 +1,906 @@ +--- +title: 'Tutorial de Django Parte 10: Probando una aplicación web Django' +slug: Learn/Server-side/Django/Testing +translation_of: Learn/Server-side/Django/Testing +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Forms", "Learn/Server-side/Django/Deployment", "Learn/Server-side/Django")}}</div> + +<p class="summary">A medida que crecen los sitios web se vuelven más difíciles de probar a mano — no sólo hay más para probar, sino que además, a medida que las interacciones entre los componentes se vuelven más complejas, un pequeño cambio en un área puede suponer muchas pruebas adicionales para verificar su impacto en otras áreas. Una forma de mitigar estos problemas es escribir tests automatizados, que pueden ser ejecutados de manera fácil y fiable cada vez que hagas un cambio. Este tutorial muestra cómo automatizar la unidad de pruebas de tu sitio web usando el framework de pruebas de Django.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisites:</th> + <td>Completa todos los tópicos anteriores, incluyendo <a href="/en-US/docs/Learn/Server-side/Django/Forms">Tutorial Django Parte 9: Trabajando con formularios</a>.</td> + </tr> + <tr> + <th scope="row">Objective:</th> + <td>Entender como escribir pruebas unidatarias para django basado en Páginas web.</td> + </tr> + </tbody> +</table> + +<h2 id="Vista_previa">Vista previa</h2> + +<p>El <a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">Local Library</a> actualmente tiene páginas para mostrar las listas con todos los libros y autores, vistas detalladas para los items de <code>Book</code> y <code>Author,</code><span class="tlid-translation translation" lang="es"><span title="">una página para renovar BookInstances y páginas para crear, actualizar y eliminar elementos de autor (y también registros de libros, si usted completó el desafío en el tutorial de formularios).</span> <span title="">Incluso con este sitio relativamente pequeño, navegar manualmente a cada página y verificar superficialmente que todo funcione como se espera, puede llevar varios minutos.</span> <span title="">A medida que hagamos cambios y el sitio vaya creciendo, el tiempo requerido para verificar manualmente que todo funcione "correctamente", aumentará de forma muy perniciosa.</span> <span title="">Si continuamos como estamos, pasaríamos la mayor parte de nuestro tiempo probando, y muy poco tiempo mejorando nuestro código.</span></span></p> + +<p>¡Las pruebas automatizadas realmente pueden ayudar con este problema! Los beneficios obvios son que pueden ejecutarse mucho más rápido que las pruebas manuales, pueden probar con un nivel de detalle mucho más bajo y probar exactamente la misma funcionalidad cada vez (¡los testers humanos no son tan confiables!) Porque son pruebas rápidas y automatizadas se puede ejecutar más regularmente, y si falla una prueba,<br> + señalan exactamente dónde el código no está funcionando como se esperaba.</p> + +<p><span class="tlid-translation translation" lang="es"><span title="">Además, las pruebas automatizadas pueden actuar como el primer "usuario" del mundo real de su código, lo que le obliga a ser riguroso a la hora de definir y documentar bien, cómo debe comportarse su sitio web.</span> <span title="">A menudo son la base de sus ejemplos de código y documentación.</span> <span title="">Por estas razones, algunos procesos de desarrollo de software comienzan con la definición e implementación de la prueba, después de lo cual el código se escribe para que coincida con el comportamiento requerido (por ejemplo, desarrollo basado en pruebas y en comportamiento).</span><br> + <br> + <span title="">Este tutorial muestra cómo escribir pruebas automatizadas para Django, agregando una serie de pruebas al sitio web LocalLibrary.</span></span></p> + +<h3 id="Tipos_de_pruebas">Tipos de pruebas</h3> + +<p>Hay numeroso tipos, niveles y clasificaciones de pruebas y enfoques de pruebas. Las pruebas automáticas más importantes son:</p> + +<dl> + <dt>Pruebas unitarias</dt> + <dd>Verifica el comportamiento funcional de un componente individual, a menudo de una clase y su nivel de funcional.</dd> + <dt>Pruebas de regresión</dt> + <dd>Pruebas que reproducen errores históricos. Cada prueba es inicialmente ejecutada para verificar que el error ha sido corregido, y estos son ejecutados de nuevo para asegurarnos que los errores no fueron reintroducidos con los futuros cambios en el código.</dd> + <dt>Pruebas de integración</dt> + <dd>Verifica cómo funcionan los grupos de componentes cuando se usan juntos. Las pruebas de integración son conscientes de las interacciones requeridas entre componentes, pero no necesariamente de las operaciones internas de cada componente. Pueden cubrir agrupaciones simples de componentes hasta todo el sitio web.</dd> +</dl> + +<div class="note"> +<p><strong>Nota: </strong>Otros tipos comunes de pruebas incluyen pruebas de caja negra, caja blanca, manuales, automatizadas, canarias, de humo, de conformidad, de aceptación, funcionales, de rendimiento, de carga y de esfuerzo. Búscalos para más información.</p> +</div> + +<h3 id="Que_provee_Django_para_pruebas">Que provee Django para pruebas?</h3> + +<p>Probar un sitio web es una tarea compleja, porque está compuesto por varias capas de lógica, desde el manejo de solicitudes a nivel HTTP, modelos de consultas, hasta la validación y procesamiento de formularios y la representación de plantillas.</p> + +<p>Django proporciona un marco de prueba con una pequeña jerarquía de clases que se basan en la libreria <code><a href="https://docs.python.org/3/library/unittest.html#module-unittest" title="(in Python v3.5)">unittest</a></code> estándar Python. A pesar del nombre, este marco de prueba es adecuado tanto para pruebas unitarias como de integración. El marco de Django agrega métodos y herramientas API para ayudar a probar el comportamiento web y específico de Django. Estos le permiten simular solicitudes, insertar datos de prueba e inspeccionar la salida de su aplicación. Django también proporciona una API(<a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#liveservertestcase">LiveServerTestCase</a>) y herramientas para <a href="https://docs.djangoproject.com/en/1.10/topics/testing/advanced/#other-testing-frameworks">usar diferentes frameworks de pruebas</a> , por ejemplo, puede integrarse con el popular framework <a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment">Selenium</a> para simular la interacción de un usuario con un navegador en vivo.</p> + +<p>Para escribir una prueba, se deriva de cualquiera de las clases base de prueba de Django (o unittest)(<a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#simpletestcase">SimpleTestCase</a>, <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#transactiontestcase">TransactionTestCase</a>, <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#testcase">TestCase</a>, <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#liveservertestcase">LiveServerTestCase</a>) y luego escribir métodos separados para verificar que la funcionalidad específica funcione como se esperaba (las pruebas usan métodos "assert" para probar que las expresiones dan valores <code>True</code> o <code>False</code>, o que dos valores son iguales, etc.) Cuando inicia una ejecución de prueba, el marco ejecuta los métodos de prueba elegidos en sus clases derivadas. Los métodos de prueba se ejecutan de forma independiente, con un comportamiento común de configuración y / o desmontaje definido en la clase, como se muestra a continuación.</p> + +<pre class="brush: python notranslate">class YourTestClass(TestCase): + + def setUp(self): + #Setup run before every test method. + pass + + def tearDown(self): + #Clean up run after every test method. + pass + + def test_something_that_will_pass(self): + self.assertFalse(False) + + def test_something_that_will_fail(self): + self.assertTrue(False) +</pre> + +<p>La mejor clase base para la mayoría de las pruebas es <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#testcase">django.test.TestCase</a>. Esta clase de prueba crea una base de datos limpia antes de que se ejecuten sus pruebas y ejecuta cada función de prueba en su propia transacción. La clase también posee una prueba <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#django.test.Client" title="django.test.Client">Client</a> que puede utilizar para simular la interacción de un usuario con el código en el nivel de vista. En las siguientes secciones, nos concentraremos en las pruebas unitarias, creadas con esta clase <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#testcase">TestCase</a></p> + +<div class="note"> +<p><strong>Nota:</strong> La clase <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#testcase">django.test.TestCase</a> es muy conveniente, pero puede resultar en que algunas pruebas sean más lentas de lo necesario (no todas las pruebas necesitarán configurar su propia base de datos o simular la interacción de la vista). Una vez que esté familiarizado con lo que puede hacer con esta clase, es posible que desee reemplazar algunas de sus pruebas con las clases de prueba más simples disponibles.</p> +</div> + +<h3 id="Que_deberias_probar">Que deberias probar?</h3> + +<p>Debe probar todos los aspectos de su propio código, pero no ninguna biblioteca o funcionalidad proporcionada como parte de Python o Django.</p> + +<p>Por ejemplo, considere el modelo <code>Author</code> definido abajo. No es necesario probarlo explícitamente <code>first_name</code> y <code>last_name</code> han sido almacenados correctamente como <code>CharField</code> en la base de datos porque eso es algo definido por Django (aunque, por supuesto, en la práctica, inevitablemente probará esta funcionalidad durante el desarrollo). Tampoco es necesario probar que el <code>date_of_birth</code> ha sido validado para ser un campo de fecha, porque nuevamente es algo implementado en Django.</p> + +<p>Sin embargo, debe verificar el texto utilizado para las etiquetas (nombre, apellido, fecha de nacimiento, fallecimiento) y el tamaño del campo asignado para el texto (100 caracteres), porque estos son parte de su diseño y algo que podría ser roto / cambiado en el futuro.</p> + +<pre class="brush: python notranslate">class Author(models.Model): + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + date_of_birth = models.DateField(null=True, blank=True) + date_of_death = models.DateField('Died', null=True, blank=True) + + def get_absolute_url(self): + return reverse('author-detail', args=[str(self.id)]) + + def __str__(self): + return '%s, %s' % (self.last_name, self.first_name)</pre> + +<p>Del mismo modo, debe verificar que los métodos personalizados <code style="font-style: normal; font-weight: normal;">get_absolute_url()</code> y <code style="font-style: normal; font-weight: normal;">__str__()</code>comportarse como sea necesario porque son su código / lógica empresarial. En el caso de <code style="font-style: normal; font-weight: normal;">get_absolute_url()</code> puedes confiar en que el metodo de Django <code>reverse()</code> se ha implementado correctamente, por lo que lo que está probando es que la vista asociada se haya definido realmente.</p> + +<div class="note"> +<p><strong>Nota:</strong> Los lectores astutos pueden notar que también querríamos restringir la fecha de nacimiento y muerte a valores sensibles, y comprobar que la muerte viene después del nacimiento. En Django, esta restricción se agregaría a sus clases de formulario (aunque puede definir validadores para los campos, estos parecen usarse solo en el nivel del formulario, no en el nivel del modelo).</p> +</div> + +<p>Con eso en mente, comencemos a ver cómo definir y ejecutar pruebas.</p> + +<h2 id="Descripción_general_de_la_estructura_de_prueba">Descripción general de la estructura de prueba</h2> + +<p>Antes de entrar en los detalles de "qué probar", primero veamos brevemente dónde y cómo se definen las pruebas..</p> + +<p>Django utiliza el descubrimiento de pruebas integrado del módulo unittest (<a href="https://docs.python.org/3/library/unittest.html#unittest-test-discovery" title="(in Python v3.5)">built-in test discovery)</a>, que descubrirá pruebas en el directorio de trabajo actual en cualquier archivo nombrado con el patrón <strong>test*.py</strong>. Siempre que asigne un nombre a los archivos de forma adecuada, puede utilizar la estructura que desee. Le recomendamos que cree un módulo para su código de prueba y que tenga archivos separados para modelos, vistas, formularios y cualquier otro tipo de código que necesite probar. Por ejemplo:</p> + +<pre class="notranslate">catalog/ + /tests/ + __init__.py + test_models.py + test_forms.py + test_views.py +</pre> + +<p>Cree una estructura de archivo como se muestra arriba en su proyecto <em>LocalLibrary</em>. El <strong>__init__.py</strong> debe ser un archivo vacío (esto le dice a Python que el directorio es un paquete). Puede crear los tres archivos de prueba copiando y cambiando el nombre del archivo de prueba de esqueleto <strong>/catalog/tests.py</strong>.</p> + +<div class="note"> +<p><strong>Note:</strong>El archivo de prueba <strong>/catalog/tests.py</strong>se creó automáticamente cuando creamos el sitio web esqueleto de Django ( <a href="/en-US/docs/Learn/Server-side/Django/skeleton_website">built the Django skeleton website)</a>.</p> + +<p>Es perfectamente "legal" poner todas sus pruebas dentro de él, pero si prueba correctamente, rápidamente terminará con un archivo de prueba muy grande e inmanejable.</p> + +<p>Elimina el archivo esqueleto ya que no lo necesitaremos.</p> +</div> + +<p>Abre el archivo <strong>/catalog/tests/test_models.py</strong>. El archivo debe importar <code>django.test.TestCase</code>, como se muestra:</p> + +<pre class="brush: python notranslate">from django.test import TestCase + +# Create your tests here. +</pre> + +<p>A menudo, agregará una clase de prueba para cada modelo / vista / formulario que desee probar, con métodos individuales para probar una funcionalidad específica. En otros casos, es posible que desee tener una clase separada para probar un caso de uso específico, con funciones de prueba individuales que prueben aspectos de ese caso de uso (por ejemplo, una clase para probar que un campo de modelo está validado correctamente, con funciones para probar cada uno de los posibles casos de falla). Una vez más, la estructura depende en gran medida de usted, pero es mejor si es coherente.</p> + +<p>Agregue la clase de prueba a continuación al final del archivo. La clase demuestra cómo construir una clase de caso de prueba derivando de <code>TestCase</code>.</p> + +<pre class="brush: python notranslate">class YourTestClass(TestCase): + + @classmethod + def setUpTestData(cls): + print("setUpTestData: Run once to set up non-modified data for all class methods.") + pass + + def setUp(self): + print("setUp: Run once for every test method to setup clean data.") + pass + + def test_false_is_false(self): + print("Method: test_false_is_false.") + self.assertFalse(False) + + def test_false_is_true(self): + print("Method: test_false_is_true.") + self.assertTrue(False) + + def test_one_plus_one_equals_two(self): + print("Method: test_one_plus_one_equals_two.") + self.assertEqual(1 + 1, 2)</pre> + +<p>La nueva clase define dos métodos que puede utilizar para la configuración previa a la prueba (por ejemplo, para crear modelos u otros objetos que necesitará para la prueba):</p> + +<ul> + <li><code>setUpTestData()</code> se llama una vez al comienzo de la ejecución de prueba para la configuración a nivel de clase. Usaría esto para crear objetos que no se modificarán ni cambiarán en ninguno de los métodos de prueba.</li> + <li><code>setUp()</code> se llama antes de cada función de prueba para configurar cualquier objeto que pueda ser modificado por la prueba (cada función de prueba obtendrá una versión "nueva" de estos objetos).</li> +</ul> + +<div class="note"> +<p>Las clases de prueba también tienen un metodo <code>tearDown()</code> que no hemos utilizado. Este método no es particularmente útil para las pruebas de bases de datos, ya que <code>TestCase</code> la clase base se encarga del desmontaje de la base de datos por usted.</p> +</div> + +<p>Debajo de ellos tenemos una serie de métodos de prueba, que utilizamos funciones <code>Assert</code> toprobar si las condiciones son verdaderas, falsas o iguales (<code>AssertTrue</code>, <code>AssertFalse</code>, <code>AssertEqual</code>). Si la condición no se evalúa como se esperaba, la prueba fallará y reportará el error a su consola.</p> + +<p>Los <code>AssertTrue</code>, <code>AssertFalse</code>, <code>AssertEqual</code> son afirmaciones estándar proporcionadas por <strong>unittest</strong>. Hay otras aserciones estándar en el marco y también aserciones específicas de Django (<a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#assertions">Django-specific assertions</a>) para probar si una vista redirecciona (<code>assertRedirects</code>),para probar si se ha utilizado una plantilla en particular (<code>assertTemplateUsed</code>), etc.</p> + +<div class="note"> +<p>Normalmente no debería incluir funciones print () en sus pruebas como se muestra arriba. Lo hacemos aquí solo para que pueda ver el orden en que se llaman las funciones de configuración en la consola (en la siguiente sección).</p> +</div> + +<h2 id="Como_correr_las_pruebas">Como correr las pruebas</h2> + +<p>La forma más sencilla de ejecutar todas las pruebas es utilizar el comando:</p> + +<pre class="brush: bash notranslate">python3 manage.py test</pre> + +<p>Esto descubrirá todos los archivos nombrados con el patrón <strong>test*.py</strong> bajo el directorio actual y ejecute todas las pruebas definidas usando las clases base apropiadas (aquí tenemos una serie de archivos de prueba, pero solo <strong>/catalog/tests/test_models.py</strong> contiene actualmente cualquier prueba). De forma predeterminada, las pruebas informarán individualmente solo sobre las fallas de las pruebas, seguidas de un resumen de la prueba.</p> + +<div class="note"> +<p>Si recibe errores similares a: <code>ValueError: Missing staticfiles manifest entry ...</code> esto puede deberse a que las pruebas no ejecutan collectstatic de forma predeterminada y su aplicación usa una clase de almacenamiento que lo requiere (consulte manifest_strict para obtener más información). Hay varias formas de superar este problema; la más fácil es simplemente ejecutar collectstatic antes de ejecutar las pruebas:</p> + +<pre class="brush: bash notranslate">python3 manage.py collectstatic +</pre> +</div> + +<p>Ejecute las pruebas en el directorio raíz de LocalLibrary. Debería ver un resultado como el siguiente.</p> + +<pre class="brush: bash notranslate">>python manage.py test + +Creating test database for alias 'default'... +<strong>setUpTestData: Run once to set up non-modified data for all class methods. +setUp: Run once for every test method to setup clean data. +Method: test_false_is_false. +.setUp: Run once for every test method to setup clean data. +Method: test_false_is_true. +FsetUp: Run once for every test method to setup clean data. +Method: test_one_plus_one_equals_two.</strong> +. +====================================================================== +FAIL: test_false_is_true (catalog.tests.tests_models.YourTestClass) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "D:\Github\django_tmp\library_w_t_2\locallibrary\catalog\tests\tests_models.py", line 22, in test_false_is_true + self.assertTrue(False) +AssertionError: False is not true + +---------------------------------------------------------------------- +Ran 3 tests in 0.075s + +FAILED (failures=1) +Destroying test database for alias 'default'...</pre> + +<p>Aquí vemos que tuvimos una falla de prueba, y podemos ver exactamente qué función falló y por qué (se espera esta falla, porque <code>False</code> no es <code>True</code>!).</p> + +<div class="note"> +<p>Sugerencia: Lo más importante que debe aprender del resultado de la prueba anterior es que es mucho más valioso si usa nombres descriptivos / informativos para sus objetos y métodos.</p> +</div> + +<p>El texto que se muestra en <strong>negritas</strong> anterior normalmente no aparecería en la salida de prueba (esto es generado por la funcion <code>print()</code> en nuestra prueba). Esto muestra el metodo <code>setUpTestData()</code> es llamado una vez para la clase y <code>setUp()</code>se llama antes de cada método.</p> + +<p>Las siguientes secciones muestran cómo puede ejecutar pruebas específicas y cómo controlar cuánta información muestran las pruebas.</p> + +<h3 id="Mostrando_más_información_de_las_pruebas">Mostrando más información de las pruebas</h3> + +<p>Si desea obtener más información sobre la ejecución de prueba, puede cambiar el nivel de detalle. Por ejemplo, para enumerar los éxitos y fallas de la prueba (y una gran cantidad de información sobre cómo está configurada la base de datos de prueba), puede establecer la verbosidad en "2" como se muestra:</p> + +<pre class="brush: bash notranslate">python3 manage.py test --verbosity 2</pre> + +<p>The allowed verbosity levels are 0, 1, 2, and 3, with the default being "1".</p> + +<h3 id="Ejecutando_pruebas_especificas">Ejecutando pruebas especificas</h3> + +<p>Si desea ejecutar un subconjunto de sus pruebas, puede hacerlo especificando la ruta de puntos completa al paquete (s), módulo, <code>TestCase</code> subclase o metodo:</p> + +<pre class="brush: bash notranslate">python3 manage.py test catalog.tests # Run the specified module +python3 manage.py test catalog.tests.test_models # Run the specified module +python3 manage.py test catalog.tests.test_models.YourTestClass # Run the specified class +python3 manage.py test catalog.tests.test_models.YourTestClass.test_one_plus_one_equals_two # Run the specified method +</pre> + +<h2 id="Pruebas_en_el_proyecto_LocalLibrary">Pruebas en el proyecto LocalLibrary</h2> + +<p>Ahora que sabemos cómo ejecutar nuestras pruebas y qué tipo de cosas necesitamos probar, veamos algunos ejemplos prácticos.</p> + +<div class="note"> +<p>Nota: No escribiremos todas las pruebas posibles, pero esto debería darle una idea de cómo funcionan las pruebas y qué más puede hacer.</p> +</div> + +<h3 id="Modelos">Modelos</h3> + +<p>Como se discutió anteriormente, debemos probar todo lo que sea parte de nuestro diseño o que esté definido por el código que hayamos escrito, pero no las bibliotecas / código que ya haya probado Django o el equipo de desarrollo de Python.</p> + +<p>Por ejemplo, considere el modelo de <code>Author</code> a continuación. Aquí deberíamos probar las etiquetas para todos los campos, porque aunque no hemos especificado explícitamente la mayoría de ellos, tenemos un diseño que dice cuáles deberían ser estos valores. Si no probamos los valores, entonces no sabemos que las etiquetas de los campos tienen sus valores deseados. De manera similar, aunque confiamos en que Django creará un campo de la longitud especificada, vale la pena especificar una prueba para esta longitud para asegurarse de que se implementó según lo planeado.</p> + +<pre class="brush: python notranslate">class Author(models.Model): + first_name = models.CharField(max_length=100) + last_name = models.CharField(max_length=100) + date_of_birth = models.DateField(null=True, blank=True) + date_of_death = models.DateField('Died', null=True, blank=True) + + def get_absolute_url(self): + return reverse('author-detail', args=[str(self.id)]) + + def __str__(self): + return '%s, %s' % (self.last_name, self.first_name)</pre> + +<p>Abra su <strong>/catalog/tests/test_models.py</strong>, y reemplace cualquier código existente con el siguiente código de prueba para el modelo de <code>Author</code>.</p> + +<p>Aquí usted verá que primero importamos <code>TestCase</code> y derivamos nuestras clases de prueba (<code>AuthorModelTest</code>) de ello, usando un nombre descriptive para que así podamos fácilmente cualquier pruebas fallidas en el output de la prueba. Luego llamamos a <code>setUpTestData()</code> para crear un objeto de autor que usaremos pero no modificaremos en ninguna de las pruebas.</p> + +<pre class="brush: python notranslate">from django.test import TestCase + +# Create your tests here. + +from catalog.models import Author + +class AuthorModelTest(TestCase): + + @classmethod + def setUpTestData(cls): + #Set up non-modified objects used by all test methods + Author.objects.create(first_name='Big', last_name='Bob') + + def test_first_name_label(self): + author=Author.objects.get(id=1) + field_label = author._meta.get_field('first_name').verbose_name + self.assertEquals(field_label,'first name') + + def test_date_of_death_label(self): + author=Author.objects.get(id=1) + field_label = author._meta.get_field('date_of_death').verbose_name + self.assertEquals(field_label,'died') + + def test_first_name_max_length(self): + author=Author.objects.get(id=1) + max_length = author._meta.get_field('first_name').max_length + self.assertEquals(max_length,100) + + def test_object_name_is_last_name_comma_first_name(self): + author=Author.objects.get(id=1) + expected_object_name = '%s, %s' % (author.last_name, author.first_name) + self.assertEquals(expected_object_name,str(author)) + + def test_get_absolute_url(self): + author=Author.objects.get(id=1) + #This will also fail if the urlconf is not defined. + self.assertEquals(author.get_absolute_url(),'/catalog/author/1')</pre> + +<p>The field tests check that the values of the field labels (<code>verbose_name</code>) and that the size of the character fields are as expected. These methods all have descriptive names, and follow the same pattern:</p> + +<pre class="brush: python notranslate">author=Author.objects.get(id=1) # Get an author object to test +field_label = author._meta.get_field('first_name').verbose_name # Get the metadata for the required field and use it to query the required field data +self.assertEquals(field_label,'first name') # Compare the value to the expected result</pre> + +<p>The interesting things to note are:</p> + +<ul> + <li>We can't get the <code>verbose_name</code> directly using <code>author.first_name.verbose_name</code>, because <code>author.first_name</code> is a <em>string</em> (not a handle to the <code>first_name</code> object that we can use to access its properties). Instead we need to use the author's <code>_meta</code> attribute to get an instance of the field and use that to query for the additional information.</li> + <li>We chose to use <code>assertEquals(field_label,'first name')</code> rather than <code>assertTrue(field_label == 'first name')</code>. The reason for this is that if the test fails the output for the former tells you what the label actually was, which makes debugging the problem just a little easier.</li> +</ul> + +<div class="note"> +<p><strong>Note:</strong> Tests for the <code>last_name</code> and <code>date_of_birth</code> labels, and also the test for the length of the <code>last_name</code> field have been omitted. Add your own versions now, following the naming conventions and approaches shown above.</p> +</div> + +<p>We also need to test our custom methods. These essentially just check that the object name was constructed as we expected using "Last Name", "First Name" format, and that the URL we get for an <code>Author</code> item is as we would expect.</p> + +<pre class="brush: python notranslate">def test_object_name_is_last_name_comma_first_name(self): + author=Author.objects.get(id=1) + expected_object_name = '%s, %s' % (author.last_name, author.first_name) + self.assertEquals(expected_object_name,str(author)) + +def test_get_absolute_url(self): + author=Author.objects.get(id=1) + #This will also fail if the urlconf is not defined. + self.assertEquals(author.get_absolute_url(),'/catalog/author/1')</pre> + +<p>Run the tests now. If you created the Author model as we described in the models tutorial it is quite likely that you will get an error for the <code>date_of_death</code> label as shown below. The test is failing because it was written expecting the label definition to follow Django's convention of not capitalising the first letter of the label (Django does this for you).</p> + +<pre class="brush: bash notranslate">====================================================================== +FAIL: test_date_of_death_label (catalog.tests.test_models.AuthorModelTest) +---------------------------------------------------------------------- +Traceback (most recent call last): + File "D:\...\locallibrary\catalog\tests\test_models.py", line 32, in test_date_of_death_label + self.assertEquals(field_label,'died') +AssertionError: 'Died' != 'died' +- Died +? ^ ++ died +? ^</pre> + +<p>This is a very minor bug, but it does highlight how writing tests can more thoroughly check any assumptions you may have made.</p> + +<div class="note"> +<p><strong>Note: </strong>Change the label for the date_of_death field (/catalog/models.py) to "died" and re-run the tests.</p> +</div> + +<p>The patterns for testing the other models are similar so we won't continue to discuss these further. Feel free to create your own tests for the our other models.</p> + +<h3 id="Formularios">Formularios</h3> + +<p>The philosophy for testing your forms is the same as for testing your models; you need to test anything that you've coded or your design specifies, but not the behaviour of the underlying framework and other third party libraries.</p> + +<p>Generally this means that you should test that the forms have the fields that you want, and that these are displayed with appropriate labels and help text. You don't need to verify that Django validates the field type correctly (unless you created your own custom field and validation) — i.e. you don't need to test that an email field only accepts emails. However you would need to test any additional validation that you expect to be performed on the fields and any messages that your code will generate for errors.</p> + +<p>Consider our form for renewing books. This has just one field for the renewal date, which will have a label and help text that we will need to verify.</p> + +<pre class="brush: python notranslate">class RenewBookForm(forms.Form): + """ + Form for a librarian to renew books. + """ + renewal_date = forms.DateField(help_text="Enter a date between now and 4 weeks (default 3).") + + def clean_renewal_date(self): + data = self.cleaned_data['renewal_date'] + + #Check date is not in past. + if data < datetime.date.today(): + raise ValidationError(_('Invalid date - renewal in past')) + #Check date is in range librarian allowed to change (+4 weeks) + if data > datetime.date.today() + datetime.timedelta(weeks=4): + raise ValidationError(_('Invalid date - renewal more than 4 weeks ahead')) + + # Remember to always return the cleaned data. + return data</pre> + +<p>Open our <strong>/catalog/tests/test_forms.py</strong> file and replace any existing code with the following test code for the <code>RenewBookForm</code> form. We start by importing our form and some Python and Django libraries to help test test time-related functionality. We then declare our form test class in the same way as we did for models, using a descriptive name for our <code>TestCase</code>-derived test class.</p> + +<pre class="brush: python notranslate">from django.test import TestCase + +# Create your tests here. + +import datetime +from django.utils import timezone +from catalog.forms import RenewBookForm + +class RenewBookFormTest(TestCase): + + def test_renew_form_date_field_label(self): + form = RenewBookForm() + self.assertTrue(form.fields['renewal_date'].label == None or form.fields['renewal_date'].label == 'renewal date') + + def test_renew_form_date_field_help_text(self): + form = RenewBookForm() + self.assertEqual(form.fields['renewal_date'].help_text,'Enter a date between now and 4 weeks (default 3).') + + def test_renew_form_date_in_past(self): + date = datetime.date.today() - datetime.timedelta(days=1) + form_data = {'renewal_date': date} + form = RenewBookForm(data=form_data) + self.assertFalse(form.is_valid()) + + def test_renew_form_date_too_far_in_future(self): + date = datetime.date.today() + datetime.timedelta(weeks=4) + datetime.timedelta(days=1) + form_data = {'renewal_date': date} + form = RenewBookForm(data=form_data) + self.assertFalse(form.is_valid()) + + def test_renew_form_date_today(self): + date = datetime.date.today() + form_data = {'renewal_date': date} + form = RenewBookForm(data=form_data) + self.assertTrue(form.is_valid()) + + def test_renew_form_date_max(self): + date = timezone.now() + datetime.timedelta(weeks=4) + form_data = {'renewal_date': date} + form = RenewBookForm(data=form_data) + self.assertTrue(form.is_valid()) +</pre> + +<p>The first two functions test that the field's <code>label</code> and <code>help_text</code> are as expected. We have to access the field using the fields dictionary (e.g. <code>form.fields['renewal_date']</code>). Note here that we also have to test whether the label value is <code>None</code>, because even though Django will render the correct label it returns <code>None</code> if the value is not <em>explicitly</em> set.</p> + +<p>The rest of the functions test that the form is valid for renewal dates just inside the acceptable range and invalid for values outside the range. Note how we construct test date values around our current date (<code>datetime.date.today()</code>) using <code>datetime.timedelta()</code> (in this case specifying a number of days or weeks). We then just create the form, passing in our data, and test if it is valid.</p> + +<div class="note"> +<p><strong>Note:</strong> Here we don't actually use the database or test client. Consider modifying these tests to use <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#django.test.SimpleTestCase">SimpleTestCase</a>.</p> + +<p>We also need to validate that the correct errors are raised if the form is invalid, however this is usually done as part of view processing, so we'll take care of that in the next section.</p> +</div> + +<p>That's all for forms; we do have some others, but they are automatically created by our generic class-based editing views, and should be tested there! Run the tests and confirm that our code still passes!</p> + +<h3 id="Vistas">Vistas</h3> + +<p>To validate our view behaviour we use the Django test <a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/#django.test.Client">Client</a>. This class acts like a dummy web browser that we can use to simulate <code>GET</code> and <code>POST</code> requests on a URL and observe the response. We can see almost everything about the response, from low-level HTTP (result headers and status codes) through to the template we're using to render the HTML and the context data we're passing to it. We can also see the chain of redirects (if any) and check the URL and status code at each step. This allows us to verify that each view is doing what is expected.</p> + +<p>Let's start with one of our simplest views, which provides a list of all Authors. This is displayed at URL <strong>/catalog/authors/</strong> (an URL named 'authors' in the URL configuration).</p> + +<pre class="brush: python notranslate">class AuthorListView(generic.ListView): + model = Author + paginate_by = 10 +</pre> + +<p>As this is a generic list view almost everything is done for us by Django. Arguably if you trust Django then the only thing you need to test is that the view is accessible at the correct URL and can be accessed using its name. However if you're using a test-driven development process you'll start by writing tests that confirm that the view displays all Authors, paginating them in lots of 10.</p> + +<p>Open the <strong>/catalog/tests/test_views.py</strong> file and replace any existing text with the following test code for <code>AuthorListView</code>. As before we import our model and some useful classes. In the <code>setUpTestData()</code> method we set up a number of <code>Author</code> objects so that we can test our pagination.</p> + +<pre class="brush: python notranslate">from django.test import TestCase + +# Create your tests here. + +from catalog.models import Author +from django.urls import reverse + +class AuthorListViewTest(TestCase): + + @classmethod + def setUpTestData(cls): + #Create 13 authors for pagination tests + number_of_authors = 13 + for author_num in range(number_of_authors): + Author.objects.create(first_name='Christian %s' % author_num, last_name = 'Surname %s' % author_num,) + + def test_view_url_exists_at_desired_location(self): + resp = self.client.get('/catalog/authors/') + self.assertEqual(resp.status_code, 200) + + def test_view_url_accessible_by_name(self): + resp = self.client.get(reverse('authors')) + self.assertEqual(resp.status_code, 200) + + def test_view_uses_correct_template(self): + resp = self.client.get(reverse('authors')) + self.assertEqual(resp.status_code, 200) + + self.assertTemplateUsed(resp, 'catalog/author_list.html') + + def test_pagination_is_ten(self): + resp = self.client.get(reverse('authors')) + self.assertEqual(resp.status_code, 200) + self.assertTrue('is_paginated' in resp.context) + self.assertTrue(resp.context['is_paginated'] == True) + self.assertTrue( len(resp.context['author_list']) == 10) + + def test_lists_all_authors(self): + #Get second page and confirm it has (exactly) remaining 3 items + resp = self.client.get(reverse('authors')+'?page=2') + self.assertEqual(resp.status_code, 200) + self.assertTrue('is_paginated' in resp.context) + self.assertTrue(resp.context['is_paginated'] == True) + self.assertTrue( len(resp.context['author_list']) == 3)</pre> + +<p>All the tests use the client (belonging to our <code>TestCase</code>'s derived class) to simulate a <code>GET</code> request and get a response (<code>resp</code>). The first version checks a specific URL (note, just the specific path without the domain) while the second generates the URL from its name in the URL configuration.</p> + +<pre class="brush: python notranslate">resp = self.client.get('/catalog/authors/') +resp = self.client.get(reverse('authors')) +</pre> + +<p>Once we have the response we query it for its status code, the template used, whether or not the response is paginated, the number of items returned, and the total number of items.</p> + +<p>The most interesting variable we demonstrate above is <code>resp.context</code>, which is the context variable passed to the template by the view. This is incredibly useful for testing, because it allows us to confirm that our template is getting all the data it needs. In other words we can check that we're using the intended template and what data the template is getting, which goes a long way to verifying that any rendering issues are solely due to template.</p> + +<h4 id="Views_that_are_restricted_to_logged_in_users">Views that are restricted to logged in users</h4> + +<p>In some cases you'll want to test a view that is restricted to just logged in users. For example our <code>LoanedBooksByUserListView</code> is very similar to our previous view but is only available to logged in users, and only displays <code>BookInstance</code> records that are borrowed by the current user, have the 'on loan' status, and are ordered "oldest first".</p> + +<pre class="brush: python notranslate">from django.contrib.auth.mixins import LoginRequiredMixin + +class LoanedBooksByUserListView(LoginRequiredMixin,generic.ListView): + """ + Generic class-based view listing books on loan to current user. + """ + model = BookInstance + template_name ='catalog/bookinstance_list_borrowed_user.html' + paginate_by = 10 + + def get_queryset(self): + return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')</pre> + +<p>Add the following test code to <strong>/catalog/tests/test_views.py</strong>. Here we first use <code>SetUp()</code> to create some user login accounts and <code>BookInstance</code> objects (along with their associated books and other records) that we'll use later in the tests. Half of the books are borrowed by each test user, but we've initially set the status of all books to "maintenance". We've used <code>SetUp()</code> rather than <code>setUpTestData()</code> because we'll be modifying some of these objects later.</p> + +<div class="note"> +<p><strong>Note:</strong> The <code>setUp()</code> code below creates a book with a specified <code>Language</code>, but <em>your</em> code may not include the <code>Language</code> model as this was created as a <em>challenge</em>. If this is the case, simply comment out the parts of the code that create or import Language objects. You should also do this in the <code>RenewBookInstancesViewTest</code> section that follows.</p> +</div> + +<pre class="brush: python notranslate">import datetime +from django.utils import timezone + +from catalog.models import BookInstance, Book, Genre, Language +from django.contrib.auth.models import User #Required to assign User as a borrower + +class LoanedBookInstancesByUserListViewTest(TestCase): + + def setUp(self): + #Create two users + test_user1 = User.objects.create_user(username='testuser1', password='12345') + test_user1.save() + test_user2 = User.objects.create_user(username='testuser2', password='12345') + test_user2.save() + + #Create a book + test_author = Author.objects.create(first_name='John', last_name='Smith') + test_genre = Genre.objects.create(name='Fantasy') + test_language = Language.objects.create(name='English') + test_book = Book.objects.create(title='Book Title', summary = 'My book summary', isbn='ABCDEFG', author=test_author, language=test_language) + # Create genre as a post-step + genre_objects_for_book = Genre.objects.all() + test_book.genre.set(genre_objects_for_book) #Direct assignment of many-to-many types not allowed. + test_book.save() + + #Create 30 BookInstance objects + number_of_book_copies = 30 + for book_copy in range(number_of_book_copies): + return_date= timezone.now() + datetime.timedelta(days=book_copy%5) + if book_copy % 2: + the_borrower=test_user1 + else: + the_borrower=test_user2 + status='m' + BookInstance.objects.create(book=test_book,imprint='Unlikely Imprint, 2016', due_back=return_date, borrower=the_borrower, status=status) + + def test_redirect_if_not_logged_in(self): + resp = self.client.get(reverse('my-borrowed')) + self.assertRedirects(resp, '/accounts/login/?next=/catalog/mybooks/') + + def test_logged_in_uses_correct_template(self): + login = self.client.login(username='testuser1', password='12345') + resp = self.client.get(reverse('my-borrowed')) + + #Check our user is logged in + self.assertEqual(str(resp.context['user']), 'testuser1') + #Check that we got a response "success" + self.assertEqual(resp.status_code, 200) + + #Check we used correct template + self.assertTemplateUsed(resp, 'catalog/bookinstance_list_borrowed_user.html') +</pre> + +<p>To verify that the view will redirect to a login page if the user is not logged in we use <code>assertRedirects</code>, as demonstrated in <code>test_redirect_if_not_logged_in()</code>. To verify that the page is displayed for a logged in user we first log in our test user, and then access the page again and check that we get a <code>status_code</code> of 200 (success). </p> + +<p>The rest of the test verify that our view only returns books that are on loan to our current borrower. Copy the (self-explanatory) code at the end of the test class above.</p> + +<pre class="brush: python notranslate"> def test_only_borrowed_books_in_list(self): + login = self.client.login(username='testuser1', password='12345') + resp = self.client.get(reverse('my-borrowed')) + + #Check our user is logged in + self.assertEqual(str(resp.context['user']), 'testuser1') + #Check that we got a response "success" + self.assertEqual(resp.status_code, 200) + + #Check that initially we don't have any books in list (none on loan) + self.assertTrue('bookinstance_list' in resp.context) + self.assertEqual( len(resp.context['bookinstance_list']),0) + + #Now change all books to be on loan + get_ten_books = BookInstance.objects.all()[:10] + + for copy in get_ten_books: + copy.status='o' + copy.save() + + #Check that now we have borrowed books in the list + resp = self.client.get(reverse('my-borrowed')) + #Check our user is logged in + self.assertEqual(str(resp.context['user']), 'testuser1') + #Check that we got a response "success" + self.assertEqual(resp.status_code, 200) + + self.assertTrue('bookinstance_list' in resp.context) + + #Confirm all books belong to testuser1 and are on loan + for bookitem in resp.context['bookinstance_list']: + self.assertEqual(resp.context['user'], bookitem.borrower) + self.assertEqual('o', bookitem.status) + + def test_pages_ordered_by_due_date(self): + + #Change all books to be on loan + for copy in BookInstance.objects.all(): + copy.status='o' + copy.save() + + login = self.client.login(username='testuser1', password='12345') + resp = self.client.get(reverse('my-borrowed')) + + #Check our user is logged in + self.assertEqual(str(resp.context['user']), 'testuser1') + #Check that we got a response "success" + self.assertEqual(resp.status_code, 200) + + #Confirm that of the items, only 10 are displayed due to pagination. + self.assertEqual( len(resp.context['bookinstance_list']),10) + + last_date=0 + for copy in resp.context['bookinstance_list']: + if last_date==0: + last_date=copy.due_back + else: + self.assertTrue(last_date <= copy.due_back)</pre> + +<p>You could also add pagination tests, should you so wish!</p> + +<h4 id="Testing_views_with_forms">Testing views with forms</h4> + +<p>Testing views with forms is a little more complicated than in the cases above, because you need to test more code paths: initial display, display after data validation has failed, and display after validation has succeeded. The good news is that we use the client for testing in almost exactly the same way as we did for display-only views.</p> + +<p>To demonstrate, let's write some tests for the view used to renew books (<code>renew_book_librarian()</code>):</p> + +<pre class="brush: python notranslate">from .forms import RenewBookForm + +@permission_required('catalog.can_mark_returned') +def renew_book_librarian(request, pk): + """ + View function for renewing a specific BookInstance by librarian + """ + book_inst=get_object_or_404(BookInstance, pk = pk) + + # If this is a POST request then process the Form data + if request.method == 'POST': + + # Create a form instance and populate it with data from the request (binding): + form = RenewBookForm(request.POST) + + # Check if the form is valid: + if form.is_valid(): + # process the data in form.cleaned_data as required (here we just write it to the model due_back field) + book_inst.due_back = form.cleaned_data['renewal_date'] + book_inst.save() + + # redirect to a new URL: + return HttpResponseRedirect(reverse('all-borrowed') ) + + # If this is a GET (or any other method) create the default form + else: + proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3) + form = RenewBookForm(initial={'renewal_date': proposed_renewal_date,}) + + return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'bookinst':book_inst})</pre> + +<p>We'll need to test that the view is only available to users who have the <code>can_mark_returned </code>permission, and that users are redirected to an HTTP 404 error page if they attempt to renew a <code>BookInstance</code> that does not exist. We should check that the initial value of the form is seeded with a date three weeks in the future, and that if validation succeeds we're redirected to the "all-borrowed books" view. As part checking the validation-fail tests we'll also check that our form is sending the appropriate error messages.</p> + +<p>Add the first part of the test class (shown below) to the bottom of <strong>/catalog/tests/test_views.py</strong>. This creates two users and two book instances, but only gives one user the permission required to access the view. The code to grant permissions during tests is shown in bold:</p> + +<pre class="brush: python notranslate">from django.contrib.auth.models import Permission # Required to grant the permission needed to set a book as returned. + +class RenewBookInstancesViewTest(TestCase): + + def setUp(self): + #Create a user + test_user1 = User.objects.create_user(username='testuser1', password='12345') + test_user1.save() + + test_user2 = User.objects.create_user(username='testuser2', password='12345') + test_user2.save() +<strong> permission = Permission.objects.get(name='Set book as returned') + test_user2.user_permissions.add(permission) + test_user2.save()</strong> + + #Create a book + test_author = Author.objects.create(first_name='John', last_name='Smith') + test_genre = Genre.objects.create(name='Fantasy') + test_language = Language.objects.create(name='English') + test_book = Book.objects.create(title='Book Title', summary = 'My book summary', isbn='ABCDEFG', author=test_author, language=test_language,) + # Create genre as a post-step + genre_objects_for_book = Genre.objects.all() + test_book.genre.set(genre_objects_for_book) # Direct assignment of many-to-many types not allowed. + test_book.save() + + #Create a BookInstance object for test_user1 + return_date= datetime.date.today() + datetime.timedelta(days=5) + self.test_bookinstance1=BookInstance.objects.create(book=test_book,imprint='Unlikely Imprint, 2016', due_back=return_date, borrower=test_user1, status='o') + + #Create a BookInstance object for test_user2 + return_date= datetime.date.today() + datetime.timedelta(days=5) + self.test_bookinstance2=BookInstance.objects.create(book=test_book,imprint='Unlikely Imprint, 2016', due_back=return_date, borrower=test_user2, status='o')</pre> + +<p>Add the following tests to the bottom of the test class. These check that only users with the correct permissions (<em>testuser2</em>) can access the view. We check all the cases: when the user is not logged in, when a user is logged in but does not have the correct permissions, when the user has permissions but is not the borrower (should succeed), and what happens when they try to access a <code>BookInstance</code> that doesn't exist. We also check that the correct template is used.</p> + +<pre class="brush: python notranslate"> def test_redirect_if_not_logged_in(self): + resp = self.client.get(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}) ) + #Manually check redirect (Can't use assertRedirect, because the redirect URL is unpredictable) + self.assertEqual( resp.status_code,302) + self.assertTrue( resp.url.startswith('/accounts/login/') ) + + def test_redirect_if_logged_in_but_not_correct_permission(self): + login = self.client.login(username='testuser1', password='12345') + resp = self.client.get(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}) ) + + #Manually check redirect (Can't use assertRedirect, because the redirect URL is unpredictable) + self.assertEqual( resp.status_code,302) + self.assertTrue( resp.url.startswith('/accounts/login/') ) + + def test_logged_in_with_permission_borrowed_book(self): + login = self.client.login(username='testuser2', password='12345') + resp = self.client.get(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance2.pk,}) ) + + #Check that it lets us login - this is our book and we have the right permissions. + self.assertEqual( resp.status_code,200) + + def test_logged_in_with_permission_another_users_borrowed_book(self): + login = self.client.login(username='testuser2', password='12345') + resp = self.client.get(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}) ) + + #Check that it lets us login. We're a librarian, so we can view any users book + self.assertEqual( resp.status_code,200) + + def test_HTTP404_for_invalid_book_if_logged_in(self): + import uuid + test_uid = uuid.uuid4() #unlikely UID to match our bookinstance! + login = self.client.login(username='testuser2', password='12345') + resp = self.client.get(reverse('renew-book-librarian', kwargs={'pk':test_uid,}) ) + self.assertEqual( resp.status_code,404) + + def test_uses_correct_template(self): + login = self.client.login(username='testuser2', password='12345') + resp = self.client.get(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}) ) + self.assertEqual( resp.status_code,200) + + #Check we used correct template + self.assertTemplateUsed(resp, 'catalog/book_renew_librarian.html') +</pre> + +<p>Add the next test method, as shown below. This checks that the initial date for the form is three weeks in the future. Note how we are able to access the value of the initial value of the form field (shown in bold).</p> + +<pre class="brush: python notranslate"> def test_form_renewal_date_initially_has_date_three_weeks_in_future(self): + login = self.client.login(username='testuser2', password='12345') + resp = self.client.get(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}) ) + self.assertEqual( resp.status_code,200) + + date_3_weeks_in_future = datetime.date.today() + datetime.timedelta(weeks=3) + self.assertEqual(<strong>resp.context['form'].initial['renewal_date']</strong>, date_3_weeks_in_future ) +</pre> + +<p>The next test (add this to the class too) checks that the view redirects to a list of all borrowed books if renewal succeeds. What differs here is that for the first time we show how you can <code>POST</code> data using the client. The post <em>data</em> is the second argument to the post function, and is specified as a dictionary of key/values.</p> + +<pre class="brush: python notranslate"> def test_redirects_to_all_borrowed_book_list_on_success(self): + login = self.client.login(username='testuser2', password='12345') + valid_date_in_future = datetime.date.today() + datetime.timedelta(weeks=2) + resp = <strong>self.client.<em>post</em>(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}), {'renewal_date':valid_date_in_future} )</strong> + self.assertRedirects(resp, reverse('all-borrowed') ) +</pre> + +<div class="warning"> +<p>The <em>all-borrowed</em> view was added as a <em>challenge</em>, and your code may instead redirect to the home page '/'. If so, modify the last two lines of the test code to be like the code below. The <code>follow=True</code> in the request ensures that the request returns the final destination URL (hence checking <code>/catalog/</code> rather than <code>/</code>).</p> + +<pre class="brush: python notranslate"> resp = self.client.post(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}), {'renewal_date':valid_date_in_future},<strong>follow=True</strong> ) + <strong>self.assertRedirects(resp, '/catalog/')</strong></pre> +</div> + +<p>Copy the last two functions into the class, as seen below. These again test <code>POST</code> requests, but in this case with invalid renewal dates. We use <code>assertFormError() </code>to verify that the error messages are as expected.</p> + +<pre class="brush: python notranslate"> def test_form_invalid_renewal_date_past(self): + login = self.client.login(username='testuser2', password='12345') + date_in_past = datetime.date.today() - datetime.timedelta(weeks=1) + resp = self.client.post(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}), {'renewal_date':date_in_past} ) + self.assertEqual( resp.status_code,200) + <strong>self.assertFormError(resp, 'form', 'renewal_date', 'Invalid date - renewal in past')</strong> + + def test_form_invalid_renewal_date_future(self): + login = self.client.login(username='testuser2', password='12345') + invalid_date_in_future = datetime.date.today() + datetime.timedelta(weeks=5) + resp = self.client.post(reverse('renew-book-librarian', kwargs={'pk':self.test_bookinstance1.pk,}), {'renewal_date':invalid_date_in_future} ) + self.assertEqual( resp.status_code,200) + <strong>self.assertFormError(resp, 'form', 'renewal_date', 'Invalid date - renewal more than 4 weeks ahead')</strong> +</pre> + +<p>The same sorts of techniques can be used to test the other view.</p> + +<h3 id="Templates">Templates</h3> + +<p>Django provides test APIs to check that the correct template is being called by your views, and to allow you to verify that the correct information is being sent. There is however no specific API support for testing in Django that your HTML output is rendered as expected.</p> + +<h2 id="Other_recommended_test_tools">Other recommended test tools</h2> + +<p>Django's test framework can help you write effective unit and integration tests — we've only scratched the surface of what the underlying <strong>unittest</strong> framework can do, let alone Django's additions (for example, check out how you can use <a href="https://docs.python.org/3.5/library/unittest.mock-examples.html">unittest.mock</a> to patch third party libraries so you can more thoroughly test your own code).</p> + +<p>While there are numerous other test tools that you can use, we'll just highlight two:</p> + +<ul> + <li><a href="http://coverage.readthedocs.io/en/latest/">Coverage</a>: This Python tool reports on how much of your code is actually executed by your tests. It is particularly useful when you're getting started, and you are trying to work out exactly what you should test.</li> + <li><a href="/en-US/docs/Learn/Tools_and_testing/Cross_browser_testing/Your_own_automation_environment">Selenium</a> is a framework to automate testing in a real browser. It allows you to simulate a real user interacting with the site, and provides a great framework for system testing your site (the next step up from integration testing.</li> +</ul> + +<h2 id="Reto_para_mi_mismo">Reto para mi mismo</h2> + +<p>There are a lot more models and views we can test. As a simple task, try to create a test case for the <code>AuthorCreate</code> view.</p> + +<pre class="brush: python notranslate">class AuthorCreate(PermissionRequiredMixin, CreateView): + model = Author + fields = '__all__' + initial={'date_of_death':'12/10/2016',} + permission_required = 'catalog.can_mark_returned'</pre> + +<p>Remember that you need to check anything that you specify or that is part of the design. This will include who has access, the initial date, the template used, and where the view redirects on success.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Writing test code is neither fun nor glamorous, and is consequently often left to last (or not at all) when creating a website. It is however an essential part of making sure that your code is safe to release after making changes, and cost-effective to maintain.</p> + +<p>In this tutorial we've shown you how to write and run tests for your models, forms, and views. Most importantly we've provided a brief summary of what you should test, which is often the hardest thing to work out when your getting started. There is a lot more to know, but even with what you've learned already you should be able to create effective unit tests for your websites.</p> + +<p>The next and final tutorial shows how you can deploy your wonderful (and fully tested!) Django website.</p> + +<h2 id="Mirar_tambien">Mirar tambien</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/testing/overview/">Writing and running tests</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/intro/tutorial05/">Writing your first Django app, part 5 > Introducing automated testing</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/testing/tools/">Testing tools reference</a> (Django docs)</li> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/testing/advanced/">Advanced testing topics</a> (Django docs)</li> + <li><a href="http://toastdriven.com/blog/2011/apr/10/guide-to-testing-in-django/">A Guide to Testing in Django</a> (Toast Driven Blog, 2011)</li> + <li><a href="http://test-driven-django-development.readthedocs.io/en/latest/index.html">Workshop: Test-Driven Web Development with Django</a> (San Diego Python, 2014)</li> + <li><a href="https://realpython.com/blog/python/testing-in-django-part-1-best-practices-and-examples/">Testing in Django (Part 1) - Best Practices and Examples</a> (RealPython, 2013)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Forms", "Learn/Server-side/Django/Deployment", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/tutorial_local_library_website/index.html b/files/es/learn/server-side/django/tutorial_local_library_website/index.html new file mode 100644 index 0000000000..a7450fafd0 --- /dev/null +++ b/files/es/learn/server-side/django/tutorial_local_library_website/index.html @@ -0,0 +1,103 @@ +--- +title: 'Tutorial Django: El Sitio Web de La Biblioteca Local' +slug: Learn/Server-side/Django/Tutorial_local_library_website +tags: + - Aprendizaje + - Artículo + - Codificación de scripts + - Guía + - Principiante + - Tutorial + - django + - lado servidor +translation_of: Learn/Server-side/Django/Tutorial_local_library_website +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django")}}</div> + +<p class="summary">El primer artículo de nuestra serie de tutoriales prácticos explica qué puedes aprender, y proporciona una visión general del sitio web de ejemplo de "biblioteca local" en el que estaremos trabajando y evolucionando en artículos subsiguientes.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td> + <p>Leer la <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/Introducci%C3%B3n">Introducción a Django</a>. Durante los siguientes artículos necesitarás tener <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django/development_environment">levantado un entorno de desarrollo Django</a>. </p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Presentar el ejemplo de aplicación usado en este tutorial, y permitir que los lectores comprendan los temas que se tratarán aquí. </p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Visión_general">Visión general</h2> + +<p>Bienvenidos al tutorial de MDN sobre la "Biblioteca Local" Django en el que desarrollaremos un sitio web que podría usarse para gestionar el catálogo de una biblioteca local. </p> + +<p>En esta serie de tutoriales:</p> + +<ul> + <li>Usarás las herramientas de Django para crear el esqueleto de un sitio web y una aplicación.</li> + <li>Arrancarás y pararás el servidor de desarrollo.</li> + <li>Crearás modelos para representar los datos de tu aplicación.</li> + <li>Usarás el sitio de administración de Django para rellenar los datos de tu sitio.</li> + <li>Crearás views para recuperar datos específicos en respuesta a diferentes peticiones, y plantillas para renderizar los datos como HTML que serán presentados en pantalla por el explorador web.</li> + <li>Crearás mapeadores para asociar los diferentes patrones URL con views específicas.</li> + <li>Añadirás autorizaciones de usuario y sesiones para controlar el comportamiento del sitio y acceso al mismo.</li> + <li>Trabajarás con formularios.</li> + <li>Escribirás código para comprobar tu aplicación.</li> + <li>Usarás la seguridad de Django con eficacia.</li> + <li>Desplegarás tu aplicación a producción.</li> +</ul> + +<p>Has aprendido algo de estos tópicos ya, y tocado otros brevemente. Al final de esta serie de tutoriales sabrás lo suficiente para desarrollar aplicaciones simples Django por tí mismo.</p> + +<h2 id="El_sitio_web_de_la_Biblioteca_Local">El sitio web de la Biblioteca Local</h2> + +<p><em>BibliotecaLocal</em> es el nombre del sitio web que crearemos para evolucionar a lo largo del curso de esta serie de tutoriales. Como habrás supuesto, el propósito de este sitio web es proporcionar un catálogo online para una pequeña biblioteca local, en la que los usuarios pueden explorar los libros disponibles y gestionar sus cuentas.</p> + +<p>Este ejemplo ha sido seleccionado cuidadosamente porque puede escalar para mostrar tanto mucho detalle como poco según necesitemos, y puede usarse para mostrar casi cualquier característica de Django. Más importante aún, nos permite proporcionar un camino guiado a través de las funcionalidades más importantes del framework web Django:</p> + +<ul> + <li>En los primeros artículos del tutorial definiremos una blibioteca simple para <em>explorar sólo</em> que podrán usar sus miembros para encontrar qué libros están disponibles. Esto nos permitirá explorar las operaciones que son comunes a casi todos los sitios web: lectura y presentación de los contenidos de una base de datos.</li> + <li>A medida que progresemos, el ejemplo de la biblioteca demostrará características más avanzadas de Django. Por ejemplo podremos extender la biblioteca para permitir a los usuarios reservar libros, y usar ésto para demostrar cómo se usan los formularios, y soportar la autenticación de usuario.</li> +</ul> + +<p>Incluso aunque es un ejemplo muy extenso, se llama <em>Biblioteca<strong>Local</strong></em> por una razón — esperamos mostrar el mínimo de información que te ayude a ponerte en marcha con Django rápidamente. Como resultado almacenaremos información sobre libros, copias de libros, autores y otras información clave. Sin embargo, no almacenaremos información sobre otros elementos que una biblioteca podría almacenar, ni proporcionaremos la infraestructura necesaría para mantener multiples sitios de bibliotecas u otras características de una "gran biblioteca".</p> + +<h2 id="Estoy_atascado_¿Donde_puedo_encontrar_el_código_fuente">Estoy atascado, ¿Donde puedo encontrar el código fuente?</h2> + +<p>A medida que avances a través del tutorial te proporcionaremos los fragmentos de código apropiados para que copies y pegues en cada punto, y habrá otro código que esperamos que puedas entender tú mismo (con algo de ayuda).</p> + +<p>Si te quedas atascado, puedes encontrar la versión completamente desarrollada <a href="https://github.com/mdn/django-locallibrary-tutorial">en el sitio web de Github aquí</a>.</p> + +<h2 id="Resumen">Resumen</h2> + +<p>Ahora que sabes un poco más sobre el sitio de la <em>BibliotecaLocal</em> y lo que vas a aprender, es hora de empezar a crear el <a href="/es/docs/Learn/Server-side/Django/skeleton_website">esqueleto(estructura)</a> de nuestro proyecto.</p> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/development_environment", "Learn/Server-side/Django/skeleton_website", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/django/web_application_security/index.html b/files/es/learn/server-side/django/web_application_security/index.html new file mode 100644 index 0000000000..e00a1771bb --- /dev/null +++ b/files/es/learn/server-side/django/web_application_security/index.html @@ -0,0 +1,176 @@ +--- +title: Seguridad de las aplicaciones web Django +slug: Learn/Server-side/Django/web_application_security +translation_of: Learn/Server-side/Django/web_application_security +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}</div> + +<p class="summary">Proteger los datos de los usuarios es una parte esencial de cualquier diseño de un sitio web. Previamente ya explicamos algunas de las amenazas de seguridad más comunes en el artículo <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Seguridad Web</a> — este artículo proporciona una demostración práctica de cómo las protecciones integradas de Django gestionan estas amenazas.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerrequisitos:</th> + <td>Lee la documentación de la Programación del Lado del servidor "<a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/First_steps/Website_security">Seguridad de la aplicación web de Django</a>". Completa todos los temas del Tutorial de Django (incluyendo este) o por lo menos el <a href="/en-US/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajar con formularios web</a>.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender las cosas principales que debes hacer (y las que no debes) para proteger su aplicación web de Django.</td> + </tr> + </tbody> +</table> + +<h2 id="Overview">Overview</h2> + +<p>The <a href="https://developer.mozilla.org/en-US/docs/Web/Security">Website security</a> topic provides an overview of what website security means for server-side design, and some of the more common threats that you may need to protect against. One of the key messages in that article is that almost all attacks are successful when the web application trusts data from the browser.</p> + +<div class="warning"> +<p><strong>Important:</strong> The single most important lesson you can learn about website security is to <strong>never trust data from the browser</strong>. This includes <code>GET</code> request data in URL parameters, <code>POST</code> data, HTTP headers and cookies, user-uploaded files, etc. Always check and sanitize all incoming data. Always assume the worst.</p> +</div> + +<p>The good news for Django users is that many of the more common threats are handled by the framework! The <a href="https://docs.djangoproject.com/en/1.10/topics/security/">Security in Django</a> (Django docs) article explains Django's security features and how to secure a Django-powered website.</p> + +<h2 id="Common_threatsprotections">Common threats/protections</h2> + +<p>Rather than duplicate the Django documentation here, in this article we'll demonstrate just a few of the security features in the context of our Django <a href="/en-US/docs/Learn/Server-side/Django/Tutorial_local_library_website">LocalLibrary</a> tutorial.</p> + +<h3 id="Cross_site_scripting_(XSS)">Cross site scripting (XSS)</h3> + +<p>XSS is a term used to describe a class of attacks that allow an attacker to inject client-side scripts <em>through</em> the website into the browsers of other users. This is usually achieved by storing malicious scripts in the database where they can be retrieved and displayed to other users, or by getting users to click a link that will cause the attacker’s JavaScript to be executed by the user’s browser.</p> + +<p>Django's template system protects you against the majority of XSS attacks by <a href="https://docs.djangoproject.com/en/1.10/ref/templates/language/#automatic-html-escaping">escaping specific characters</a> that are "dangerous" in HTML. We can demonstrate this by attempting to inject some JavaScript into our LocalLibrary website using the Create-author form we set up in <a href="/en-US/docs/Learn/Server-side/Django/Forms">Django Tutorial Part 9: Working with forms</a>.</p> + +<ol> + <li>Start the website using the development server (<code>python3 manage.py runserver</code>).</li> + <li>Open the site in your local browser and login to your superuser account.</li> + <li>Navigate to the author-creation page (which should be at URL: <code><a href="http://127.0.0.1:8000/catalog/author/create/">http://127.0.0.1:8000/catalog/author/create/</a></code>).</li> + <li>Enter names and date details for a new user, and then append the following text to the Last Name field:<br> + <code><script>alert('Test alert');</script></code>.<br> + <img alt="Author Form XSS test" src="https://mdn.mozillademos.org/files/14305/author_create_form_alert_xss.png" style="border-style: solid; border-width: 1px; height: 245px; width: 594px;"> + <div class="note"> + <p><strong>Note:</strong> This is a harmless script that, if executed, will display an alert box in your browser. If the alert is displayed when you submit the record then the site is vulnerable to XSS threats.</p> + </div> + </li> + <li>Press <strong>Submit</strong> to save the record.</li> + <li>When you save the author it will be displayed as shown below. Because of the XSS protections the <code>alert()</code> should not be run. Instead the script is displayed as plain text.<img alt="Author detail view XSS test" src="https://mdn.mozillademos.org/files/14307/author_detail_alert_xss.png" style="border-style: solid; border-width: 1px; height: 248px; width: 986px;"></li> +</ol> + +<p>If you view the page HTML source code, you can see that the dangerous characters for the script tags have been turned into their harmless escape code equivalents (e.g. <code>></code> is now <code>&gt;</code>)</p> + +<pre class="brush: html"><h1>Author: Boon&lt;script&gt;alert(&#39;Test alert&#39;);&lt;/script&gt;, David (Boonie) </h1> +</pre> + +<p>Using Django templates protects you against the majority of XSS attacks. However it is possible to turn off this protection, and the protection isn't automatically applied to all tags that wouldn't normally be populated by user input (for example, the <code>help_text</code> in a form field is usually not user-supplied, so Django doesn't escape those values).</p> + +<p>It is also possible for XSS attacks to originate from other untrusted source of data, such as cookies, Web services or uploaded files (whenever the data is not sufficiently sanitized before including in a page). If you're displaying data from these sources, then you may need to add your own sanitisation code.</p> + +<h3 id="Cross_site_request_forgery_(CSRF)_protection">Cross site request forgery (CSRF) protection</h3> + +<p>CSRF attacks allow a malicious user to execute actions using the credentials of another user without that user’s knowledge or consent. For example consider the case where we have a hacker who wants to create additional authors for our LocalLibrary.</p> + +<div class="note"> +<p><strong>Note:</strong> Obviously our hacker isn't in this for the money! A more ambitious hacker could use the same approach on other sites to perform much more harmful tasks (e.g. transfer money to their own accounts, etc.)</p> +</div> + +<p>In order to do this, they might create an HTML file like the one below, which contains an author-creation form (like the one we used in the previous section) that is submitted as soon as the file is loaded. They would then send the file to all the Librarians and suggest that they open the file (it contains some harmless information, honest!). If the file is opened by any logged in librarian, then the form would be submitted with their credentials and a new author would be created.</p> + +<pre class="brush: html"><html> +<body onload='document.EvilForm.submit()'> + +<form action="http://127.0.0.1:8000/catalog/author/create/" method="post" name='EvilForm'> + <table> + <tr><th><label for="id_first_name">First name:</label></th><td><input id="id_first_name" maxlength="100" name="first_name" type="text" value="Mad" required /></td></tr> + <tr><th><label for="id_last_name">Last name:</label></th><td><input id="id_last_name" maxlength="100" name="last_name" type="text" value="Man" required /></td></tr> + <tr><th><label for="id_date_of_birth">Date of birth:</label></th><td><input id="id_date_of_birth" name="date_of_birth" type="text" /></td></tr> + <tr><th><label for="id_date_of_death">Died:</label></th><td><input id="id_date_of_death" name="date_of_death" type="text" value="12/10/2016" /></td></tr> + </table> + <input type="submit" value="Submit" /> +</form> + +</body> +</html> +</pre> + +<p>Run the development web server, and log in with your superuser account. Copy the text above into a file and then open it in the browser. You should get a CSRF error, because Django has protection against this kind of thing!</p> + +<p>The way the protection is enabled is that you include the <code>{% csrf_token %}</code> template tag in your form definition. This token is then rendered in your HTML as shown below, with a value that is specific to the user on the current browser.</p> + +<pre class="brush: html"><input type='hidden' name='csrfmiddlewaretoken' value='0QRWHnYVg776y2l66mcvZqp8alrv4lb8S8lZ4ZJUWGZFA5VHrVfL2mpH29YZ39PW' /> +</pre> + +<p>Django generates a user/browser specific key and will reject forms that do not contain the field, or that contain an incorrect field value for the user/browser.</p> + +<p>To use this type of attack the hacker now has to discover and include the CSRF key for the specific target user. They also can't use the "scattergun" approach of sending a malicious file to all librarians and hoping that one of them will open it, since the CSRF key is browser specific.</p> + +<p>Django's CSRF protection is turned on by default. You should always use the <code>{% csrf_token %}</code> template tag in your forms and use <code>POST</code> for requests that might change or add data to the database.</p> + +<h3 id="Other_protections">Other protections</h3> + +<p>Django also provides other forms of protection (most of which would be hard or not particularly useful to demonstrate):</p> + +<dl> + <dt>SQL injection protection</dt> + <dd>SQL injection vulnerabilities enable malicious users to execute arbitrary SQL code on a database, allowing data to be accessed, modified, or deleted irrespective of the user's permissions. In almost every case you'll be accessing the database using Django’s querysets/models, so the resulting SQL will be properly escaped by the underlying database driver. If you do need to write raw queries or custom SQL then you'll need to explicitly think about preventing SQL injection.</dd> + <dt>Clickjacking protection</dt> + <dd>In this attack a malicious user hijacks clicks meant for a visible top level site and routes them to a hidden page beneath. This technique might be used, for example, to display a legitimate bank site but capture the login credentials in an invisible <a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/iframe" title="The HTML Inline Frame Element (<iframe>) represents a nested browsing context, effectively embedding another HTML page into the current page. In HTML 4.01, a document may contain a head and a body or a head and a frameset, but not both a body and a frameset. However, an <iframe> can be used within a normal document body. Each browsing context has its own session history and active document. The browsing context that contains the embedded content is called the parent browsing context. The top-level browsing context (which has no parent) is typically the browser window."><code><iframe></code></a> controlled by the attacker. Django contains <a href="https://docs.djangoproject.com/en/1.10/ref/clickjacking/#clickjacking-prevention">clickjacking protection</a> in the form of the <a href="https://docs.djangoproject.com/en/1.10/ref/middleware/#django.middleware.clickjacking.XFrameOptionsMiddleware" title="django.middleware.clickjacking.XFrameOptionsMiddleware"><code>X-Frame-Options middleware</code></a> which, in a supporting browser, can prevent a site from being rendered inside a frame.</dd> + <dt>Enforcing SSL/HTTPS</dt> + <dd>SSL/HTTPS can be enabled on the web server in order to encrypt all traffic between the site and browser, including authentication credentials that would otherwise be sent in plain text (enabling HTTPS is highly recommended). If HTTPS is enabled then Django provides a number of other protections you can use:</dd> +</dl> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-SECURE_PROXY_SSL_HEADER"><code>SECURE_PROXY_SSL_HEADER</code></a> can be used to check whether content is secure, even if it is incoming from a non-HTTP proxy.</li> + <li><a href="https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-SECURE_SSL_REDIRECT"><code>SECURE_SSL_REDIRECT</code></a> is used to redirect all HTTP requests to HTTPS.</li> + <li>Use <a href="https://docs.djangoproject.com/en/1.10/ref/middleware/#http-strict-transport-security">HTTP Strict Transport Security</a> (HSTS). This is an HTTP header that informs a browser that all future connections to a particular site should always use HTTPS. Combined with redirecting HTTP requests to HTTPS, this setting ensures that HTTPS is always used after a successful connection has occurred. HSTS may either be configured with <a href="https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-SECURE_HSTS_SECONDS"><code>SECURE_HSTS_SECONDS</code></a> and <a href="https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-SECURE_HSTS_INCLUDE_SUBDOMAINS"><code>SECURE_HSTS_INCLUDE_SUBDOMAINS</code></a> or on the Web server.</li> + <li>Use ‘secure’ cookies by setting <a href="https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-SESSION_COOKIE_SECURE"><code>SESSION_COOKIE_SECURE</code></a> and <a href="https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-CSRF_COOKIE_SECURE"><code>CSRF_COOKIE_SECURE</code></a> to <code>True</code>. This will ensure that cookies are only ever sent over HTTPS.</li> +</ul> + +<dl> + <dt>Host header validation</dt> + <dd>Use <a href="https://docs.djangoproject.com/en/1.10/ref/settings/#std:setting-ALLOWED_HOSTS"><code>ALLOWED_HOSTS</code></a> to only accept requests from trusted hosts.</dd> +</dl> + +<p>There are many other protections, and caveats to the usage of the above mechanisms. While we hope that this has given you an overview of what Django offers, you should still read the Django security documentation.</p> + +<ul> +</ul> + +<h2 id="Summary">Summary</h2> + +<p>Django has effective protections against a number of common threats, including XSS and CSRF attacks. In this article we've demonstrated how those particular threats are handled by Django in our <em>LocalLibrary</em> website. We've also provided a brief overview of some of the other protections.</p> + +<p>This has been a very brief foray into web security. We strongly recommend that you read <a href="https://docs.djangoproject.com/en/1.10/topics/security/">Security in Django</a> to gain a deeper understanding.</p> + +<p>The next and final step in this module about Django is to complete the <a href="/en-US/docs/Learn/Server-side/Django/django_assessment_blog">assessment task</a>.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://docs.djangoproject.com/en/1.10/topics/security/">Security in Django</a> (Django docs)</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/Security">Server side website security</a> (MDN)</li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/Security">Web security</a> (MDN)</li> + <li><a href="/en-US/docs/Web/Security/Securing_your_site">Securing your site</a> (MDN)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Django/Deployment", "Learn/Server-side/Django/django_assessment_blog", "Learn/Server-side/Django")}}</p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/es/docs/Learn/Server-side/Django/Introducción">Introducción a Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/development_environment">Configurando un entorno de desarrollo Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Tutorial_local_library_website">Tutorial de Django: El sito web de la Biblioteca Local</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/skeleton_website">Tutorial de Django Parte 2: Creando el esqueleto de un sitio web</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Models">Tutorial de Django Parte 3: Usando modelos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Admin_site">Tutorial de Django Parte 4: Sitio de administración de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Home_page">Tutorial de Django Parte 5: Creando nuestra página de inicio</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Generic_views">Tutorial de Django Parte 6: Listas genéricas y vistas de detalle</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Sessions">Tutorial de Django Parte 7: Framework de sesiones</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Authentication">Tutorial de Django Parte 8: Autenticación de usuarios y permisos</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Forms">Tutorial de Django Parte 9: Trabajando con formularios</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Testing">Tutorial de Django Parte 10: Probando una aplicación web de Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/Deployment">Tutorial de Django Parte 11: Poniendo Django en producción</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/web_application_security">Seguridad en aplicaciones web Django</a></li> + <li><a href="/es/docs/Learn/Server-side/Django/django_assessment_blog">DIY Django mini blog</a></li> +</ul> diff --git a/files/es/learn/server-side/express_nodejs/development_environment/index.html b/files/es/learn/server-side/express_nodejs/development_environment/index.html new file mode 100644 index 0000000000..40a96d56e4 --- /dev/null +++ b/files/es/learn/server-side/express_nodejs/development_environment/index.html @@ -0,0 +1,407 @@ +--- +title: Setting up a Node development environment +slug: Learn/Server-side/Express_Nodejs/development_environment +tags: + - Aprender + - Entorno de Desarrollo + - Express + - JavaScript + - Node + - nodejs + - npm +translation_of: Learn/Server-side/Express_Nodejs/development_environment +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary">Ahora que sabes para que sirve Express, nosotros te vamos a mostrar como preparar y testear un entorno de desarrollo Node/Express en: Windows, Linux (Ubuntu), y macOS. Este artículo te va a dar todo lo que se necesita para poder empezar a desarrollar apps en Express, sin importar el sistema operativo que se use.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Saber como abrir una terminal / línea de comando. Saber como instalar paquetes de software en su sistema operativo de su computadora de desarrollo.</td> + </tr> + <tr> + <th scope="row">Objectivo:</th> + <td>Configurar un ambiente de desarrollo para Express (X.XX) en su computadora.</td> + </tr> + </tbody> +</table> + +<h2 id="Express_ambiente_de_desarrollo_reseña">Express ambiente de desarrollo reseña</h2> + +<p><em>Node</em> y <em>Express</em> hacen muy fácil configurar su computadora con el propósito de iniciar el desarrollo de aplicaciones web. Esta seccion provee una reseña de qué herramientas son necesarias, explica algunos de los métodos más simples para instalar Node (y Express) en Ubuntu, macOS y Windows, y muestra como puede probar su instalación.</p> + +<h3 id="Qué_es_el_ambiente_de_desarrollo_Express">Qué es el ambiente de desarrollo Express?</h3> + +<p>El ambiente de desarrollo <em>Express</em> incluye una instalación de <em>Nodejs</em>, el <em>NPM administrador de paquetes</em>, y (opcionalmente) el Generador de Aplicaciones de <em>Express </em>en su computadora local.</p> + +<p><em>Node</em> y el administrador de paquetes <em>NPM</em> se instalan juntos desde paquetes binarios, instaladores, administradores de paquetes del sistema operativo o desde los fuentes (como se muestra en las siguientes secciónes). <em>Express</em> es entonces instalado por NPM como una dependencia individual de sus aplicaciones web <em>Express</em> (conjuntamente con otras librerías como motores de plantillas, controladores de bases de datos, middleware de autenticación, middleware para servir archivos estáticos, etc.)</p> + +<p><em>NPM</em> puede ser usado también para (globalmente) instalar el Generador de Aplicaciones de <em>Express</em>, una herramienta manual para crear la estructura de las web apps de <em>Express</em> que siguen el <a href="/en-US/Apps/Fundamentals/Modern_web_app_architecture/MVC_architecture"> patrón MVC </a>. El generador de aplicaciones es opcional porque no necesita utilizar esta herramienta para crear apps que usan Express, o construir apps Express que tienen el mismo diseño arquitectónico o dependencias. No obstante estaremos usandolo, porque hace mucho más fácil, y promueve una estrucura modular de aplicación.</p> + +<div class="note"> +<p><strong>Nota:</strong> A diferencia de otros frameworks web , el ambiente de desarrollo no incluye un servidor web independiente. Una aplicación web <em>Node</em>/<em>Express</em> crea y ejecuta su propio servidor web!</p> +</div> + +<p>Hay otras herramientas periféricas que son parte de un ambiente de desarrollo típico, incluyendo <a href="/en-US/docs/Learn/Common_questions/Available_text_editors">editores de texto</a> o IDEs para edición de código, y herramientas de administración de control de fuentes como <a href="https://git-scm.com/">Git</a> para administrar con seguridad diferentes versiones de su codigo. Asumimos que usted ya tiene instaladas esta clase de herramientas (en particular un editor de texto).</p> + +<h3 id="Qué_sistemas_operativos_son_soportados">Qué sistemas operativos son soportados?</h3> + +<p><em>Node</em> puede ser ejecutado en Windows, macOS, varias "versiones" de Linux, Docker, etc. (hay una lista completa de paginas de <a href="https://nodejs.org/en/download/">Downloads</a> de nodejs). Casi cualquier computadora personal podría tener el desempeño necesario para ejecutar Node durante el desarrollo. <em>Express</em> es ejecutado en un ambiente <em>Node</em>, y por lo tanto puede ejecutarse en cualquier plataforma que ejecute <em>Node</em>.</p> + +<p>En este articulo proveemos instruciones para configurarlo para Windows, macOS, and Ubuntu Linux.</p> + +<h3 id="¿Qué_versión_de_NodeExpress_puedo_usar">¿Qué versión de Node/Express puedo usar?</h3> + +<p>Hay varias <a href="https://nodejs.org/en/blog/release/">versiones de Node</a> — recientes que contienen reparacion de bugs, soporte para versiones mas recientes de ECMAScript (JavaScript) estandares, y mejoras a las APIs de Node . </p> + +<p>Generalmente se debe usar la versión más reciente <em>SLP (soporte de largo-plazo),</em> una versión como esta es más estable que la versión "actual", mientras que sigue teniendo características relativamente recientes (y continua siendo activamente actualizado). Debería utilizar la versión <em>Actual</em> si necesita una característica que no esta presente en la versión SLP.</p> + +<p>Para <em>Express</em> siempre se debe utilizar la versión más reciente.</p> + +<h3 id="¿Qué_pasa_con_bases_de_datos_y_otras_dependencias">¿Qué pasa con bases de datos y otras dependencias?</h3> + +<p>Otras dependencias, tales como los controladores de bases de datos, motores de plantillas, motores de autenticación, etc. son parte de la aplicación, y son importadas dentro del ambiente de la aplicación utilizando el administrador de paquetes NPM. Estos los discutiremos en artículos posteriores app-specific.</p> + +<h2 id="Instalar_Node">Instalar Node</h2> + +<p>Para poder utilizar <em>Express</em> primero tiene que instalar <em>Nodejs</em> y el <a href="https://docs.npmjs.com/">Administrador de Paquetes de Node (NPM)</a> en su sistema operativo. Las siguientes secciones explican la forma más fácil de instalar la versión Soporte de Largo-Plazo (SLP) de Nodejs en Ubuntu Linux 16.04, macOS, y Windows 10.</p> + +<div class="note"> +<p><strong>Tip:</strong> Las secciones de abajo muestran la forma más facil de instalar <em>Node</em> y <em>NPM</em> en nuestras plataformas de sistemas operativo a elegir. Si esta utilizando otro SO o solo quiere ver alguna de otros enfoques para las plataformas actuales entonce vea <a href="https://nodejs.org/en/download/package-manager/">Instalando Node.js via administrador de paquetes</a> (nodejs.org).</p> +</div> + +<h3 id="macOS_y_Windows">macOS y Windows</h3> + +<p>Instalar <em>Node</em> y <em>NPM</em> en Windows y macOS es sencillo, porque simplemente debe utilizar el instalador provisto:</p> + +<ol> + <li>Descargue el instalador requerido: + <ol> + <li>Vaya a <a href="https://nodejs.org/en/">https://nodejs.org/es/</a></li> + <li>Seleccione el boton para descargar la versión LTS que es "Recomendada la mayoría de los usuarios".</li> + </ol> + </li> + <li>Instale Node al dar doble-click en el archivo de descarga y en seguida la instalación inicia.</li> +</ol> + +<h3 id="Ubuntu_18.04">Ubuntu 18.04</h3> + +<p>La forma más fácil de instalar la versión LTS de Node 10.x es la usar el <a href="https://nodejs.org/en/download/package-manager/#debian-and-ubuntu-based-linux-distributions">administrador de paquetes</a> para obtenerlo del repositorio de distribuciones <em>binarias </em>de Ubuntu. Esto puede ser hecho muy simple al ejecutar los siguientes dos comandos en su terminal:</p> + +<pre class="brush: bash"><code>curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - +sudo apt-get install -y nodejs</code> +</pre> + +<div class="warning"> +<p><strong>Advertencia:</strong> No instale directamente desde los repositorios normales de Ubuntu porque pueden contener versions muy antiguas de Node.</p> +</div> + +<ol> +</ol> + +<h3 id="Probar_su_instalación_de_Nodejs_y_NPM">Probar su instalación de Nodejs y NPM</h3> + +<p>La forma más fácil de probar que Node está instalado es ejecutar el comando "version" en su prompt de terminal/command y checar que una cadena de versión es devuelta:</p> + +<pre class="brush: bash">>node -v +v10.16.0</pre> + +<p>The administrador de paquetes <em>NPM</em> de <em>Nodejs</em> también debería haber sido instalado y puede ser probado de la misma forma:</p> + +<pre class="brush: bash">>npm -v +6.9.0</pre> + +<p>Como una prueba un poco más emocionante creemos un muy básico "básico servidor node" que simplemente imprima "Hola Mundo" en el browser cuando visite la URL correcta en él:</p> + +<ol> + <li>Copie el siguiente texto en un archivo llamado <strong>holanode.js</strong>. Este utiliza características básicas de Node (nada desde Express) y algo de sintáxis ES6: + + <pre class="brush: js">//Load HTTP module +const http = require("http"); +<code>const hostname = '127.0.0.1'; +const port = 3000; + +//Create HTTP server and listen on port 3000 for requests +const server = http.createServer((req, res) => { + + //Set the response HTTP header with HTTP status and Content type + res.statusCode = 200; + res.setHeader('Content-Type', 'text/plain'); + res.end('Hello World\n'); +}); + +//listen for request on port 3000, and as a callback function have the port listened on logged +server.listen(port, hostname, () => { + console.log(`Server running at http://${hostname}:${port}/`); +});</code> + +</pre> + + <p><span class="tlid-translation translation" lang="es"><span title="">El código importa el módulo "http" y lo usa para crear un servidor </span></span> (<code>createServer()</code>) <span class="tlid-translation translation" lang="es"><span title="">que escucha las solicitudes HTTP en el puerto 3000</span></span>. <span class="tlid-translation translation" lang="es"><span title="">Luego, el script imprime un mensaje en la consola con la URL del navegador puede usar para probar el servidor</span></span>. La función <code>createServer()</code> <span class="tlid-translation translation" lang="es"><span title="">toma como argumento una función callback que se invocará cuando se reciba una solicitud HTTP </span></span>— <span class="tlid-translation translation" lang="es"><span title="">esto simplemente devuelve una respuesta con un código de estado HTTP de 200 ("OK") y el texto sin formato "Hello World".</span></span></p> + + <div class="note"> + <p><strong>Nota:</strong> <span class="tlid-translation translation" lang="es"><span title="">¡No se preocupe si aún no comprende exactamente lo que está haciendo este código!</span> <span title="">¡Explicaremos nuestro código con mayor detalle una vez que comencemos a usar Express!</span></span></p> + </div> + </li> + <li><span class="tlid-translation translation" lang="es"><span title="">Inicie el servidor navegando en el mismo directorio que su archivo <code>hellonode.js</code> en su símbolo del sistema, y llamando a <code>node</code> junto con el nombre del script, así:</span></span> + <pre class="brush: bash">>node hellonode.js +Server running at http://127.0.0.1:3000/ +</pre> + </li> + <li>Navega a la URL <a href="http://127.0.0.1:3000">http://127.0.0.1:3000 </a>. Sí todo esta funciona, el navegador simplemente debe mostrar la cadena de texto "Hello World".</li> +</ol> + +<h2 id="Usando_NPM">Usando NPM</h2> + +<p><span class="tlid-translation translation" lang="es"><span title="">Junto al propio node,</span></span> <a href="https://docs.npmjs.com/">NPM</a> <span class="tlid-translation translation" lang="es"><span title="">es la herramienta más importante para trabajar con aplicaciones de node.</span> <span title="">NPM se usa para obtener los paquetes (bibliotecas de JavaScript) que una aplicación necesita para el desarrollo, las pruebas y/o la producción, y también se puede usar para ejecutar pruebas y herramientas utilizadas en el proceso de desarrollo.</span></span></p> + +<div class="note"> +<p><strong>Nota:</strong> <span class="tlid-translation translation" lang="es"><span title="">Desde la perspectiva de Node, Express es solo otro paquete que necesita instalar usando NPM y luego requerir en su propio código.</span></span></p> +</div> + +<p><span class="tlid-translation translation" lang="es"><span title="">Se puede usar</span></span> NPM <span class="tlid-translation translation" lang="es"><span title="">manualmente para buscar por separado cada paquete necesario.</span> <span title="">Por lo general, administramos las dependencias utilizando un archivo de definición de texto plano llamado</span></span> <a href="https://docs.npmjs.com/files/package.json">package.json</a>. <span class="tlid-translation translation" lang="es"><span title="">Este archivo enumera todas las dependencias para un "paquete" de JavaScript específico, incluido el nombre del paquete, la versión, la descripción, el archivo inicial a ejecutar, las dependencias de producción, las dependencias de desarrollo, las versiones de Node con las que puede trabajar, etc. El archivo package.json debería</span> <span title="">contener todo lo que NPM necesita para buscar y ejecutar su aplicación (si estuviera escribiendo una biblioteca reutilizable, podría usar esta definición para cargar su paquete en el repositorio npm y ponerlo a disposición de otros usuarios).</span></span></p> + +<h3 id="Agregando_dependencias"><span class="tlid-translation translation" lang="es"><span title="">Agregando dependencias</span></span></h3> + +<p><span class="tlid-translation translation" lang="es"><span title="">Los siguientes pasos muestran cómo puede usar NPM para descargar un paquete, guardarlo en las dependencias del proyecto y luego requerirlo en una aplicación Node.</span></span></p> + +<div class="note"> +<p><strong>Nota:</strong> <span class="tlid-translation translation" lang="es"><span title="">Aquí mostramos las instrucciones para buscar e instalar el paquete <em>Express</em>.</span> <span title="">Más adelante mostraremos cómo este paquete y otros ya están especificados para nosotros utilizando el <em>Generador de aplicaciones Express</em>.</span> <span title="">Esta sección se proporciona porque es útil para comprender cómo funciona NPM y qué está creando el generador de aplicaciones.</span></span></p> +</div> + +<ol> + <li><span class="tlid-translation translation" lang="es"><span title="">Primero cree un directorio para su nueva aplicación y acceda a él:</span></span> + + <pre class="brush: bash">mkdir myapp +cd myapp</pre> + </li> + <li><span class="tlid-translation translation" lang="es"><span title="">Use el comando <code>npm init</code> para crear un archivo <strong>package.json</strong> para su aplicación.</span> <span title="">Este comando le solicita varias cosas, incluido el nombre y la versión de su aplicación y el nombre del archivo de punto de entrada inicial (de forma predeterminada, esto es <strong>index.js</strong>).</span> <span title="">Por ahora, solo acepte los valores predeterminados:</span></span></li> + <li> + <pre class="brush: bash">npm init</pre> + + <p><span class="tlid-translation translation" lang="es"><span title="">Si muestra el archivo <strong>package.json</strong> (<code>cat package.json</code>), verá los valores predeterminados que aceptó, que finalizarán con la licencia.</span></span></p> + + <pre class="brush: json">{ + "name": "myapp", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC" +} +</pre> + </li> + <li><span class="tlid-translation translation" lang="es"><span title="">Ahora instale Express en el directorio <code>myapp</code> y guárdelo en la lista de dependencias de su archivo package.json</span></span></li> + <li> + <pre class="brush: bash">npm install express --save</pre> + + <p><span class="tlid-translation translation" lang="es"><span title="">La sección de dependencias de su <strong>package.json</strong> ahora aparecerá al final del archivo <strong>package.json</strong> e incluirá <em>Express</em>.</span></span></p> + + <pre class="brush: json">{ + "name": "myapp", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", +<strong> "dependencies": { + "express": "^4.16.3" + }</strong> +} +</pre> + </li> + <li><span class="tlid-translation translation" lang="es"><span title="">Para usar la biblioteca, llame a la función <code>require ()</code> como se muestra a continuación en su archivo <strong>index.js</strong>.</span></span> + <pre><code><strong>const express = require('express')</strong> +const app = express(); + +app.get('/', (req, res) => { + res.send('Hello World!') +}); + +app.listen(</code>8000<code>, () => { + console.log('Example app listening on port </code>8000<code>!') +});</code> +</pre> + + <p><span class="tlid-translation translation" lang="es"><span title="">Este código muestra una aplicación web mínima "HelloWorld" Express.</span> <span title="">Esto importa el módulo "express" y lo usa para crear un servidor (<code>app</code>) que escucha las solicitudes HTTP en el puerto 8000 e imprime un mensaje en la consola que indica qué URL del navegador puede usar para probar el servidor.</span> <span title="">La función <code>app.get ()</code> solo responde a las solicitudes HTTP <code>GET</code> con la ruta URL especificada (<code>'/'</code>), en este caso llamando a una función para enviar nuestro mensaje Hello World!</span> <span title="">.</span></span></p> + </li> + <li> + <p>Cree un archivo llamado <strong>index.js</strong> en la raíz del directorio de la aplicación "myapp" y dele el contenido que se muestra arriba.</p> + </li> + <li><span class="tlid-translation translation" lang="es"><span title="">Puede iniciar el servidor llamando a node con el script en su símbolo del sistema:</span></span> + <pre class="brush: bash">>node index.js +Example app listening on port 8000 +</pre> + </li> + <li>Navega a la URL (<a href="http://127.0.0.1:8000/">http://127.0.0.1:8000/</a>). Sí todo esta funciona, el navegador simplemente debe mostrar la cadena de texto "Hello World".</li> +</ol> + +<h3 id="Dependencias_de_Desarrollo">Dependencias de Desarrollo</h3> + +<p><span class="tlid-translation translation" lang="es"><span title="">Si una dependencia solo se usa durante el desarrollo, debe guardarla como una "dependencia de desarrollo" (para que los usuarios de su paquete no tengan que instalarla en producción).</span></span> <span class="tlid-translation translation" lang="es"><span title="">Por ejemplo, para usar la popular herramienta Linting JavaScript</span></span> <a href="http://eslint.org/">eslint</a> <span class="tlid-translation translation" lang="es"><span title="">llamaría a NPM como se muestra a continuación:</span></span></p> + +<pre class="brush: bash"><code>npm install eslint --save-dev</code></pre> + +<div class="text-wrap tlid-copy-target"> +<div class="result-shield-container tlid-copy-target"><span class="tlid-translation translation" lang="es"><span title="">La siguiente entrada se agregaría al <strong>paquete.json</strong> de su aplicación:</span></span></div> + +<div class="result-shield-container tlid-copy-target"></div> +</div> + +<pre class="brush: js"> "devDependencies": { + "eslint": "^4.12.1" + } +</pre> + +<div class="note"> +<p><strong>Nota:</strong> "<a href="https://en.wikipedia.org/wiki/Lint_(software)">Linters</a>" <span class="tlid-translation translation" lang="es"><span title="">son herramientas que realizan análisis estáticos en el software para reconocer e informar la adhesión / no adhesión a algún conjunto de mejores prácticas de codificación.</span></span></p> +</div> + +<h3 id="Ejecutando_tareas"><span class="tlid-translation translation" lang="es"><span title="">Ejecutando tareas</span></span></h3> + +<p><span class="tlid-translation translation" lang="es"><span title="">Además de definir y buscar dependencias, también puede definir scripts con nombre en sus archivos package.json y llamar a NPM para ejecutarlos con el comando</span></span> <a href="https://docs.npmjs.com/cli/run-script">run-script</a>. <span class="tlid-translation translation" lang="es"><span title="">Este enfoque se usa comúnmente para automatizar las pruebas en ejecución y partes de la cadena de herramientas de desarrollo o construcción (por ejemplo, ejecutar herramientas para minimizar JavaScript, reducir imágenes, LINT/analizar su código, etc.)</span></span>.<span class="tlid-translation translation" lang="es"> </span></p> + +<div class="note"> +<p><strong>Nota:</strong> <span class="tlid-translation translation" lang="es"><span title="">Los ejecutadores de tareas como</span></span> <a href="http://gulpjs.com/">Gulp</a> y <a href="http://gruntjs.com/">Grunt</a><span class="tlid-translation translation" lang="es"><span title=""> también se pueden usar para ejecutar pruebas y otras herramientas externas.</span></span></p> +</div> + +<p><span class="tlid-translation translation" lang="es"><span title="">Por ejemplo, para definir un script para ejecutar la dependencia de desarrollo de <em>eslint </em>que especificamos en la sección anterior, podríamos agregar el siguiente bloque de script a nuestro archivo <strong>package.json</strong> (suponiendo que el origen de nuestra aplicación esté en una carpeta /src/js):</span></span></p> + +<pre class="brush: js">"scripts": { + ... + "lint": "eslint src/js" + ... +} +</pre> + +<p><span class="tlid-translation translation" lang="es"><span title="">Para explicar un poco más, <code>eslint src/js</code> es un comando que podríamos ingresar en nuestra línea de terminal/linea de comandos para ejecutar <code>eslint </code>en archivos JavaScript contenidos en el directorio <code>src/js</code> dentro de nuestro directorio de aplicaciones.</span> <span title="">Incluir lo anterior dentro del archivo package.json de nuestra aplicación proporciona un acceso directo para este comando: <code>lint</code>.</span></span></p> + +<p><br> + <span class="tlid-translation translation" lang="es"><span title="">Entonces podríamos ejecutar eslint usando NPM llamando a:</span></span></p> + +<pre class="brush: bash"><code>npm run-script lint +# OR (using the alias) +npm run lint</code> +</pre> + +<div class="text-wrap tlid-copy-target"> +<div class="result-shield-container tlid-copy-target"><span class="tlid-translation translation" lang="es"><span title="">Es posible que este ejemplo no parezca más corto que el comando original, pero puede incluir comandos mucho más grandes dentro de sus scripts npm, incluidas cadenas de comandos múltiples.</span> <span title="">Puede identificar un solo script npm que ejecute todas sus pruebas a la vez.</span></span></div> +</div> + +<h2 id="Instalando_Express_Application_Generator">Instalando Express Application Generator</h2> + +<p><span class="tlid-translation translation" lang="es"><span title="">La herramienta</span></span> <a href="https://expressjs.com/en/starter/generator.html">Express Application Generator</a> <span class="tlid-translation translation" lang="es"><span title="">genera un "esqueleto" de la aplicación Express.</span> <span title="">Instale el generador usando NPM como se muestra (el indicador <code>-g</code> instala la herramienta globalmente para que pueda llamarla desde cualquier lugar):</span></span></p> + +<pre><code>npm install express-generator -g</code></pre> + +<p><span class="tlid-translation translation" lang="es"><span title="">Para crear una aplicación <em>Express </em>llamada "helloworld" con la configuración predeterminada, navegue hasta donde desea crearla y ejecute la aplicación como se muestra:</span></span></p> + +<pre class="brush: bash">express helloworld</pre> + +<div class="note"> +<p><strong>Nota: </strong><span class="tlid-translation translation" lang="es"><span title="">También puede especificar la biblioteca de plantillas para usar y una serie de otras configuraciones.</span> <span title="">Use el comando <code>--help</code> para ver todas las opciones:</span></span></p> + +<pre class="brush: bash">express --help +</pre> +</div> + +<p><span class="tlid-translation translation" lang="es"><span title="">NPM creará la nueva aplicación Express en una subcarpeta de su ubicación actual, mostrando el progreso de la compilación en la consola.</span> <span title="">Al finalizar, la herramienta mostrará los comandos que necesita ingresar para instalar las dependencias de Node e iniciar la aplicación.</span></span></p> + +<div class="note"> +<p><span class="tlid-translation translation" lang="es"><span title="">La nueva aplicación tendrá un archivo <strong>package.json</strong> en su directorio raíz.</span> <span title="">Puede abrir esto para ver qué dependencias están instaladas, incluidas Express y la biblioteca de plantillas Jade:</span></span></p> + +<pre class="brush: js">{ + "name": "helloworld", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www" + }, + "dependencies": { + "body-parser": "~1.18.2", + "cookie-parser": "~1.4.3", + "debug": "~2.6.9", + "express": "~4.15.5", + "jade": "~1.11.0", + "morgan": "~1.9.0", + "serve-favicon": "~2.4.5" + } +}</pre> +</div> + +<p><span class="tlid-translation translation" lang="es"><span title="">Instale todas las dependencias para la aplicación helloworld usando NPM como se muestra:</span></span></p> + +<pre class="brush: bash">cd helloworld +npm install +</pre> + +<p><span class="tlid-translation translation" lang="es"><span title="">Luego ejecute la aplicación (los comandos son ligeramente diferentes para Windows y Linux/macOS), como se muestra a continuación:</span></span></p> + +<pre class="brush: bash"># <span class="tlid-translation translation" lang="es"><span title="">Ejecute helloworld en Windows con símbolo del sistema</span></span> +<code>SET DEBUG=helloworld:* & npm start</code> + +# <span class="tlid-translation translation" lang="es"><span title="">Ejecute helloworld en Windows con PowerShell</span></span> +SET DEBUG=helloworld:* | npm start + +# <span class="tlid-translation translation" lang="es"><span title="">Ejecute helloworld en Linux/macOS</span></span> +DEBUG=helloworld:* npm start +</pre> + +<p><span class="tlid-translation translation" lang="es"><span title="">El comando DEBUG crea registros útiles, lo que resulta en una salida como la que se muestra a continuación.</span></span></p> + +<pre class="brush: bash">>SET DEBUG=helloworld:* & npm start + +> helloworld@0.0.0 start D:\Github\expresstests\helloworld +> node ./bin/www + + helloworld:server Listening on port 3000 +0ms</pre> + +<p><span class="tlid-translation translation" lang="es"><span title="">Abra un navegador y navegue a</span></span> <a href="http://127.0.0.1:3000/">http://127.0.0.1:3000/</a> <span class="tlid-translation translation" lang="es"><span title="">para ver la página de bienvenida Express predeterminada.</span></span></p> + +<p><img alt="Express - Generated App Default Screen" src="https://mdn.mozillademos.org/files/14331/express_default_screen.png" style="border-style: solid; border-width: 1px; display: block; height: 301px; margin: 0px auto; width: 675px;"></p> + +<p><span class="tlid-translation translation" lang="es"><span title="">Hablaremos más sobre la aplicación generada cuando lleguemos al artículo sobre la generación de una aplicación esqueleto.</span></span></p> + +<ul> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p><span class="tlid-translation translation" lang="es"><span title="">Ahora tiene un entorno de desarrollo de Node en funcionamiento en su computadora que puede usarse para crear aplicaciones web Express.</span> <span title="">También ha visto cómo se puede usar NPM para importar Express en una aplicación, y también cómo puede crear aplicaciones usando la herramienta Express Application Generator y luego ejecutarlas.</span><br> + <br> + <span title="">En el siguiente artículo, comenzaremos a trabajar a través de un tutorial para crear una aplicación web completa utilizando este entorno y las herramientas asociadas.</span></span></p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://nodejs.org/en/download/">Downloads</a> page (nodejs.org)</li> + <li><a href="https://nodejs.org/en/download/package-manager/">Installing Node.js via package manager</a> (nodejs.org)</li> + <li><a href="http://expressjs.com/en/starter/installing.html">Installing Express</a> (expressjs.com)</li> + <li><a href="https://expressjs.com/en/starter/generator.html">Express Application Generator</a> (expressjs.com)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Introduction", "Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/es/learn/server-side/express_nodejs/index.html b/files/es/learn/server-side/express_nodejs/index.html new file mode 100644 index 0000000000..2c224095c0 --- /dev/null +++ b/files/es/learn/server-side/express_nodejs/index.html @@ -0,0 +1,76 @@ +--- +title: Express Web Framework (Node.js/JavaScript) +slug: Learn/Server-side/Express_Nodejs +tags: + - Aplicaciones Web + - Aprendizaje + - Express + - Express.js + - JavaScript + - Node + - Novato + - Programación del lado del Servidor + - introducción + - programacion +translation_of: Learn/Server-side/Express_Nodejs +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Express es un framework web transigente, escrito en JavaScript y alojado dentro del entorno de ejecución NodeJS. El modulo explica algunos de los beneficios clave de este framework, como configurar tu entorno de desarrollo y como realizar tareas comunes en desarrollo y publicación web.</p> + +<h2 id="Prerequisitos">Prerequisitos</h2> + +<p>Antes de empezar con este módulo necesitaras entender los conceptos de programación web en el lado del servidor y los frameworks, de preferencia leyendo acerca de estos temas en nuestro modulo <a href="/en-US/docs/Learn/Server-side/First_steps">Primeros pasos en la programación web del lado del servidor</a>. Un conocimiento general de conceptos de programación y JavaScript es altamente recomendado, pero no esencial para entender los conceptos básicos.</p> + +<div class="note"> +<p><strong>Nota</strong> : Esta web posee muchos recursos útiles para aprender JavaScript <em>en el contexto del desarrollo en el lado del cliente:</em> <a href="/en-US/docs/Web/JavaScript">JavaScript</a>, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide">Guía de JavaScript</a>, <a href="/en-US/docs/Learn/Getting_started_with_the_web/JavaScript_basics">JavaScript Básico</a>, <a href="/en-US/docs/Learn/JavaScript">JavaScript</a> (aprendizaje). El lenguaje JavaScript y sus conceptos son los mismos para el desarrollo en el lado del servidor en NodeJS y este material será relevante. NodeJS ofrece <a href="https://nodejs.org/dist/latest-v6.x/docs/api/">APIs adicionales</a> para soportar funcionalidades que son útiles en entornos sin navegador web, por ejemplo para crear servidores HTTP y acceder al sistema de archivos, pero no soportan APIs de JavaScript para trabajar con el navegador y el DOM.</p> + +<p>Esta guía proporciona información útil para trabajar con Node.js y Express, además hay numerosos y excelentes recursos en Internet y en libros - algunos de estos referenciados en <a href="http://stackoverflow.com/a/5511507/894359">Cómo empezar con Node.js</a> (Inglés - StackOverflow) y <a href="https://www.quora.com/What-are-the-best-resources-for-learning-Node-js?">¿Cuáles son los mejores recursos para aprender Node.js?</a> (Inglés - Quora).</p> +</div> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="/es/docs/Learn/Server-side/Express_Nodejs/Introduction">Introducción a Express/Node </a></dt> + <dd>En el primer artículo de Express respondemos las preguntas "¿Qué es Node?" y "¿Qué es Express?" y te daremos una visión general de qué hace especial al framework web Express. Destacaremos las principales caracteristicas, y mostraremos algunos de los bloques principales de una aplicación Express (aunque en este punto aún no tendrás un entorno de desarrollo para probarlo).</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Preparando un entorno de desarrollo Node (Express)</a></dt> + <dd>Ahora que sabes para que sirve Express, te mostraremos como preparar y probar un entorno de desarrollo Node/Express en Windows, Linux (Ubuntu), y Mac OS X. Sin importar el sistema operativo que estes usando, este artículo te proporcionará lo que necesites para empezar a desarrollar aplicaciones Express.</dd> + <dt><strong><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Tutorial Express: la web de Librería local</a></strong></dt> + <dd>El primer artículo en nuestra serie de tutoriales prácticos en los que se explica lo que aprenderás así como una breve introducción al proyecto de <em>"Librería local", </em>que será en el que trabajaremos y desarrollaremos a lo largo de la serie.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Tutorial Express 2: Creando el esqueleto de un sitio web</a> </dt> + <dd>Este artículo muestra cómo puede crear el "esqueleto" de un proyecto web, al cual podremos ir agregando nuestras rutas específicas para el sitio, plantillas/vistas, y bases de datos.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Tutorial Express 3: Usando una base de datos (con Mongoose)</a></dt> + <dd>Este artículo nos introducirá brevemente en las bases de datos para Node/Express. Entonces nos mostrara como podemos usar <a href="http://mongoosejs.com/">Mongoose</a> para agregar acceso a una base de datos para el sitio web LocalLibrary. Explica como son declarados los objetos de esquema y modelos, los principales tipos para los campos, y validación básica. También mostrara brevemente algunas de las principales formas con las que puedes acceder a los modelos de datos.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Tutorial Express 4: Rutas y controladores</a></dt> + <dd>En este tutorial prepararemos las rutas (URL handling code) con un manejador de funciones "dummy" para todos los puntos de obtención de recursos que iremos a necesitar en nuestra web LocalLibrary. Al finalizar, tendremos una estructura modular para manejar nuestro código manejador de rutas, que podremos extender con funciones manejadoras reales en los artículos siguientes. También tendremos un muy buen entendimiento de cómo crear rutas modulares usando Express.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Tutorial Express 5: Mostrado datos de la librería</a></dt> + <dd>Ahora estamos listos para añadir paginas donde mostrar los libros de LocalLibrary y otros datos. Las paginas incluirán una página de inicio que muestre cuantos elementos tenemos de cada tipo de modelo, y páginas de lista y detalles para todos nuestros modelos. En el camino iremos ganando experiencia práctica en obtener elementos de la base de datos, y usando plantillas.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Tutorial Express 6: Trabajando con formularios</a></dt> + <dd>En este tutorial mostraremos como trabajar con <a href="/en-US/docs/Web/Guide/HTML/Forms">formularios HTML</a> en Express, usando Pug, y en particular como escribir formularios para crear, actualizar y borrar documentos en la base de datos.</dd> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Tutorial Express 7: Desplegando para producción</a></dt> + <dd>Ahora que has creado una increíble web llamada LocalLibrary, la querrás instalar en un servidor web público para que pueda acceder a ella el personal de la librería y los usuarios por Internet. Este artículo te ofrece una visión general de como deberías buscar un alojamiento para tu página web, y que necesitas para tener tu sitio listo para producción.</dd> + <dd> </dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<dl> + <dt><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Installing_on_PWS_Cloud_Foundry">Instalando LocalLibrary en PWS/Cloud Foundry</a></dt> + <dd>Este artículo nos da una demonstración práctica de cómo instalar <em>LocalLibrary</em> en la <a href="http://run.pivotal.io">nube Pivotal Web Services PaaS</a> — ésta es una alternativa, muy completa y de código libre, a Heroku, el servicio en la nube PaaS es usado en la parte 7 de este tutorial, listado más adelante. PWS/Cloud Foundry es un recurso digno de revisar si estás en busca de una alternativa a Heroku ( o cualquier otro servicio en la nube PaaS), o simplemente si tienes ganas de intentar algo diferente.</dd> +</dl> + +<h2 id="Añadiendo_mas_tutoriales">Añadiendo mas tutoriales</h2> + +<div> +<p>Este es el final de los tutoriales (por ahora). Si quisieras extenderlos, hay otros temas interesantes por tratar como:</p> + +<ul> + <li>Uso de sesiones.</li> + <li>Autenticación de usuarios.</li> + <li>Autorizaciones y permisos de usuario.</li> + <li>Probando una aplicación web Express.</li> + <li>Seguridad web para aplicaciones web Express.</li> +</ul> + +<p>Y por supuesto, ¡seria excelente tener una tarea de evaluación!</p> +</div> diff --git a/files/es/learn/server-side/express_nodejs/introduction/index.html b/files/es/learn/server-side/express_nodejs/introduction/index.html new file mode 100644 index 0000000000..d607c0dd0f --- /dev/null +++ b/files/es/learn/server-side/express_nodejs/introduction/index.html @@ -0,0 +1,498 @@ +--- +title: Introducción a Express/Node +slug: Learn/Server-side/Express_Nodejs/Introduction +tags: + - Aprender + - Express + - MDN + - Node + - Servidor + - javascri + - lado del servidor + - nodejs +translation_of: Learn/Server-side/Express_Nodejs/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Aprendizaje/Lado-Servidor/Express_Nodejs/Ambiente-Desarrollo", "Aprendizaje/Lado-Servidor/Express_Nodejs")}}</div> + +<p class="summary">En este primer articulo de Express resolveremos las preguntas "¿Qué es Node?" y "¿Qué es Express?", y te daremos una visión general de que hace especial al framework web "Express". Delinearemos las características principales, y te mostraremos algunos de los principales bloques de construcción de una aplicación en Express (aunque en este punto no tendrás todavía un entorno de desarrollo en que probarlo).</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td> + <p>Conocimientos básicos de informática. Noción general sobre <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos">programación lado servidor de sitios web</a>, y en particular los mecanismos de las interacciones <a href="/es/docs/Learn/Server-side/Primeros_pasos/Vision_General_Cliente_Servidor">cliente-servidor en sitios web</a>.</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Ganar familiaridad con lo que es Express y cómo encaja con Node, qué funcionalidad proporciona y los pilares de construcción de una aplicación Express.</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_son_Express_y_Node">¿Qué son Express y Node?</h2> + +<p><a href="https://nodejs.org/">Node</a> (o más correctamente: <em>Node.js</em>) es un entorno que trabaja en tiempo de ejecución, de código abierto, multi-plataforma, que permite a los desarrolladores crear toda clase de herramientas de lado servidor y aplicaciones en <a href="/es/docs/Glossary/JavaScript">JavaScript</a>. La ejecución en tiempo real está pensada para usarse fuera del contexto de un explorador web (es decir, ejecutarse directamente en una computadora o sistema operativo de servidor). Como tal, el entorno omite las APIs de JavaScript específicas del explorador web y añade soporte para APIs de sistema operativo más tradicionales que incluyen HTTP y bibliotecas de sistemas de ficheros.</p> + +<p>Desde una perspectiva de desarrollo de servidor web, Node tiene un gran número de ventajas:</p> + +<ul> + <li>¡Gran rendimiento! <em>Node</em> ha sido diseñado para optimizar el rendimiento y la escalabilidad en aplicaciones web y es un muy buen complemento para muchos problemas comunes de desarrollo web (ej, aplicaciones web en tiempo real).</li> + <li>El código está escrito en "simple JavaScript", lo que significa que se pierde menos tiempo ocupándose de las "conmutaciones de contexto" entre lenguajes cuando estás escribiendo tanto el código del explorador web como del servidor.</li> + <li>JavaScript es un lenguaje de programación relativamente nuevo y se beneficia de los avances en diseño de lenguajes cuando se compara con otros lenguajes de servidor web tradicionales (ej, Python, PHP, etc.) Muchos otros lenguajes nuevos y populares se compilan/convierten a JavaScript de manera que puedes también usar CoffeeScript, ClosureScript, Scala, LiveScript, etc.</li> + <li>El gestor de paquetes de <em>Node</em> (NPM del inglés: Node Packet Manager) proporciona acceso a cientos o miles de paquetes reutilizables. Tiene además la mejor en su clase resolución de dependencias y puede usarse para automatizar la mayor parte de la cadena de herramientas de compilación.</li> + <li>Es portable, con versiones que funcionan en Microsoft Windows, OS X, Linux, Solaris, FreeBSD, OpenBSD, WebOS, y NonStop OS. Además, está bien soportado por muchos de los proveedores de hospedaje web, que proporcionan infraestructura específica y documentación para hospedaje de sitios <em>Node</em>.</li> + <li>Tiene un ecosistema y comunidad de desarrolladores de terceros muy activa, con cantidad de gente deseosa de ayudar.</li> +</ul> + +<p>Puedes crear de forma sencilla un servidor web básico para responder cualquier petición simplemente usando el paquete HTTP de <em>Node</em>, como se muestra abajo. Este, creará un servidor y escuchará cualquier clase de peticiones en la URL <code>http://127.0.0.1:8000/</code>; cuando se reciba una petición, se responderá enviando en texto la respuesta: "Hola Mundo!".</p> + +<pre class="brush: js notranslate">// Se carga el módulo de HTTP +var http = require("http"); + +// Creación del servidor HTTP, y se define la escucha +// de peticiones en el puerto 8000 +http.createServer(function(request, response) { + + // Se define la cabecera HTTP, con el estado HTTP (OK: 200) y el tipo de contenido + response.writeHead(200, {'Content-Type': 'text/plain'}); + + // Se responde, en el cuerpo de la respuesta con el mensaje "Hello World" + response.end('Hola Mundo!\n'); +}).listen(8000); + +// Se escribe la URL para el acceso al servidor +console.log('Servidor en la url http://127.0.0.1:8000/');</pre> + +<p>Otras tareas comunes de desarrollo web no están directamente soportadas por el mismo <em>Node</em>. Si quieres añadir el manejo específico de diferentes verbos HTTP (ej, <code>GET</code>, <code>POST</code>, <code>DELETE</code>, etc.), gestionar de forma separada las peticiones por medio de diferentes direcciones URL ("rutas"), servir ficheros estáticos o usar plantillas para crear la respuesta de forma dinámica, necesitarás escribir el código por tí mismo, o ¡puedes evitar reinventar la rueda usando un framework web!</p> + +<p><a href="https://expressjs.com/">Express</a> es el framework web más popular de <em>Node</em>, y es la librería subyacente para un gran número de otros <a href="https://expressjs.com/en/resources/frameworks.html">frameworks web de Node</a> populares. Proporciona mecanismos para:</p> + +<ul> + <li>Escritura de manejadores de peticiones con diferentes verbos HTTP en diferentes caminos URL (rutas).</li> + <li>Integración con motores de renderización de "vistas" para generar respuestas mediante la introducción de datos en plantillas.</li> + <li>Establecer ajustes de aplicaciones web como qué puerto usar para conectar, y la localización de las plantillas que se utilizan para renderizar la respuesta.</li> + <li>Añadir procesamiento de peticiones "middleware" adicional en cualquier punto dentro de la tubería de manejo de la petición.</li> +</ul> + +<p>A pesar de que <em>Express</em> es en sí mismo bastante minimalista, los desarrolladores han creado paquetes de middleware compatibles para abordar casi cualquier problema de desarrollo web. Hay librerías para trabajar con cookies, sesiones, inicios de sesión de usuario, parámetros URL, datos <code>POST</code>, cabeceras de seguridad y <em>muchos</em> más. Puedes encontrar una lista de paquetes middleware mantenida por el equipo de Express en <a href="https://expressjs.com/es/resources/middleware.html">Express Middleware</a> (junto con una lista de algunos de los paquetes más populares de terceros).</p> + +<div class="note"> +<p><strong>Nota:</strong> esta flexibilidad es una espada de doble filo. Hay paquetes de middleware para abordar casi cualquier problema o requerimiento, pero deducir cuáles son los paquetes adecuados a usar algunas veces puede ser un auténtico reto. Tampoco hay una "forma correcta" de estructurar una aplicación, y muchos ejemplos que puedes encontrar en la Internet no son óptimos, o sólo muestran una pequeña parte de lo que necesitas hacer para desarrollar una aplicación web.</p> +</div> + +<h2 id="¿Dónde_comenzó">¿Dónde comenzó?</h2> + +<p><em>Node</em> fué lanzado inicialmente, sólo para Linux, en 2009. El gestor de paquetes NPM fué lanzado en 2010, y el soporte nativo para Windows fue añadido en 2012. La versión actual LTS (Long Term Suppport) es Node v12.18.0 mientras que la última versión es Node 14.4.0. Ésto es sólo una pequeña foto de una historia muy rica; profundiza en <a href="https://en.wikipedia.org/wiki/Node.js#History">Wikipedia</a> si quieres saber más).</p> + +<p><em>Express</em> fue lanzado inicialmente en Noviembre de 2010 y está ahora en la versión 4.17.1 de la API. Puedes comprobar en el <a href="https://expressjs.com/en/changelog/4x.html">changelog</a> la información sobre cambios en la versión actual, y en <a href="https://github.com/expressjs/express/blob/master/History.md">GitHub</a> notas de lanzamiento históricas más detalladas.</p> + +<h2 id="¿Qué_popularidad_tiene_NodeExpress">¿Qué popularidad tiene Node/Express?</h2> + +<p>La popularidad de un framework web es importante porque es un indicador de se continuará manteniendo y qué recursos tienen más probabilidad de estar disponibles en términos de documentación, librerías de extensiones y soporte técnico.</p> + +<p>No existe una medida disponible de inmediato y definitiva de la popularidad de los frameworks de lado servidor (aunque sitios como <a href="http://hotframeworks.com/">Hot Frameworks</a> intentan asesorar sobre popularidad usando mecanismos como contar para cada plataforma el número de preguntas sobre proyectos en GitHub y StackOverflow). Una pregunta mejor es si Node y Express son lo "suficientemente populares" para evitar los problemas de las plataformas menos populares. ¿Continúan evolucionando? ¿Puedes conseguir la ayuda que necesitas? ¿Hay alguna posibilidad de que consigas un trabajo remunerado si aprendes Express?</p> + +<p>De acuerdo con el número de <a href="https://expressjs.com/en/resources/companies-using-express.html">compañías de perfil alto</a> que usan Express, el número de gente que contribuye al código base, y el número de gente que proporciona soporte tanto libre como pagado, podemos entonces decir que sí, !<em>Express</em> es un framework popular!</p> + +<h2 id="¿Es_Express_dogmático">¿Es Express dogmático?</h2> + +<p>Los frameworks web frecuentemente se refieren a sí mismos como "dogmáticos" ("<em>opinionated</em>") o "no dogmáticos" ("<em>unopinionated</em>").</p> + +<p>Los frameworks dogmáticos son aquellos que opinan acerca de la "manera correcta" de gestionar cualquier tarea en particular. Ofrecen soporte para el desarrollo rápido en un <em>dominio en particular</em> (resolver problemas de un tipo en particular) porque la manera correcta de hacer cualquier cosa está generalmente bien comprendida y bien documentada. Sin embargo pueden ser menos flexibles para resolver problemas fuera de su dominio principal, y tienden a ofrecer menos opciones para elegir qué componentes y enfoques pueden usarse.</p> + +<p>Los framewoks no dogmáticos, en contraposición, tienen muchas menos restricciones sobre el modo mejor de unir componentes para alcanzar un objetivo, o incluso qué componentes deberían usarse. Hacen más fácil para los desarrolladores usar las herramientas más adecuadas para completar una tarea en particular, si bien al coste de que necesitas encontrar esos componentes por tí mismo.<br> + <br> + Express es no dogmático, transigente. Puedes insertar casi cualquier middleware compatible que te guste dentro de la cadena de manejo de la petición, en casi cualquier orden que te apetezca. Puedes estructurar la app en un fichero o múltiples ficheros y usar cualquier estructura de directorios. ¡Algunas veces puedes sentir que tienes demasiadas opciones!</p> + +<h2 id="¿Cómo_es_el_código_para_Express">¿Cómo es el código para Express?</h2> + +<p>En sitios web o aplicaciones web dinámicas, que accedan a bases de datos, el servidor espera a recibir peticiones HTTP del navegador (o cliente). Cuando se recibe una petición, la aplicación determina cuál es la acción adecuada correspondiente, de acuerdo a la estructura de la URL y a la información (opcional) indicada en la petición con los métodos <code>POST</code> o <code>GET</code>. Dependiendo de la acción a realizar, puede que se necesite leer o escribir en la base de datos, o realizar otras acciones necesarias para atender la petición correctamente. La aplicación ha de responder al navegador, normalmente, creando una página HTML dinámicamente para él, en la que se muestre la información pedida, usualmente dentro de un elemento especifico para este fin, en una plantilla HTML.</p> + +<p><em>Express</em> posee métodos para especificar que función ha de ser llamada dependiendo del verbo HTTP usado en la petición (<code>GET</code>, <code>POST</code>, <code>SET</code>, etc.) y la estructura de la URL ("ruta"). También tiene los métodos para especificar que plantilla ("view") o gestor de visualización utilizar, donde están guardadas las plantillas de HTML que han de usarse y como generar la visualización adecuada para cada caso. El middleware de <em>Express</em>, puede usarse también para añadir funcionalidades para la gestión de cookies, sesiones y usuarios, mediante el uso de parámetros, en los métodos <code>POST</code>/<code>GET</code>. Puede utilizarse además cualquier sistema de trabajo con bases de datos, que sea soportado por <em>Node</em> (<em>Express</em> no especifica ningún método preferido para trabajar con bases de datos). </p> + +<p>En las siguientes secciones, se explican algunos puntos comunes que se pueden encontrar cuando se trabaja con código de <em>Node</em> y <em>Express</em>.</p> + +<h3 id="Hola_Mundo!_-_en_Express">Hola Mundo! - en Express</h3> + +<p>Primero consideremos el tradicional ejemplo de <a href="https://expressjs.com/en/starter/hello-world.html">Hola Mundo!</a> (se comentará cada parte a continuación).</p> + +<div class="note"> +<p><strong>Consejo:</strong> Si tiene <em>Node</em> y <em>Express</em> instalado (o piensa instalarlos posteriormente) puede guardar este código en un archivo llamado <strong>app.js</strong> y ejecutarlo posteriormente en la linea de comandos invocándolo mediante: <code>node app.js</code>. </p> +</div> + +<pre class="brush: js notranslate">var express = require('express'); +var app = express(); + +<strong>app.get('/', function(req, res) { + res.send('Hola Mundo!'); +});</strong> + +app.listen(3000, function() { + console.log('Aplicación ejemplo, escuchando el puerto 3000!'); +}); +</pre> + +<p>Las primeras dos líneas incluyen (mediante la orden <code>require()</code>) el módulo de Express y crean una <a href="https://expressjs.com/en/4x/api.html#app">aplicación de Express</a>. Este elemento se denomina comúnmente <code>app</code>, y posee métodos para el enrutamiento de las peticiones HTTP, configuración del 'middleware', y visualización de las vistas de HTML, uso del motores de 'templates', y gestión de las <a href="https://expressjs.com/en/4x/api.html#app.settings.table">configuraciones de las aplicaciones </a> que controlan la aplicación (por ejemplo el entorno, las definiciones para enrutado ... etcetera.)</p> + +<p>Las líneas que siguen en el código (las tres líneas que comienzan con <code>app.get</code>) muestran una definición de ruta que se llamará cuando se reciba una petición HTTP <code>GET</code> con una dirección (<code>'/'</code>) relativa al directorio raíz. La función 'callback' coge una petición y una respuesta como argumentos, y ejecuta un <code><a href="https://expressjs.com/en/4x/api.html#res.send">send()</a></code> en la respuesta, para enviar la cadena de caracteres: "Hola Mundo!".</p> + +<p>El bloque final de código, define y crea el servidor, escuchando el puerto 3000 e imprime un comentario en la consola. Cuando se está ejecutando el servidor, es posible ir hasta la dirección <code>localhost:3000</code> en un navegador, y ver como el servidor de este ejemplo devuelve el mensaje de respuesta.</p> + +<h3 id="Importando_y_creando_módulos">Importando y creando módulos</h3> + +<p>Un modulo es una librería o archivo JavaScript que puede ser importado dentro de otro código utilizando la función <code>require()</code> de Node. Por sí mismo, <em>Express</em> es un modulo, como lo son el middleware y las librerías de bases de datos que se utilizan en las aplicaciones <em>Express.</em></p> + +<p>El código mostrado abajo, muestra como puede importarse un modulo con base a su nombre, como ejemplo se utiliza el framework <em>Express</em> . Primero se invoca la función <code style="font-style: normal; font-weight: normal;">require()</code>, indicando como parámetro el nombre del módulo o librería como una cadena (<code>'express'</code>), posteriormente se invoca el objeto obtenido para crear una <a href="https://expressjs.com/en/4x/api.html#app">aplicación Express</a>.</p> + +<p>Posteriormente, se puede acceder a las propiedades y funciones del objeto Aplicación.</p> + +<pre class="brush: js notranslate">var express = require('express'); +var app = express(); +</pre> + +<p>También podemos crear nuestros propios módulos que puedan posteriormente ser importados de la misma manera.</p> + +<div class="note"> +<p><strong>Consejo:</strong> Usted puede desear crear sus propios módulos, esto le permitirá organizar su código en partes más administrables; una aplicación que reside en un solo archivo es difícil de entender y manejar.</p> + +<p>El utilizar módulos independientes también le permite administrar el espacio de nombres, de esta manera unicamente las variables que exporte explícitamente son importadas cuando utilice un módulo.</p> +</div> + +<p>Para hacer que los objetos esten disponibles fuera de un modulo, solamente es necesario asignarlos al objeto <code>exports</code>. Por ejemplo, el modulo mostrado a continuación <strong>square.js</strong> es un archivo que exporta los métodos <code>area()</code> y <code>perimeter()</code> :</p> + +<pre class="brush: js notranslate"><strong>exports</strong>.area = function(width) { return width * width; }; +<strong>exports</strong>.perimeter = function(width) { return 4 * width; }; +</pre> + +<p>Nosotros podemos importar este módulo utilizando la función <code>require()</code>, y entonces podremos invocar los métodos exportados de la siguiente manera:</p> + +<pre class="brush: js notranslate">// Utilizamos la función<strong> require()</strong> El nombre del archivo se ingresa sin la extensión (opcional) .js +var square = require('./square'); +// invocamos el metodo <strong>area()</strong> +console.log('El área de un cuadrado con lado de 4 es ' + square.area(4));</pre> + +<div class="note"> +<p><strong>Nota:</strong> Usted también puede especificar una ruta absoluta a la ubicación del módulo (o un nombre como se realizó inicialmente). </p> +</div> + +<p>Si usted desea exportar completamente un objeto en una asignación en lugar de construir cada propiedad por separado, debe asignarlo al módulo <code>module.exports</code> como se muestra a continuación (también puede hacer esto al inicio de un constructor o de otra función.)</p> + +<pre class="brush: js notranslate">module.exports = { + area: function(width) { + return width * width; + }, + + perimeter: function(width) { + return 4 * width; + } +}; +</pre> + +<p>Para más información acerca de módulos vea <a href="https://nodejs.org/api/modules.html#modules_modules">Modulos</a> (<em>Node</em> API docs).</p> + +<h3 id="Usando_APIs_asíncronas">Usando APIs asíncronas</h3> + +<p>El código JavaScript usa frecuentemente APIs asíncronas antes que sincrónicas para operaciones que tomen algún tiempo en completarse. En una API sincrónica cada operación debe completarse antes de que la siguiente pueda comenzar. Por ejemplo, la siguiente función de registro es síncrona, y escribirá en orden el texto en la consola (Primero, Segundo).</p> + +<pre class="brush: js notranslate">console.log('Primero'); +console.log('Segundo'); +</pre> + +<p>En contraste, en una API asincrónica, la API comenzará una operación e inmediatamente retornará (antes de que la operación se complete). Una vez que la operación finalice, la API usará algún mecanismo para realizar operaciones adicionales. Por ejemplo, el código de abajo imprimirá "Segundo, Primero" porque aunque el método <code>setTimeout()</code> es llamado primero y retorna inmediatamente, la operación no se completa por varios segundos.</p> + +<pre class="brush: js notranslate">setTimeout(function() { + console.log('Primero'); + }, 3000); +console.log('Segundo'); +</pre> + +<p>Usar APIs asíncronas sin bloques es aun mas importante en <em>Node</em> que en el navegador, porque <em>Node</em> es un entorno de ejecución controlado por eventos de un solo hilo. "Un solo hilo" quiere decir que todas las peticiones al servidor son ejecutadas en el mismo hilo ( en vez de dividirse en procesos separados). Este modelo es extremadamente eficiente en términos de velocidad y recursos del servidor, pero eso significa que si alguna de sus funciones llama a métodos sincrónicos que tomen demasiado tiempo en completarse, bloquearan no solo la solicitud actual, sino también cualquier otra petición que este siendo manejada por tu aplicación web.</p> + +<p>Hay muchas maneras para una API asincrónica de notificar a su aplicación que se ha completado. La manera mas común es registrar una función callback cuando usted invoca a una API asincrónica, la misma será llamada de vuelta cuando la operación se complete. Éste es el enfoque utilizado anteriormente.</p> + +<div class="note"> +<p><strong>Tip:</strong> Usar "callbacks" puede ser un poco enmarañado si usted tiene una secuencia de operaciones asíncronas dependientes que deben ser llevadas a cabo en orden, porque esto resulta en múltiples niveles de "callbacks" anidadas. Este problema es comúnmente conocido como "callback hell" (callback del infierno). Este problema puede ser reducido con buenas practicas de código (vea <a href="http://callbackhell.com/">http://callbackhell.com/</a>), usando un modulo como <a href="https://www.npmjs.com/package/async">async</a>, o incluso avanzando a características de ES6 como las <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise">promesas</a>.</p> +</div> + +<div class="note"> +<p><strong>Nota:</strong> Una convención común para <em>Node</em> y <em>Express</em> es usar callbacks de error primero. En esta convención el primer valor en su función callback es un error, mientras que los argumentos subsecuentes contienen datos correctos. Hay una buena explicación de porque este enfoque es útil en este blog: <a href="http://fredkschott.com/post/2014/03/understanding-error-first-callbacks-in-node-js">The Node.js Way - Understanding Error-First Callbacks</a> (fredkschott.com).</p> +</div> + +<h3 id="Creando_manejadores_de_rutas">Creando manejadores de rutas</h3> + +<p>En nuestro ejemplo anterior de "Hola Mundo!" en <em>Express</em> (véase mas arriba), definimos una función (callback) manejadora de ruta para peticiones HTTP <code>GET</code> a la raíz del sitio (<code>'/'</code>).</p> + +<pre class="brush: js notranslate">app.<strong>get</strong>('/', function(req, res) { + res.send('Hello World!'); +}); +</pre> + +<p>La función callback toma una petición y una respuesta como argumentos. En este caso el método simplemente llama a <code><a href="https://expressjs.com/en/4x/api.html#res.send">send()</a></code> en la respuesta para retornar la cadena "Hello World!". Hay un <a href="https://expressjs.com/en/guide/routing.html#response-methods">número de otros métodos de respuesta</a> para finalizar el ciclo de solicitud/respuesta, por ejemplo podrá llamar a <code><a href="https://expressjs.com/en/4x/api.html#res.json">res.json()</a></code> para enviar una respuesta JSON o <code><a href="https://expressjs.com/en/4x/api.html#res.sendFile">res.sendFile()</a></code> para enviar un archivo.</p> + +<div class="note"> +<p><strong>JavaScript tip:</strong> Usted puede utilizar cualquier nombre que quiera para los argumentos en las funciones callback; cuando la callback es invocada el primer argumento siempre sera la petición y el segundo siempre sera la respuesta. Tiene sentido nombrarlos de manera que pueda identificar el objeto con el que esta trabajando en el cuerpo de la callback.</p> +</div> + +<p>El objeto que representa una aplicación de <em>Express</em>, también posee métodos para definir los manejadores de rutas para el resto de los verbos HTTP: <code>post()</code>, <code>put()</code>, <code>delete()</code>, <code>options()</code>, <code>trace()</code>, <code>copy()</code>, <code>lock()</code>, <code>mkcol()</code>, <code>move()</code>, <code>purge()</code>, <code>propfind()</code>, <code>proppatch()</code>, <code>unlock()</code>, <code>report()</code>, <code>mkactivity()</code>, <code>checkout()</code>, <code>merge()</code>, <code>m-</code><code>search</code><code>()</code>, <code>notify()</code>, <code>subscribe()</code>, <code>unsubscribe()</code>, <code>patch()</code>, <code>search()</code>, y <code>connect()</code>.</p> + +<p>Hay un método general para definir las rutas: <code>app.all()</code>, el cual será llamado en respuesta a cualquier método HTTP. Se usa para cargar funciones del middleware en una dirección particular para todos los métodos de peticiones. El siguiente ejemplo (de la documentación de <em>Express</em>) muestra el uso de los manejadores a <code>/secret</code> sin tener en cuenta el verbo HTTP utilizado (siempre que esté definido por el <a href="https://nodejs.org/api/http.html#http_http_methods">módulo http</a>).</p> + +<pre class="brush: js notranslate">app.all('/secret', function(req, res, next) { + console.log('Accediendo a la seccion secreta ...'); + next(); // pasa el control al siguiente manejador +});</pre> + +<p>Las rutas le permiten igualar patrones particulares de caracteres en la URL, y extraer algunos valores de ella y pasarlos como parámetros al manejador de rutas (como atributo del objeto petición pasado como parámetro).</p> + +<p>Usualmente es útil agrupar manejadores de rutas para una parte del sitio juntos y accederlos usando un prefijo de ruta en común. (Ej: un sitio con una Wiki podría tener todas las rutas relacionadas a dicha sección en un archivo y siendo accedidas con el prefijo de ruta /wiki/. En <em>Express</em> esto se logra usando el objeto <code><a href="http://expressjs.com/en/guide/routing.html#express-router">express.Router</a></code>. Ej: podemos crear nuestra ruta wiki en un módulo llamado wiki.js, y entonces exportar el objeto <code>Router</code>, como se muestra debajo:</p> + +<pre class="brush: js notranslate">// wiki.js - Modulo de rutas Wiki + +var express = require('express'); +var router = express.Router(); + +// Home page route +router.get('/', function(req, res) { + res.send('Página de inicio Wiki'); +}); + +// About page route +router.get('/about', function(req, res) { + res.send('Acerca de esta wiki'); +}); + +module.exports = router; +</pre> + +<div class="note"> +<p><strong>Nota:</strong> Agregar rutas al objeto <code>Router</code> es como agregar rutas al objeto <code>app</code> ( como se vio anteriormente).</p> +</div> + +<p>Para usar el router en nuestro archivo app principal, necesitamos <code>require()</code> el módulo de rutas (<strong>wiki.js</strong>), entonces llame <code>use()</code> en la aplicación <em>Express</em> para agregar el Router al software intermediario que maneja las rutas. Las dos rutas serán accesibles entonces desde <code style="font-style: normal; font-weight: normal;">/wiki/</code> y <code style="font-style: normal; font-weight: normal;">/wiki/about/</code>.</p> + +<pre class="brush: js notranslate">var wiki = require('./wiki.js'); +// ... +app.use('/wiki', wiki);</pre> + +<p>Le mostraremos mucho más sobre como trabajar con rutas, y en particular, acerca de como usar el <code>Router</code>, más adelante en la sección<a href="https://developer.mozilla.org/en-US/docs/Learn/Server-side/Express_Nodejs/routes"> Rutas y controladores .</a></p> + +<h3 id="Usando_middleware">Usando middleware</h3> + +<p>El "middleware" es ampliamente utilizado en las aplicaciones de <em>Express:</em> desde tareas para servir archivos estáticos, a la gestión de errores o la compresión de las respuestas HTTP. Mientras las funciones de enrutamiento, con el objeto <a href="http://expressjs.com/en/guide/routing.html#express-router" rel="noopener">express.Router</a>, se encargan del ciclo petición-respuesta, al gestionar la respuesta adecuada al cliente, las funciones de middleware normalmente realizan alguna operación al gestionar una petición o respuesta y a continuación llaman a la siguiente función en la "pila", que puede ser otra función de middleware u otra función de enrutamiento. El orden en el que las funciones de middleware son llamadas depende del desarrollador de la aplicación.</p> + +<div class="note"> +<p><strong>Nota:</strong> El middleware puede realizar cualquier operación: hacer cambios a una petición, ejecutar código, realizar cambios a la petición o al objeto pedido, puede también finalizar el ciclo de petición-respuesta. Si no finaliza el ciclo debe llamar a la función <code>next()</code> para pasar el control de la ejecución a la siguiente función del middleware ( o a la petición quedaría esperando una respuesta ... ). </p> +</div> + +<p>La mayoría de las aplicaciones usan middleware desarrollado por terceras partes, para simplificar funciones habituales en el desarrollo web, como puede ser: gestión de cookies, sesiones, autentificado de usuarios, peticiones <code>POST</code> y datos en JSON, registros de eventos, etc. Puede encontrar en el siguiente enlace una <a href="http://expressjs.com/en/resources/middleware.html">lista de middleware mantenido por el equipo de <em>Express</em></a> (que también incluye otros paquetes populares de terceras partes). Las librerías de <em>Express</em> están disponibles con la aplicación NPM (Node Package Manager).</p> + +<p>Para usar estas colecciones, primero ha de instalar la aplicación usando NPM. Por ejemplo para instalar el registro de peticiones HTTP <a href="http://expressjs.com/en/resources/middleware/morgan.html">morgan</a>, se haría con el comando Bash: </p> + +<pre class="brush: bash notranslate"><code>$ npm install morgan +</code></pre> + +<p>Entonces podría llamar a la función <code>use()</code> en un objeto de aplicación <em>Express</em> para utilizar este middleware a su aplicación. </p> + +<pre class="brush: js notranslate">var express = require('express'); +<strong>var logger = require('morgan');</strong> +var app = express(); +<strong>app.use(logger('dev'));</strong> +...</pre> + +<div class="note"> +<p><strong>Note:</strong> Las funciones Middleware y routing son llamadas en el orden que son declaradas. Para algunos middleware el orden es importante (por ejemplo si el middleware de sesion depende del middleware de cookie, entonces el manejador de cookie tiene que ser llamado antes). Casi siempre es el caso que el middleware es llamado antes de configurar las rutas, o tu manejador de rutas no tendra acceso a la funcionalidad agregada por tu middleware.</p> +</div> + +<p>Tu puedes escribir tu propia funcion middleware, y si quieres hacerlo así (solo para crear código de manejo de error). La única diferencia entre una función middleware y un callback manejador de rutas es que las funciones middleware tienen un tercer argumento <code>next</code>, cuyas funciones middleware son esperadas para llamarlas si ellas no completan el ciclo request (cuando la función midleware es llamada, esta contiene la próxima función que debe ser llamada).</p> + +<p>Puede agregar una función middleware a la cadenan de procesamiento con cualquier <code>app.use()</code> o <code>app.add()</code>, dependiendo de si quiere aplicar el middleware a todas las respuestas o a respuestas con un verbo particular HTTP (<code>GET</code>, <code>POST</code>, etc). Usted especifica rutas, lo mismo en ambos casos, aunque la ruta es opcional cuando llama <strong>app.use()</strong>.</p> + +<p>El ejemplo de abajo muestra como puede agregar la función middleware usando ambos métodos, y con/sin una ruta.</p> + +<pre class="brush: js notranslate">var express = require('express'); +var app = express(); + +// An example middleware function +var a_middleware_function = function(req, res, <em>next</em>) { + // ... perform some operations + next(); // Call next() so Express will call the next middleware function in the chain. +} + +// Function added with use() for all routes and verbs +app.use(a_middleware_function); + +// Function added with use() for a specific route +app.use('/someroute', a_middleware_function); + +// A middleware function added for a specific HTTP verb and route +app.get('/', a_middleware_function); + +app.listen(3000);</pre> + +<div class="note"> +<p><strong>JavaScript Tip:</strong> Arriba declaramos la función middleware separadamente y la configuramos como el callback. En nuestra función previous manejadora de ruta declaramos la función callback cuando esta fué usada. En JavaScript, cuealquer aproximación es valida.</p> +</div> + +<p>La documentación Express tiene mucha mas documentación excelente acerca del uso y escritura de middleware Express.</p> + +<h3 id="Sirviendo_archivos_estáticos">Sirviendo archivos estáticos</h3> + +<p>Puede utilizar el middleware <a href="http://expressjs.com/en/4x/api.html#express.static">express.static</a> para servir archivos estáticos, incluyendo sus imagenes, CSS y JavaScript (<code>static()</code> es la única función middleware que es actualmente <strong>parte</strong> de <em>Express</em>). Por ejemplo, podria utilizar la linea de abajo para servir imágenes, archivos CSS, y archivos JavaScript desde un directorio nombrado '<strong>public'</strong> al mismo nivel desde donde llama a node:</p> + +<pre class="brush: js notranslate">app.use(express.static('public')); +</pre> + +<p>Cualesquiere archivos en el directorio público son servidos al agregar su nombre de archivo (<em>relativo</em> a la ubicación del directorio "público" ) de la ubicación URL. Por ejemplo:</p> + +<pre class="notranslate"><code>http://localhost:3000/images/dog.jpg +http://localhost:3000/css/style.css +http://localhost:3000/js/app.js +http://localhost:3000/about.html +</code></pre> + +<p>Puede llamar <code>static()</code> multiples ocasiones a servir multiples directorios. Si un archivo no puede ser encontrado por una función middleware entonces este simplemente será pasado en la subsequente middleware (el orden en que el middleware está basado en su orden de declaración).</p> + +<pre class="brush: js notranslate">app.use(express.static('public')); +app.use(express.static('media')); +</pre> + +<p>Tambien puede crear un prefijo virtual para sus URLs estáticas, aun más teniendo los archivos agregados en la ubicación URL. Por ejemplo, aqui especificamos <a href="http://expressjs.com/en/4x/api.html#app.use">a mount path</a> tal que los archivos son bajados con el prefijo "/media":</p> + +<pre class="brush: js notranslate">app.use('/media', express.static('public')); +</pre> + +<p>Ahora, puede bajar los archivos que estan en el directorio <code>publico</code> del path con prefijo <code>/media</code>.</p> + +<pre class="notranslate"><code>http://localhost:3000/media/images/dog.jpg +http://localhost:3000/media/video/cat.mp4 +http://localhost:3000/media/cry.mp3</code> +</pre> + +<p>Para más información, ver <a href="Serving static files in Express">Sirviendo archivos estáticos en Express</a>.</p> + +<h3 id="Manejando_errores">Manejando errores</h3> + +<p>Los errores majejados por una o más funciones especiales middleware que tienen cuatro argumentos, en lugar de las usuales tres: <code>(err, req, res, next)</code>. For example:</p> + +<pre class="brush: js notranslate">app.use(function(err, req, res, next) { + console.error(err.stack); + res.status(500).send('Something broke!'); +}); +</pre> + +<p>Estas pueden devolver cualquier contenido, pero deben ser llamadas despues de todas las otras <code>app.use()</code> llamadas de rutas tal que ellas son las últimas middleware en el proceso de manejo de request!</p> + +<p>Express viene con un manejador de error integrado, el que se ocupa de error remanente que pudiera ser encontrado en la app. Esta función middleware manejador de error esta agregada al final del stack de funciones middleware. Si pasa un error a <code>next()</code> y no lo maneja en un manejador de error, este sera manejado por el manejador de error integrado; el error sera escrito en el cliente con el rastreo de pila.</p> + +<div class="note"> +<p><strong>Note:</strong> El rastreo de pila no esta incluido en el ambiente de producción. Para ejecutarlo en modo de producción necesita configurar la variable de ambiente <code>NODE_ENV</code> to '<code>production'</code>.</p> +</div> + +<div class="note"> +<p><strong>Note:</strong> HTTP404 y otros codigos de estatus de "error" no son tratados como errores. Si quiere manejar estos, puede agregar una función middleware para hacerlo. Para mas información vea las <a href="http://expressjs.com/en/starter/faq.html#how-do-i-handle-404-responses">FAQ</a>.</p> +</div> + +<p>Para mayor información vea Manejo de error (Docs. Express).</p> + +<h3 id="Usando_Bases_de_datos">Usando Bases de datos</h3> + +<p>Las apps de <em>Express</em> pueden usar cualquier mecanismo de bases de datos suportadas por <em>Node</em> (<em>Express</em> en sí mismo no define ningúna conducta/requerimiento specifico adicional para administración de bases de datos). Hay muchas opciones, incluyendo PostgreSQL, MySQL, Redis, SQLite, MongoDB, etc.</p> + +<p>Con el propósito de usar éste, debe primero instalar el manejador de bases de datos utilizando NPM. Por ejemplo, para instalar el manejador para el popular NoSQL MongoDB querría utilizar el comando:</p> + +<pre class="brush: bash notranslate"><code>$ npm install mongodb +</code></pre> + +<p>La base de datos por si misma puede ser instalada localmente o en un servidor de la nube. En su codigo Express requiere el manejador, conectarse a la base de datos, y entonces ejecutar operaciones crear, leer, actualizar, y borrar (CLAB). }El ejemplo de abajo (de la documentación Express documentation) muestra como puede encontrar registros en la colección "mamiferos" usando MongoDB.</p> + +<pre class="brush: js notranslate">var MongoClient = require('mongodb').MongoClient; + +MongoClient.connect('mongodb://localhost:27017/animals', function(err, db) { + if (err) throw err; + + db.collection('mammals').find().toArray(function (err, result) { + if (err) throw err; + + console.log(result); + }); +});</pre> + +<p>Otra aproximación popular es acceder a su base de datos indirectamente, via an Mapeo Objeto Relacional ("MOR"). En esta aproximación usted define sus datos como "objetos" o "modelos" y el MOR mapea estos a través del deliniamiento basico de la base de datos. Esta aproximación tiene el beneficio de que como un desrrollador puede continuar pensando en términos de objetos de JavaScript mas que en semántica de bases de datos, y en esto hay un lugar obvio para ejecutar la validación y chequeo de entrada de datos. Hablaremos más de bases de datos en un artículo posterior.</p> + +<p>Para más información ver <a href="https://expressjs.com/en/guide/database-integration.html">Integracion de Bases de Datos</a> (docs Express ).</p> + +<h3 id="Renderización_de_data_vistas">Renderización de data (vistas)</h3> + +<p>El Motor de plantilla (referido como "motor de vistas" por <em>Express</em>) le permite definir la estructura de documento de salida en una plantilla, usando marcadores de posición para datos que seran llenados cuando una pagina es generada. Las plantillas son utilizadas generalmete para crear HTML, pero tambien pueden crear otros tipos de documentos. Express tiene soporte para <a href="https://github.com/expressjs/express/wiki#template-engines">numerosos motores de plantillas</a>, y hay una util comparación de los motores más populares aquí: <a href="https://strongloop.com/strongblog/compare-javascript-templates-jade-mustache-dust/">Comparando Motores de Plantillas de JavaScript: Jade, Mustache, Dust and More</a>.</p> + +<p>En su código de configuración de su aplicación usted configura el motor de plantillas para usar y su localización Express podiría buscar plantillas usando las configuraciones de 'vistas' y 'motores de vistas', mostrado abajo (tendría también que instalar el paquete conteniendo su librería de plantillas!)</p> + +<pre class="brush: js notranslate">var express = require('express'); +var app = express(); + +// Set directory to contain the templates ('views') +app.set('views', path.join(__dirname, 'views')); + +// Set view engine to use, in this case 'some_template_engine_name' +app.set('view engine', 'some_template_engine_name'); +</pre> + +<p>La apariencia de la plantilla dependera de qué motor use. Asumiendo que tiene un archivo de plantillas nombrado "index.<template_extension>" este contiene placeholders para variables de datos nombradas 'title' y "message", podría llamar <code><a href="http://expressjs.com/en/4x/api.html#res.render">Response.render()</a></code> en una función manejadora de rutas para crear y enviar la HTML response:</p> + +<pre class="brush: js notranslate">app.get('/', function(req, res) { + res.render('index', { title: 'About dogs', message: 'Dogs rock!' }); +});</pre> + +<p>Para más información vea <a href="http://expressjs.com/en/guide/using-template-engines.html">Usando motores de plantillas con Express</a> (docs Express ).</p> + +<h3 id="Estructura_de_Archivos">Estructura de Archivos</h3> + +<p>Express no hace asunciones en términos de estructura o que componentes usted usa. Rutas, vistas, archivos estáticos, y otras lógicas de aplicación específica puede vivir en cualquier número de archivos con cualquier estructura de directorio. Mientras que esto es perfectamente posible, se puede tener toda la aplicación en un solo archivo, en <em>Express</em>, tipicamente esto tiene sentido al desplegar su aplicacion dentro de archivos basados en función (e.g. administracion de cuentas, blogs, tableros de discusion) y dominio de problema arquitectonico (e.g. modelo, vista or controlador si tu pasas a estar usando una <a href="/en-US/docs/Web/Apps/Fundamentals/Modern_web_app_architecture/MVC_architecture">arquitectura MVC</a>).</p> + +<p>En un tópico posterior usaremos el Generador de Aplicaciones <em>Express Application Generator</em>, el que crea un esquelo de una app modular que podemos facilmente extender para crear aplicaciones web.</p> + +<ul> +</ul> + +<h2 id="Resumen">Resumen</h2> + +<p><span class="tlid-translation translation" lang="es"><span title="">¡Felicitaciones, ha completado el primer paso en su viaje Express/Node!</span> <span title="">Ahora debes comprender los principales beneficios de Express y Node, y más o menos cómo se verían las partes principales de una aplicación Express (rutas, middleware, manejo de errores y plantillas).</span> <span title="">¡También debe comprender que con Express como un </span></span> framework unopinionated<span class="tlid-translation translation" lang="es"><span title="">, la forma en que une estas partes y las bibliotecas que usa dependen en gran medida de usted!</span><br> + <br> + <span title="">Por supuesto, Express es deliberadamente un un </span></span> framework <span class="tlid-translation translation" lang="es"><span title="">de aplicaciones web muy ligero, por lo que gran parte de sus beneficios y potencial proviene de bibliotecas y características de terceros.</span> <span title="">Lo veremos con más detalle en los siguientes artículos.</span> <span title="">En nuestro próximo artículo, veremos cómo configurar un entorno de desarrollo de Node, para que pueda comenzar a ver código de Express en acción.</span></span></p> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="https://nodejs.org/api/modules.html#modules_modules">Modules</a> (Node API docs)</li> + <li><a href="https://expressjs.com/">Express</a> (home page)</li> + <li><a href="http://expressjs.com/en/starter/basic-routing.html">Basic routing</a> (Express docs)</li> + <li><a href="http://expressjs.com/en/guide/routing.html">Routing guide</a> (Express docs)</li> + <li><a href="http://expressjs.com/en/guide/using-template-engines.html">Using template engines with Express</a> (Express docs)</li> + <li><a href="https://expressjs.com/en/guide/using-middleware.html">Using middleware</a> (Express docs)</li> + <li><a href="http://expressjs.com/en/guide/writing-middleware.html">Writing middleware for use in Express apps</a> (Express docs)</li> + <li><a href="https://expressjs.com/en/guide/database-integration.html">Database integration</a> (Express docs)</li> + <li><a href="Serving static files in Express">Serving static files in Express</a> (Express docs)</li> + <li><a href="http://expressjs.com/en/guide/error-handling.html">Error handling</a> (Express docs)</li> +</ul> + +<div>{{NextMenu("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs")}}</div> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/es/learn/server-side/express_nodejs/mongoose/index.html b/files/es/learn/server-side/express_nodejs/mongoose/index.html new file mode 100644 index 0000000000..f5701c468a --- /dev/null +++ b/files/es/learn/server-side/express_nodejs/mongoose/index.html @@ -0,0 +1,801 @@ +--- +title: 'Express Tutorial 3: Utilizando bases de datos (con Mongoose)' +slug: Learn/Server-side/Express_Nodejs/mongoose +translation_of: Learn/Server-side/Express_Nodejs/mongoose +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary">Este artículo introduce brevemente las bases de datos así como su uso en aplicaciones Node/Express. Despues, profundiza en el uso específico de <a href="http://mongoosejs.com/">Mongoose</a> en el proyecto <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">LocalLibrary</a>. Explica como se declaran y utilizan los esquemas modelo-objeto, los principales campos de datos y su validación básica. También muestra brevemente algunas de las muchas formas para acceder y modificar los datos.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos</th> + <td><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial 2: Creando un esqueleto web</a></td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Ser capaz de crear, diseñar y utilizar bases de datos en Node/Express utilizando Mongoose</td> + </tr> + </tbody> +</table> + +<h2 id="Overview">Overview</h2> + +<p>Library staff will use the Local Library website to store information about books and borrowers, while library members will use it to browse and search for books, find out whether there are any copies available, and then reserve or borrow them. In order to store and retrieve information efficiently, we will store it in a <em>database</em>.</p> + +<p>Las aplicaciones Express pueden utilizar diferentes bases de datos, y existen diferentes aproximaciones que se pueden utilizar para realizar operaciones CRUD (<strong>C</strong>reate, <strong>R</strong>ead, <strong>U</strong>pdate and <strong>D</strong>elete). Este tutorial proporciona una vista general sobre algunas de las opciones disponibles, para a continuación mostrar en detalle los mecanismos elegidos en particular.</p> + +<h3 id="What_databases_can_I_use">What databases can I use?</h3> + +<p><em>Express</em> apps can use any database supported by <em>Node</em> (<em>Express</em> itself doesn't define any specific additional behaviour/requirements for database management). There are <a href="https://expressjs.com/en/guide/database-integration.html">many popular options</a>, including PostgreSQL, MySQL, Redis, SQLite, and MongoDB.</p> + +<p>When choosing a database, you should consider things like time-to-productivity/learning curve, performance, ease of replication/backup, cost, community support, etc. While there is no single "best" database, almost any of the popular solutions should be more than acceptable for a small-to-medium-sized site like our Local Library.</p> + +<p>For more information on the options see: <a href="https://expressjs.com/en/guide/database-integration.html">Database integration</a> (Express docs).</p> + +<h3 id="What_is_the_best_way_to_interact_with_a_database">What is the best way to interact with a database?</h3> + +<p>There are two approaches for interacting with a database: </p> + +<ul> + <li>Using the databases' native query language (e.g. SQL)</li> + <li>Using an Object Data Model ("ODM") / Object Relational Model ("ORM"). An ODM/ORM represents the website's data as JavaScript objects, which are then mapped to the underlying database. Some ORMs are tied to a specific database, while others provide a database-agnostic backend.</li> +</ul> + +<p>The very best <em>performance</em> can be gained by using SQL, or whatever query language is supported by the database. ODM's are often slower because they use translation code to map between objects and the database format, which may not use the most efficient database queries (this is particularly true if the ODM supports different database backends, and must make greater compromises in terms of what database features are supported).</p> + +<p>The benefit of using an ORM is that programmers can continue to think in terms of JavaScript objects rather than database semantics — this is particularly true if you need to work with different databases (on either the same or different websites). They also provide an obvious place to perform validation and checking of data.</p> + +<div class="note"> +<p><strong>Tip:</strong> Using ODM/ORMs often results in lower costs for development and maintenance! Unless you're very familiar with the native query language or performance is paramount, you should strongly consider using an ODM.</p> +</div> + +<h3 id="What_ORMODM_should_I_use">What ORM/ODM should I use?</h3> + +<p>There are many ODM/ORM solutions available on the NPM package manager site (check out the <a href="https://www.npmjs.com/browse/keyword/odm">odm</a> and <a href="https://www.npmjs.com/browse/keyword/orm">orm</a> tags for a subset!).</p> + +<p>A few solutions that were popular at the time of writing are:</p> + +<ul> + <li><a href="https://www.npmjs.com/package/mongoose">Mongoose</a>: Mongoose is a <a href="https://www.mongodb.org/">MongoDB</a> object modeling tool designed to work in an asynchronous environment.</li> + <li><a href="https://www.npmjs.com/package/waterline">Waterline</a>: An ORM extracted from the Express-based <a href="http://sailsjs.com/">Sails</a> web framework. It provides a uniform API for accessing numerous different databases, including Redis, MySQL, LDAP, MongoDB, and Postgres.</li> + <li><a href="https://www.npmjs.com/package/bookshelf">Bookshelf</a>: Features both promise-based and traditional callback interfaces, providing transaction support, eager/nested-eager relation loading, polymorphic associations, and support for one-to-one, one-to-many, and many-to-many relations. Works with PostgreSQL, MySQL, and SQLite3.</li> + <li><a href="https://www.npmjs.com/package/objection">Objection</a>: Makes it as easy as possible to use the full power of SQL and the underlying database engine (supports SQLite3, Postgres, and MySQL).</li> + <li> + <p><a href="https://www.npmjs.com/package/sequelize">Sequelize</a> is a promise-based ORM for Node.js and io.js. It supports the dialects PostgreSQL, MySQL, MariaDB, SQLite and MSSQL and features solid transaction support, relations, read replication and more.</p> + </li> +</ul> + +<p>As a general rule you should consider both the features provided and the "community activity" (downloads, contributions, bug reports, quality of documentation, etc.) when selecting a solution. At time of writing Mongoose is by far the most popular ORM, and is a reasonable choice if you're using MongoDB for your database.</p> + +<h3 id="Using_Mongoose_and_MongoDb_for_the_LocalLibrary">Using Mongoose and MongoDb for the LocalLibrary</h3> + +<p>For the <em>Local Library</em> example (and the rest of this topic) we're going to use the <a href="https://www.npmjs.com/package/mongoose">Mongoose ODM</a> to access our library data. Mongoose acts as a front end to <a href="https://www.mongodb.com/what-is-mongodb">MongoDB</a>, an open source <a href="https://en.wikipedia.org/wiki/NoSQL">NoSQL</a> database that uses a document-oriented data model. A “collection” of “documents”, in a MongoDB database, <a href="https://docs.mongodb.com/manual/core/databases-and-collections/#collections">is analogous to</a> a “table” of “rows” in a relational database.</p> + +<p>This ODM and database combination is extremely popular in the Node community, partially because the document storage and query system looks very much like JSON, and is hence familiar to JavaScript developers.</p> + +<div class="note"> +<p><strong>Tip:</strong> You don't need to know MongoDB in order to use Mongoose, although parts of the <a href="http://mongoosejs.com/docs/guide.html">Mongoose documentation</a> <em>are</em> easier to use and understand if you are already familiar with MongoDB.</p> +</div> + +<p>The rest of this tutorial shows how to define and access the Mongoose schema and models for the <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">LocalLibrary website</a> example.</p> + +<h2 id="Designing_the_LocalLibrary_models">Designing the LocalLibrary models</h2> + +<p>Before you jump in and start coding the models, it's worth taking a few minutes to think about what data we need to store and the relationships between the different objects.</p> + +<p>We know that we need to store information about books (title, summary, author, genre, ISBN) and that we might have multiple copies available (with globally unique ids, availability statuses, etc.). We might need to store more information about the author than just their name, and there might be multiple authors with the same or similar names. We want to be able to sort information based on book title, author, genre, and category.</p> + +<p>When designing your models it makes sense to have separate models for every "object" (group of related information). In this case the obvious objects are books, book instances, and authors.</p> + +<p>You might also want to use models to represent selection-list options (e.g. like a drop down list of choices), rather than hard coding the choices into the website itself — this is recommended when all the options aren't known up front or may change. The obvious candidate for a model of this type is the book genre (e.g. Science Fiction, French Poetry, etc.)</p> + +<p>Once we've decided on our models and fields, we need to think about the relationships between them.</p> + +<p>With that in mind, the UML association diagram below shows the models we'll define in this case (as boxes). As discussed above, we've created models for book (the generic details of the book), book instance (status of specific physical copies of the book available in the system), and author. We have also decided to have a model for genre, so that values can be created dynamically. We've decided not to have a model for the <code>BookInstance:status</code> — we will hard code the acceptable values because we don't expect these to change. Within each of the boxes you can see the model name, the field names and types, and also the methods and their return types.</p> + +<p>The diagram also shows the relationships between the models, including their <em>multiplicities</em>. The multiplicities are the numbers on the diagram showing the numbers (maximum and minimum) of each model that may be present in the relationship. For example, the connecting line between the boxes shows that <code>Book</code> and a <code>Genre</code> are related. The numbers close to the <code>Book</code> model show that a Genre must have zero or more <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">Book</span></font> (as many as you like), while the numbers on the other end of the line next to the <code>Genre</code> show that it can have zero or more associated genre.</p> + +<div class="note"> +<p><strong>Note</strong>: As discussed in our <a href="#related_documents">Mongoose primer</a> below it is often better to have the field that defines the relationship between the documents/models in just <em>one</em> model (you can still find the reverse relationship by searching for the associated <code>_id</code> in the other model). Below we have chosen to define the relationship between Book/Genre and Book/Author in the Book schema, and the relationship between the Book/BookInstance in the BookInstance Schema. This choice was somewhat arbitrary — we could equally well have had the field in the other schema.</p> +</div> + +<p><img alt="Mongoose Library Model with correct cardinality" src="https://mdn.mozillademos.org/files/15645/Library%20Website%20-%20Mongoose_Express.png" style="height: 620px; width: 737px;"></p> + +<div class="note"> +<p><strong>Note</strong>: The next section provides a basic primer explaining how models are defined and used. As you read it, consider how we will construct each of the models in the diagram above.</p> +</div> + +<h2 id="Mongoose_primer">Mongoose primer</h2> + +<p>This section provides an overview of how to connect Mongoose to a MongoDB database, how to define a schema and a model, and how to make basic queries. </p> + +<div class="note"> +<p><strong>Note:</strong> This primer is "heavily influenced" by the <a href="https://www.npmjs.com/package/mongoose">Mongoose quick start</a> on <em>npm</em> and the <a href="http://mongoosejs.com/docs/guide.html">official documentation</a>.</p> +</div> + +<h3 id="Installing_Mongoose_and_MongoDB">Installing Mongoose and MongoDB</h3> + +<p>Mongoose is installed in your project (<strong>package.json</strong>) like any other dependency — using NPM. To install it, use the following command inside your project folder:</p> + +<pre class="brush: bash"><code>npm install mongoose</code> +</pre> + +<p>Installing <em>Mongoose</em> adds all its dependencies, including the MongoDB database driver, but it does not install MongoDB itself. If you want to install a MongoDB server then you can <a href="https://www.mongodb.com/download-center">download installers from here</a> for various operating systems and install it locally. You can also use cloud-based MongoDB instances.</p> + +<div class="note"> +<p><strong>Note:</strong> For this tutorial we'll be using the mLab cloud-based <em>database as a service</em> <a href="https://mlab.com/plans/pricing/">sandbox tier</a> to provide the database. This is suitable for development, and makes sense for the tutorial because it makes "installation" operating system independent (database-as-a-service is also one approach you might well use for your production database).</p> +</div> + +<h3 id="Connecting_to_MongoDB">Connecting to MongoDB</h3> + +<p><em>Mongoose</em> requires a connection to a MongoDB database. You can <code>require()</code> and connect to a locally hosted database with <code>mongoose.connect()</code>, as shown below.</p> + +<pre class="brush: js">//Import the mongoose module +var mongoose = require('mongoose'); + +//Set up default mongoose connection +var mongoDB = 'mongodb://127.0.0.1/my_database'; +mongoose.connect(mongoDB); +// Get Mongoose to use the global promise library +mongoose.Promise = global.Promise; +//Get the default connection +var db = mongoose.connection; + +//Bind connection to error event (to get notification of connection errors) +db.on('error', console.error.bind(console, 'MongoDB connection error:'));</pre> + +<p>You can get the default <code>Connection</code> object with <code>mongoose.connection</code>. Once connected, the open event is fired on the <code>Connection</code> instance.</p> + +<div class="note"> +<p><strong>Tip:</strong> If you need to create additional connections you can use <code>mongoose.createConnection()</code>. This takes the same form of database URI (with host, database, port, options etc.) as <code>connect()</code> and returns a <code>Connection</code> object).</p> +</div> + +<h3 id="Defining_and_creating_models">Defining and creating models</h3> + +<p>Models are <em>defined </em>using the <code>Schema</code> interface. The Schema allows you to define the fields stored in each document along with their validation requirements and default values. In addition, you can define static and instance helper methods to make it easier to work with your data types, and also virtual properties that you can use like any other field, but which aren't actually stored in the database (we'll discuss a bit further below).</p> + +<p>Schemas are then "compiled" into models using the <code>mongoose.model()</code> method. Once you have a model you can use it to find, create, update, and delete objects of the given type.</p> + +<div class="note"> +<p><strong>Note:</strong> Each model maps to a <em>collection</em> of <em>documents</em> in the MongoDB database. The documents will contain the fields/schema types defined in the model <code>Schema</code>.</p> +</div> + +<h4 id="Defining_schemas">Defining schemas</h4> + +<p>The code fragment below shows how you might define a simple schema. First you <code>require()</code> mongoose, then use the Schema constructor to create a new schema instance, defining the various fields inside it in the constructor's object parameter.</p> + +<pre class="brush: js">//Require Mongoose +var mongoose = require('mongoose'); + +//Define a schema +var Schema = mongoose.Schema; + +var SomeModelSchema = new Schema({ + a_string: String, + a_date: Date +}); +</pre> + +<p>In the case above we just have two fields, a string and a date. In the next sections we will show some of the other field types, validation, and other methods.</p> + +<h4 id="Creating_a_model">Creating a model</h4> + +<p>Models are created from schemas using the <code>mongoose.model()</code> method:</p> + +<pre class="brush: js">// Define schema +var Schema = mongoose.Schema; + +var SomeModelSchema = new Schema({ + a_string: String, + a_date: Date +}); + +<strong>// Compile model from schema +var SomeModel = mongoose.model('SomeModel', SomeModelSchema );</strong></pre> + +<p>The first argument is the singular name of the collection that will be created for your model (Mongoose will create the database collection for the above model <em>SomeModel</em> above), and the second argument is the schema you want to use in creating the model.</p> + +<div class="note"> +<p><strong>Note:</strong> Once you've defined your model classes you can use them to create, update, or delete records, and to run queries to get all records or particular subsets of records. We'll show you how to do this in the <a href="#Using_models">Using models</a> section, and when we create our views.</p> +</div> + +<h4 id="Tipos_de_esquema_(campos)">Tipos de esquema (campos)</h4> + +<p>Un esquema puede tener un número de campos arbitrario — cada uno representa un campo en los documentos almacenados en <em>MongoDB</em>. A continuación se muestra un ejemplo de esquema con varios de los tipos de campos más comunes y cómo se declaran.</p> + +<pre class="brush: js">var schema = new Schema( +{ + name: <strong>String</strong>, + binary: <strong>Buffer</strong>, + living: <strong>Boolean</strong>, + updated: { type: <strong>Date</strong>, default: Date.now }, + age: { type: <strong>Number</strong>, min: 18, max: 65, required: true }, + mixed: <strong>Schema.Types.Mixed</strong>, + _someId: <strong>Schema.Types.ObjectId</strong>, + array: <strong>[]</strong>, + ofString: [<strong>String</strong>], // You can also have an array of each of the other types too. + nested: { stuff: { type: <strong>String</strong>, lowercase: true, trim: true } } +})</pre> + +<p>Most of the <a href="http://mongoosejs.com/docs/schematypes.html">SchemaTypes</a> (the descriptors after “type:” or after field names) are self explanatory. The exceptions are:</p> + +<ul> + <li><code>ObjectId</code>: Represents specific instances of a model in the database. For example, a book might use this to represent its author object. This will actually contain the unique ID (<code>_id</code>) for the specified object. We can use the <code>populate()</code> method to pull in the associated information when needed.</li> + <li><a href="http://mongoosejs.com/docs/schematypes.html#mixed">Mixed</a>: An arbitrary schema type.</li> + <li><font face="Consolas, Liberation Mono, Courier, monospace">[]</font>: An array of items. You can perform JavaScript array operations on these models (push, pop, unshift, etc.). The examples above show an array of objects without a specified type and an array of <code>String</code> objects, but you can have an array of any type of object.</li> +</ul> + +<p>The code also shows both ways of declaring a field:</p> + +<ul> + <li>Field <em>name</em> and <em>type</em> as a key-value pair (i.e. as done with fields <code>name</code>, <code>binary </code>and <code>living</code>).</li> + <li>Field <em>name</em> followed by an object defining the <code>type</code>, and any other <em>options</em> for the field. Options include things like: + <ul> + <li>default values.</li> + <li>built-in validators (e.g. max/min values) and custom validation functions.</li> + <li>Whether the field is required</li> + <li>Whether <code>String</code> fields should automatically be set to lowercase, uppercase, or trimmed (e.g. <code>{ type: <strong>String</strong>, lowercase: true, trim: true }</code>)</li> + </ul> + </li> +</ul> + +<p>For more information about options see <a href="http://mongoosejs.com/docs/schematypes.html">SchemaTypes</a> (Mongoose docs).</p> + +<h4 id="Validation">Validation</h4> + +<p>Mongoose provides built-in and custom validators, and synchronous and asynchronous validators. It allows you to specify both the acceptable range or values and the error message for validation failure in all cases.</p> + +<p>The built-in validators include:</p> + +<ul> + <li>All <a href="http://mongoosejs.com/docs/schematypes.html">SchemaTypes</a> have the built-in <a href="http://mongoosejs.com/docs/api.html#schematype_SchemaType-required">required</a> validator. This is used to specify whether the field must be supplied in order to save a document.</li> + <li><a href="http://mongoosejs.com/docs/api.html#schema-number-js">Numbers</a> have <a href="http://mongoosejs.com/docs/api.html#schema_number_SchemaNumber-min">min</a> and <a href="http://mongoosejs.com/docs/api.html#schema_number_SchemaNumber-max">max</a> validators.</li> + <li><a href="http://mongoosejs.com/docs/api.html#schema-string-js">Strings</a> have: + <ul> + <li><a href="http://mongoosejs.com/docs/api.html#schema_string_SchemaString-enum">enum</a>: specifies the set of allowed values for the field.</li> + <li><a href="http://mongoosejs.com/docs/api.html#schema_string_SchemaString-match">match</a>: specifies a regular expression that the string must match.</li> + <li><a href="http://mongoosejs.com/docs/api.html#schema_string_SchemaString-maxlength">maxlength</a> and <a href="http://mongoosejs.com/docs/api.html#schema_string_SchemaString-minlength">minlength</a> for the string.</li> + </ul> + </li> +</ul> + +<p>The example below (slightly modified from the Mongoose documents) shows how you can specify some of the validator types and error messages:</p> + +<pre class="brush: js"><code> + var breakfastSchema = new Schema({ + eggs: { + type: Number, + min: [6, 'Too few eggs'], + max: 12, + required: [true, 'Why no eggs?'] + }, + drink: { + type: String, + enum: ['Coffee', 'Tea', 'Water',] + } + }); +</code></pre> + +<p>For complete information on field validation see <a href="http://mongoosejs.com/docs/validation.html">Validation</a> (Mongoose docs).</p> + +<h4 id="Virtual_properties">Virtual properties</h4> + +<p>Virtual properties are document properties that you can get and set but that do not get persisted to MongoDB. The getters are useful for formatting or combining fields, while setters are useful for de-composing a single value into multiple values for storage. The example in the documentation constructs (and deconstructs) a full name virtual property from a first and last name field, which is easier and cleaner than constructing a full name every time one is used in a template.</p> + +<div class="note"> +<p><strong>Note:</strong> We will use a virtual property in the library to define a unique URL for each model record using a path and the record's <code>_id</code> value.</p> +</div> + +<p>For more information see <a href="http://mongoosejs.com/docs/guide.html#virtuals">Virtuals</a> (Mongoose documentation).</p> + +<h4 id="Methods_and_query_helpers">Methods and query helpers</h4> + +<p>A schema can also have <a href="http://mongoosejs.com/docs/guide.html#methods">instance methods</a>, <a href="http://mongoosejs.com/docs/guide.html#statics">static methods</a>, and <a href="http://mongoosejs.com/docs/guide.html#query-helpers">query helpers</a>. The instance and static methods are similar, but with the obvious difference that an instance method is associated with a particular record and has access to the current object. Query helpers allow you to extend mongoose's <a href="http://mongoosejs.com/docs/queries.html">chainable query builder API</a> (for example, allowing you to add a query "byName" in addition to the <code>find()</code>, <code>findOne()</code> and <code>findById()</code> methods).</p> + +<h3 id="Using_models">Using models</h3> + +<p>Once you've created a schema you can use it to create models. The model represents a collection of documents in the database that you can search, while the model's instances represent individual documents that you can save and retrieve.</p> + +<p>We provide a brief overview below. For more information see: <a href="http://mongoosejs.com/docs/models.html">Models</a> (Mongoose docs).</p> + +<h4 id="Creating_and_modifying_documents">Creating and modifying documents</h4> + +<p>To create a record you can define an instance of the model and then call <code>save()</code>. The examples below assume SomeModel is a model (with a single field "name") that we have created from our schema.</p> + +<pre class="brush: js"><code>// Create an instance of model SomeModel +var awesome_instance = new </code>SomeModel<code>({ name: 'awesome' }); + +// Save the new model instance, passing a callback +awesome_instance.save(function (err) { + if (err) return handleError(err); + // saved! +}); +</code></pre> + +<p>Creation of records (along with updates, deletes, and queries) are asynchronous operations — you supply a callback that is called when the operation completes. The API uses the error-first argument convention, so the first argument for the callback will always be an error value (or null). If the API returns some result, this will be provided as the second argument.</p> + +<p>You can also use <code>create()</code> to define the model instance at the same time as you save it. The callback will return an error for the first argument and the newly-created model instance for the second argument.</p> + +<pre class="brush: js">SomeModel<code>.create({ name: 'also_awesome' }, function (err, awesome_instance) { + if (err) return handleError(err); + // saved! +});</code></pre> + +<p>Every model has an associated connection (this will be the default connection when you use <code>mongoose.model()</code>). You create a new connection and call <code>.model()</code> on it to create the documents on a different database.</p> + +<p>You can access the fields in this new record using the dot syntax, and change the values. You have to call <code>save()</code> or <code>update()</code> to store modified values back to the database.</p> + +<pre class="brush: js">// Access model field values using dot notation +console.log(<code>awesome_instance.name</code>); //should log '<code>also_awesome</code>' + +// Change record by modifying the fields, then calling save(). +<code>awesome_instance</code>.name="New cool name"; +<code>awesome_instance.save(function (err) { + if (err) return handleError(err); // saved! + });</code> +</pre> + +<h4 id="Searching_for_records">Searching for records</h4> + +<p>You can search for records using query methods, specifying the query conditions as a JSON document. The code fragment below shows how you might find all athletes in a database that play tennis, returning just the fields for athlete <em>name</em> and <em>age</em>. Here we just specify one matching field (sport) but you can add more criteria, specify regular expression criteria, or remove the conditions altogether to return all athletes.</p> + +<pre class="brush: js"><code>var Athlete = mongoose.model('Athlete', yourSchema); + +// find all athletes who play tennis, selecting the 'name' and 'age' fields +Athlete.find({ 'sport': 'Tennis' }, 'name age', function (err, athletes) { + if (err) return handleError(err); + // 'athletes' contains the list of athletes that match the criteria. +})</code></pre> + +<p>If you specify a callback, as shown above, the query will execute immediately. The callback will be invoked when the search completes.</p> + +<div class="note"> +<p><strong>Note:</strong> All callbacks in Mongoose use the pattern <code>callback(error, result)</code>. If an error occurs executing the query, the <code>error</code> parameter will contain an error document, and <code>result</code> will be null. If the query is successful, the <code>error</code> parameter will be null, and the <code>result</code> will be populated with the results of the query.</p> +</div> + +<p>If you don't specify a callback then the API will return a variable of type <a href="http://mongoosejs.com/docs/api.html#query-js">Query</a>. You can use this query object to build up your query and then execute it (with a callback) later using the <code>exec()</code> method.</p> + +<pre class="brush: js"><code>// find all athletes that play tennis +var query = Athlete.find({ 'sport': 'Tennis' }); + +// selecting the 'name' and 'age' fields +query.select('name age'); + +// limit our results to 5 items +query.limit(5); + +// sort by age +query.sort({ age: -1 }); + +// execute the query at a later time +query.exec(function (err, athletes) { + if (err) return handleError(err); + // athletes contains an ordered list of 5 athletes who play Tennis +})</code></pre> + +<p>Above we've defined the query conditions in the <code>find()</code> method. We can also do this using a <code>where()</code> function, and we can chain all the parts of our query together using the dot operator (.) rather than adding them separately. The code fragment below is the same as our query above, with an additional condition for the age.</p> + +<pre><code>Athlete. + find(). + where('sport').equals('Tennis'). + where('age').gt(17).lt(50). //Additional where query + limit(5). + sort({ age: -1 }). + select('name age'). + exec(callback); // where callback is the name of our callback function.</code></pre> + +<p>The <a href="http://mongoosejs.com/docs/api.html#query_Query-find">find()</a> method gets all matching records, but often you just want to get one match. The following methods query for a single record:</p> + +<ul> + <li><code><a href="http://mongoosejs.com/docs/api.html#model_Model.findById">findById()</a></code>: Finds the document with the specified <code>id</code> (every document has a unique <code>id</code>).</li> + <li><code><a href="http://mongoosejs.com/docs/api.html#query_Query-findOne">findOne()</a></code>: Finds a single document that matches the specified criteria.</li> + <li><code><a href="http://mongoosejs.com/docs/api.html#model_Model.findByIdAndRemove">findByIdAndRemove()</a></code>, <code><a href="http://mongoosejs.com/docs/api.html#model_Model.findByIdAndUpdate">findByIdAndUpdate()</a></code>, <code><a href="http://mongoosejs.com/docs/api.html#query_Query-findOneAndRemove">findOneAndRemove()</a></code>, <code><a href="http://mongoosejs.com/docs/api.html#query_Query-findOneAndUpdate">findOneAndUpdate()</a></code>: Finds a single document by <code>id</code> or criteria and either update or remove it. These are useful convenience functions for updating and removing records.</li> +</ul> + +<div class="note"> +<p><strong>Note:</strong> There is also a <code><a href="http://mongoosejs.com/docs/api.html#model_Model.count">count()</a></code> method that you can use to get the number of items that match conditions. This is useful if you want to perform a count without actually fetching the records.</p> +</div> + +<p>There is a lot more you can do with queries. For more information see: <a href="http://mongoosejs.com/docs/queries.html">Queries</a> (Mongoose docs).</p> + +<h4 id="Working_with_related_documents_—_population">Working with related documents — population</h4> + +<p>You can create references from one document/model instance to another using the <code>ObjectId</code> schema field, or from one document to many using an array of <code>ObjectIds</code>. The field stores the id of the related model. If you need the actual content of the associated document, you can use the <code><a href="http://mongoosejs.com/docs/api.html#query_Query-populate">populate()</a></code> method in a query to replace the id with the actual data.</p> + +<p>For example, the following schema defines authors and stories. Each author can have multiple stories, which we represent as an array of <code>ObjectId</code>. Each story can have a single author. The "ref" (highlighted in bold below) tells the schema which model can be assigned to this field.</p> + +<pre class="brush: js"><code>var mongoose = require('mongoose') + , Schema = mongoose.Schema + +var authorSchema = Schema({ + name : String, + stories : [{ type: Schema.Types.ObjectId, <strong>ref</strong>: 'Story' }] +}); + +var storySchema = Schema({ + author : { type: Schema.Types.ObjectId, <strong>ref</strong>: 'Author' }, + title : String +}); + +var Story = mongoose.model('Story', storySchema); +var Author = mongoose.model('Author', authorSchema);</code></pre> + +<p>We can save our references to the related document by assigning the <code>_id</code> value. Below we create an author, then a story, and assign the author id to our stories author field.</p> + +<pre class="brush: js"><code>var bob = new Author({ name: 'Bob Smith' }); + +bob.save(function (err) { + if (err) return handleError(err); + + //Bob now exists, so lets create a story + var story = new Story({ + title: "Bob goes sledding", + author: bob._id // assign the _id from the our author Bob. This ID is created by default! + }); + + story.save(function (err) { + if (err) return handleError(err); + // Bob now has his story + }); +});</code></pre> + +<p>Our story document now has an author referenced by the author document's ID. In order to get the author information in our story results we use <code>populate()</code>, as shown below.</p> + +<pre class="brush: js"><code>Story +.findOne({ title: 'Bob goes sledding' }) +.populate('author') //This populates the author id with actual author information! +.exec(function (err, story) { + if (err) return handleError(err); + console.log('The author is %s', story.author.name); + // prints "The author is Bob Smith" +});</code></pre> + +<div class="note"> +<p><strong>Note:</strong> Astute readers will have noted that we added an author to our story, but we didn't do anything to add our story to our author's <code>stories</code> array. How then can we get all stories by a particular author? One way would be to add our author to the stories array, but this would result in us having two places where the information relating authors and stories needs to be maintained.</p> + +<p>A better way is to get the <code>_id</code> of our <em>author</em>, then use <code>find()</code> to search for this in the author field across all stories.</p> + +<pre class="brush: js"><code>Story +.find({ author : bob._id }) +.exec(function (err, stories) { + if (err) return handleError(err); + // returns all stories that have Bob's id as their author. +});</code> +</pre> +</div> + +<p>This is almost everything you need to know about working with related items<em> for this tutorial</em>. For more detailed information see <a href="http://mongoosejs.com/docs/populate.html">Population</a> (Mongoose docs).</p> + +<h3 id="One_schemamodel_per_file">One schema/model per file</h3> + +<p>While you can create schemas and models using any file structure you like, we highly recommend defining each model schema in its own module (file), exporting the method to create the model. This is shown below:</p> + +<pre class="brush: js"><code>// File: ./models/somemodel.js + +//Require Mongoose +var mongoose = require('mongoose'); + +//Define a schema +var Schema = mongoose.Schema; + +var SomeModelSchema = new Schema({ + a_string : String, + a_date : Date, +}); + +<strong>//Export function to create "SomeModel" model class +module.exports = mongoose.model('SomeModel', SomeModelSchema );</strong></code></pre> + +<p>You can then require and use the model immediately in other files. Below we show how you might use it to get all instances of the model.</p> + +<pre class="brush: js"><code>//Create a SomeModel model just by requiring the module +var SomeModel = require('../models/somemodel') + +// Use the SomeModel object (model) to find all SomeModel records +SomeModel.find(callback_function);</code></pre> + +<h2 id="Setting_up_the_MongoDB_database">Setting up the MongoDB database</h2> + +<p>Now that we understand something of what Mongoose can do and how we want to design our models, it's time to start work on the <em>LocalLibrary</em> website. The very first thing we want to do is set up a MongoDb database that we can use to store our library data.</p> + +<p>For this tutorial we're going to use <a href="https://mlab.com/welcome/">mLab</a>'s free cloud-hosted "<a href="https://mlab.com/plans/pricing/">sandbox</a>" database. This database tier is not considered suitable for production websites because it has no redundancy, but it is great for development and prototyping. We're using it here because it is free and easy to set up, and because mLab is a popular <em>database as a service</em> vendor that you might reasonably choose for your production database (other popular choices at the time of writing include <a href="https://www.compose.com/">Compose</a>, <a href="https://scalegrid.io/pricing.html">ScaleGrid</a> and <a href="https://www.mongodb.com/cloud/atlas">MongoDB Atlas</a>).</p> + +<div class="note"> +<p><strong>Note:</strong> If you prefer you can set up a MongoDb database locally by downloading and installing the <a href="https://www.mongodb.com/download-center">appropriate binaries for your system</a>. The rest of the instructions in this article would be similar, except for the database URL you would specify when connecting.</p> +</div> + +<p>You will first need to <a href="https://mlab.com/signup/">create an account</a> with mLab (this is free, and just requires that you enter basic contact details and acknowledge their terms of service). </p> + +<p>After logging in, you'll be taken to the <a href="https://mlab.com/home">home</a> screen:</p> + +<ol> + <li>Click <strong>Create New</strong> in the <em>MongoDB Deployments</em> section.<img alt="" src="https://mdn.mozillademos.org/files/14446/mLabCreateNewDeployment.png" style="height: 415px; width: 1000px;"></li> + <li>This will open the <em>Cloud Provider Selection </em>screen.<br> + <img alt="MLab - screen for new deployment" src="https://mdn.mozillademos.org/files/15661/mLab_new_deployment_form_v2.png" style="height: 931px; width: 1297px;"><br> + + <ul> + <li>Select the SANDBOX (Free) plan from the Plan Type section. </li> + <li>Select any provider from the <em>Cloud Provider </em>section. Different providers offer different regions (displayed below the selected plan type).</li> + <li>Click the <strong>Continue</strong> button.</li> + </ul> + </li> + <li>This will open the <em>Select Region</em> screen. + <p><img alt="Select new region screen" src="https://mdn.mozillademos.org/files/15662/mLab_new_deployment_select_region_v2.png" style="height: 570px; width: 1293px;"></p> + + <ul> + <li> + <p>Select the region closest to you and then <strong>Continue</strong>.</p> + </li> + </ul> + </li> + <li> + <p>This will open the <em>Final Details</em> screen.<br> + <img alt="New deployment database name" src="https://mdn.mozillademos.org/files/15663/mLab_new_deployment_final_details.png" style="height: 569px; width: 1293px;"></p> + + <ul> + <li> + <p>Enter the name for the new database as <code>local_library</code> and then select <strong>Continue</strong>.</p> + </li> + </ul> + </li> + <li> + <p>This will open the <em>Order Confirmation</em> screen.<br> + <img alt="Order confirmation screen" src="https://mdn.mozillademos.org/files/15664/mLab_new_deployment_order_confirmation.png" style="height: 687px; width: 1290px;"></p> + + <ul> + <li> + <p>Click <strong>Submit Order</strong> to create the database.</p> + </li> + </ul> + </li> + <li> + <p>You will be returned to the home screen. Click on the new database you just created to open its details screen. As you can see the database has no collections (data).<br> + <img alt="mLab - Database details screen" src="https://mdn.mozillademos.org/files/15665/mLab_new_deployment_database_details.png" style="height: 700px; width: 1398px;"><br> + <br> + The URL that you need to use to access your database is displayed on the form above (shown for this database circled above). In order to use this you need to create a database user that you can specify in the URL.</p> + </li> + <li>Click the <strong>Users</strong> tab and select the <strong>Add database user</strong> button.</li> + <li>Enter a username and password (twice), and then press <strong>Create</strong>. Do not select <em>Make read only</em>.<br> + <img alt="" src="https://mdn.mozillademos.org/files/14454/mLab_database_users.png" style="height: 204px; width: 600px;"></li> +</ol> + +<p>You have now created the database, and have an URL (with username and password) that can be used to access it. This will look something like: <code>mongodb://your_user_namer:your_password@ds119748.mlab.com:19748/local_library</code>.</p> + +<h2 id="Install_Mongoose">Install Mongoose</h2> + +<p>Open a command prompt and navigate to the directory where you created your <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">skeleton Local Library website</a>. Enter the following command to install Mongoose (and its dependencies) and add it to your <strong>package.json</strong> file, unless you have already done so when reading the <a href="#Installing_Mongoose_and_MongoDB">Mongoose Primer</a> above.</p> + +<pre class="brush: bash">npm install mongoose +</pre> + +<h2 id="Connect_to_MongoDB">Connect to MongoDB</h2> + +<p>Open <strong>/app.js</strong> (in the root of your project) and copy the following text below where you declare the <em>Express application object</em> (after the line <code>var app = express();</code>). Replace the database url string ('<em>insert_your_database_url_here</em>') with the location URL representing your own database (i.e. using the information <a href="#Setting_up_the_MongoDB_database">from mLab</a>).</p> + +<pre class="brush: js">//Set up mongoose connection +var mongoose = require('mongoose'); +var mongoDB = '<em>insert_your_database_url_here</em>'; +mongoose.connect(mongoDB); +mongoose.Promise = global.Promise; +var db = mongoose.connection; +db.on('error', console.error.bind(console, 'MongoDB connection error:'));</pre> + +<p>As discussed <a href="#Connecting_to_MongoDB">in the Mongoose primer above</a>, this code creates the default connection to the database and binds to the error event (so that errors will be printed to the console). </p> + +<h2 id="Defining_the_LocalLibrary_Schema">Defining the LocalLibrary Schema</h2> + +<p>We will define a separate module for each model, as <a href="#One_schemamodel_per_file">discussed above</a>. Start by creating a folder for our models in the project root (<strong>/models</strong>) and then create separate files for each of the models:</p> + +<pre>/express-locallibrary-tutorial //the project root + <strong>/models</strong> + <strong>author.js</strong> + <strong>book.js</strong> + <strong>bookinstance.js</strong> + <strong>genre.js</strong> +</pre> + +<h3 id="Author_model">Author model</h3> + +<p>Copy the <code>Author</code> schema code shown below and paste it into your <strong>./models/author.js</strong> file. The scheme defines an author has having <code>String</code> SchemaTypes for the first and family names, that are required and have a maximum of 100 characters, and <code>Date</code> fields for the date of birth and death.</p> + +<pre class="brush: js">var mongoose = require('mongoose'); + +var Schema = mongoose.Schema; + +var AuthorSchema = new Schema( + { + first_name: {type: String, required: true, max: 100}, + family_name: {type: String, required: true, max: 100}, + date_of_birth: {type: Date}, + date_of_death: {type: Date}, + } +); + +<strong>// Virtual for author's full name +AuthorSchema +.virtual('name') +.get(function () { + return this.family_name + ', ' + this.first_name; +}); + +// Virtual for author's lifespan +AuthorSchema +</strong>.virtual('lifespan') +.get(function () { + return (this.date_of_death.getYear() - this.date_of_birth.getYear()).toString(); +}); + +// Virtual for author's URL +AuthorSchema +.virtual('url') +.get(function () { + return '/catalog/author/' + this._id; +}); + +//Export model +module.exports = mongoose.model('Author', AuthorSchema); + +</pre> + +<p>We've also declared a <a href="#Virtual_properties">virtual</a> for the AuthorSchema named "url" that returns the absolute URL required to get a particular instance of the model — we'll use the property in our templates whenever we need to get a link to a particular author.</p> + +<div class="note"> +<p><strong>Note:</strong> Declaring our URLs as a virtual in the schema is a good idea because then the URL for an item only ever needs to be changed in one place.<br> + At this point, a link using this URL wouldn't work, because we haven't got any routes handling code for individual model instances. We'll set those up in a later article!</p> +</div> + +<p>At the end of the module we export the model.</p> + +<h3 id="Book_model">Book model</h3> + +<p>Copy the <code>Book</code> schema code shown below and paste it into your <strong>./models/book.js</strong> file. Most of this is similar to the author model — we've declared a schema with a number of string fields and a virtual for getting the URL of specific book records, and we've exported the model.</p> + +<pre class="brush: js">var mongoose = require('mongoose'); + +var Schema = mongoose.Schema; + +var BookSchema = new Schema( + { + title: {type: String, required: true}, + <strong> author: {type: Schema.Types.ObjectId, ref: 'Author', required: true},</strong> + summary: {type: String, required: true}, + isbn: {type: String, required: true}, + <strong> genre: [{type: Schema.Types.ObjectId, ref: 'Genre'}]</strong> + } +); + +// Virtual for book's URL +BookSchema +.virtual('url') +.get(function () { + return '/catalog/book/' + this._id; +}); + +//Export model +module.exports = mongoose.model('Book', BookSchema); +</pre> + +<p>The main difference here is that we've created two references to other models:</p> + +<ul> + <li>author is a reference to a single <code>Author</code> model object, and is required.</li> + <li>genre is a reference to an array of <code>Genre</code> model objects. We haven't declared this object yet!</li> +</ul> + +<h3 id="BookInstance_model">BookInstance model</h3> + +<p>Finally, copy the <code>BookInstance</code> schema code shown below and paste it into your <strong>./models/bookinstance.js</strong> file. The <code>BookInstance</code> represents a specific copy of a book that someone might borrow, and includes information about whether the copy is available or on what date it is expected back, "imprint" or version details.</p> + +<pre class="brush: js">var mongoose = require('mongoose'); + +var Schema = mongoose.Schema; + +var BookInstanceSchema = new Schema( + { + book: { type: Schema.Types.ObjectId, ref: 'Book', required: true }, //reference to the associated book + imprint: {type: String, required: true}, + status: {type: String, required: true, <strong>enum: ['Available', 'Maintenance', 'Loaned', 'Reserved']</strong>, <strong>default: 'Maintenance'</strong>}, + due_back: {type: Date, <strong>default: Date.now</strong>} + } +); + +// Virtual for bookinstance's URL +BookInstanceSchema +.virtual('url') +.get(function () { + return '/catalog/bookinstance/' + this._id; +}); + +//Export model +module.exports = mongoose.model('BookInstance', BookInstanceSchema);</pre> + +<p>The new things we show here are the field options:</p> + +<ul> + <li><code>enum</code>: This allows us to set the allowed values of a string. In this case, we use it to specify the availability status of our books (using an enum means that we can prevent mis-spellings and arbitrary values for our status)</li> + <li><code>default</code>: We use default to set the default status for newly created bookinstances to maintenance and the default <code>due_back</code> date to <code>now</code> (note how you can call the Date function when setting the date!)</li> +</ul> + +<p>Everything else should be familiar from our previous schema.</p> + +<h3 id="Genre_model_-_challenge!">Genre model - challenge!</h3> + +<p>Open your <strong>./models/genre.js</strong> file and create a schema for storing genres (the category of book, e.g. whether it is fiction or non-fiction, romance or military history, etc).</p> + +<p>The definition will be very similar to the other models:</p> + +<ul> + <li>The model should have a <code>String</code> SchemaType called <code>name</code> to describe the genre.</li> + <li>This name should be required and have between 3 and 100 characters.</li> + <li>Declare a <a href="#Virtual_properties">virtual</a> for the genre's URL, named <code>url</code>.</li> + <li>Export the model.</li> +</ul> + +<h2 id="Testing_—_create_some_items">Testing — create some items</h2> + +<p>That's it. We now have all models for the site set up!</p> + +<p>In order to test the models (and to create some example books and other items that we can use in our next articles) we'll now run an <em>independent</em> script to create items of each type:</p> + +<ol> + <li>Download (or otherwise create) the file <a href="https://raw.githubusercontent.com/hamishwillee/express-locallibrary-tutorial/master/populatedb.js">populatedb.js</a> inside your <em>express-locallibrary-tutorial</em> directory (in the same level as <code>package.json</code>). + + <div class="note"> + <p><strong>Note:</strong> You don't need to know how <a href="https://raw.githubusercontent.com/hamishwillee/express-locallibrary-tutorial/master/populatedb.js">populatedb.js</a> works; it just adds sample data into the database.</p> + </div> + </li> + <li>Enter the following commands in the project root to install the <em>async</em> module that is required by the script (we'll discuss this in later tutorials, ) + <pre class="brush: bash">npm install async</pre> + </li> + <li>Run the script using node in your command prompt, passing in the URL of your <em>MongoDB</em> database (the same one you replaced the <em>insert_your_database_url_here </em>placeholder with, inside <code>app.js</code> earlier): + <pre class="brush: bash">node populatedb <your mongodb url></pre> + </li> + <li>The script should run through to completion, displaying items as it creates them in the terminal.</li> +</ol> + +<div class="note"> +<p><strong>Tip:</strong> Go to your database on <a href="https://mlab.com/home">mLab</a>. You should now be able to drill down into individual collections of Books, Authors, Genres and BookInstances, and check out individual documents.</p> +</div> + +<h2 id="Summary">Summary</h2> + +<p>In this article, we've learned a bit about databases and ORMs on Node/Express, and a lot about how Mongoose schema and models are defined. We then used this information to design and implement <code>Book</code>, <code>BookInstance</code>, <code>Author</code> and <code>Genre</code> models for the <em>LocalLibrary</em> website.</p> + +<p>Last of all we tested our models by creating a number of instances (using a standalone script). In the next article we'll look at creating some pages to display these objects.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://expressjs.com/en/guide/database-integration.html">Database integration</a> (Express docs)</li> + <li><a href="http://mongoosejs.com/">Mongoose website</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/guide.html">Mongoose Guide</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/validation.html">Validation</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/schematypes.html">Schema Types</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/models.html">Models</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/queries.html">Queries</a> (Mongoose docs)</li> + <li><a href="http://mongoosejs.com/docs/populate.html">Population</a> (Mongoose docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs/routes", "Learn/Server-side/Express_Nodejs")}}</p> + +<p> </p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> + +<p> </p> diff --git a/files/es/learn/server-side/express_nodejs/skeleton_website/index.html b/files/es/learn/server-side/express_nodejs/skeleton_website/index.html new file mode 100644 index 0000000000..b829e52665 --- /dev/null +++ b/files/es/learn/server-side/express_nodejs/skeleton_website/index.html @@ -0,0 +1,502 @@ +--- +title: 'Express Tutorial Part 2: Creating a skeleton website' +slug: Learn/Server-side/Express_Nodejs/skeleton_website +translation_of: Learn/Server-side/Express_Nodejs/skeleton_website +--- +<div>{{LearnSidebar}}</div> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}</p> + +<p class="summary">Este segundo artículo de nuestro <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Tutorial Express</a> muestra cómo puede crear un "esqueleto" para un proyecto de sitio web que luego puede completar con rutas, plantillas/vistas, y llamadas a base de datos especifícas del sitio.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Configurar un entorno de desarrollo de Node</a>. Revise el Tutorial Express.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Poder empezar sus nuevos proyectos web usando el <em>Generador de Aplicaciones Express</em>.</td> + </tr> + </tbody> +</table> + +<h2 id="Visión_General">Visión General</h2> + +<p>Este artículo muestra cómo puede crear un sitio web "esqueleto" usando la herramienta <a href="https://expressjs.com/en/starter/generator.html">Generador de Aplicaciones Express</a>, que luego puede completar con rutas, vistas/plantillas, y llamadas a base de datos especifícas del sitio. En este caso usaremos la herramienta para crear el framework para nuestro <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">website Local Library</a>, al que luego agregaremos todo el código que el sitio necesite. El proceso es extremadamente simple, requiriendo sólo que se invoque el generador en la línea de comandos con un nombre para el nuevo proyecto, opcionalmente especificando también el motor de plantillas y el generador de CSS a utilizar.</p> + +<p><span style="line-height: 1.5;">Las siguientes secciones muestran como puede llamar al generador de aplicaciones, y proporcionan una pequeña explicación sobre las diferentes opciones para vistas y CSS. También explicaremos como está estructurado el esqueleto del sitio web. Al final, mostraremos como puede ejecutar el sitio web para verificar que funciona.</span></p> + +<div class="note"> +<p><span style="line-height: 1.5;"><strong>Nota</strong>: El <em>Generador de Aplicaciones Express</em> no es el único generador para aplicaciones Express, y el proyecto generado no es la única forma viable para estructurar sus archivos y directorios. El sitio generado, sin embargo, tiene una estructura modular que es fácil de extender y comprender. Para informacion sobre una <em>mínima</em> aplicación Express, vea el <a href="https://expressjs.com/en/starter/hello-world.html">Ejemplo Hello world </a> (Express docs).</span></p> +</div> + +<h2 id="Usando_el_generador_de_aplicaciones">Usando el generador de aplicaciones</h2> + +<p>Ya debe haber instalado el generador como parte de <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Configurar un entorno de desarrollo de Node</a>. Como un rápido recordatorio, la herramienta generador se instala para todos los sitios usando el manejador de paquetes NPM, como se muestra:</p> + +<pre class="brush: bash notranslate"><code>npm install express-generator -g</code></pre> + +<p>El generador tiene un número de opciones, las cuales puede observar en la línea de comandos usando el comando <code>--help</code> (o bien <code>-h</code>):</p> + +<pre class="brush: bash notranslate">> express --help + + Usage: express [options] [dir] + + Options: + + -h, --help output usage information + --version output the version number + -e, --ejs add ejs engine support + --pug add pug engine support + --hbs add handlebars engine support + -H, --hogan add hogan.js engine support + -v, --view <engine> add view <engine> support (ejs|hbs|hjs|jade|pug|twig|vash) (defaults to jade) + -c, --css <engine> add stylesheet <engine> support (less|stylus|compass|sass) (defaults to plain css) + --git add .gitignore + -f, --force force on non-empty directory +</pre> + +<p>Simplemente puede especificar <code>express</code> para crear un proyecto dentro del directorio actual usando el motor de plantillas <em>Jade</em> y CSS plano (si especifica un nombre de directorio entonces el proyecto será creado en un subdirectorio con ese nombre).</p> + +<pre class="brush: bash notranslate"><code>express</code></pre> + +<p>También puede seleccionar el motor de plantillas para las vistas usando <code>--view</code> y/o un motor generador de CSS usando <code>--css</code>.</p> + +<div class="note"> +<p><strong>Nota:</strong> Las otras opciones para elegir motores de plantillas (e.g. <code>--hogan</code>, <code>--ejs</code>, <code>--hbs</code> etc.) están descontinuadas. Use <code>--view</code> (o bien<code> -v</code>)!</p> +</div> + +<h3 id="¿Cuál_motor_de_vistas_debo_usar">¿Cuál motor de vistas debo usar?</h3> + +<p>El <em>Generador de Aplicaciones Express</em> le permite configurar un número de populares motores de plantillas, incluyendo <a href="https://www.npmjs.com/package/ejs">EJS</a>, <a href="http://github.com/donpark/hbs">Hbs</a>, <a href="https://pugjs.org/api/getting-started.html">Pug</a> (Jade), <a href="https://www.npmjs.com/package/twig">Twig</a>, y <a href="https://www.npmjs.com/package/vash">Vash</a>, aunque si no se especifica una opcion de vista, selecciona Jade por defecto. Express puede soportar un gran número de motores de plantillas <a href="https://github.com/expressjs/express/wiki#template-engines">aquí una lista</a>.</p> + +<div class="note"> +<p><strong>Nota:</strong> Si quiere usar un motor de plantillas que no es soportado por el generador entonces vea el artículo <a href="https://expressjs.com/en/guide/using-template-engines.html">Usando motores de plantillas con Express</a> (Express docs) y la documentación de su motor de plantillas.</p> +</div> + +<p>Generalmente hablando debe seleccionar un motor de plantillas que le brinde toda la funcionalidad que necesite y le permita ser productivo rápidamente — o en otras palabras, en la misma forma en que selecciona cualquier otro componente. Alguna de las cosas a considerar cuando se comparan motores de plantillas:</p> + +<ul> + <li>Tiempo de productividad — Si su equipo ya tiene experiencia con un lenguaje de plantillas entonces es probable que sean más productivos usando ese lenguaje. Si no, debería considerar la curva de aprendizaje relativa del motor de plantillas candidato. </li> + <li>Popularidad y actividad — Revise la popularidad del motor y si tiene una comunidad activa. Es importante obtener soporte para el motor cuando tenga problemas durante la vida útil del sitio web.</li> + <li>Estilo — Algunos motores de plantillas usan marcas específicas para indicar inserción de contenido dentro del HTML "ordinario", mientras que otros construyen el HTML usando una sintaxis diferente (por ejemplo, usando indentación (sangría) y nombres de bloque).</li> + <li>Tiempo Renderizado/desempeño.</li> + <li>Características — debe considerar si los motores que elija poseen las siguientes características disponibles: + <ul> + <li>Herencia del diseño: Le permite definir una plantilla base y luego "heredar" sólo las partes que desea que sean diferentes para una página particular. Típicamente esto es un mejor enfoque que construir plantillas incluyendo un número de componentes requeridos, contruyéndolas desde cero cada vez. </li> + <li>Soporte para incluir: Le permite construir plantillas incluyendo otras plantillas.</li> + <li>Control consiso de la sintanxis de variables y ciclos.</li> + <li>Habilidad para filtrar valores de variables a nivel de las plantillas (e.g. convertir variables en mayúsculas, o darle formato a una fecha).</li> + <li>Habilidad para generar formatos de salida distintos al HTML (e.g. JSON o XML).</li> + <li>Soporte para operaciones asincrónas y de transmisión.</li> + <li>Pueden ser usadas tanto en el cliente como en el servidor. Si un motor de plantillas puede ser usado del lado del cliente esto da la posibilidad de servir datos y tener todo o la mayoría del renderizado del lado del cliente.</li> + </ul> + </li> +</ul> + +<div class="note"> +<p><strong>Tip:</strong> En Internet hay muchos recursos que le ayudarán a comparar diferentes opciones. </p> +</div> + +<p>Para este proyecto usaremos el motor de plantillas <a href="https://pugjs.org/api/getting-started.html">Pug</a> (este es el recientemente renombrado motor Jade), ya que es de los más populares lenguajes de plantillas Express/JavaScript y es soportado por el generador por defecto.</p> + +<h3 id="¿Cuál_motor_de_hojas_de_estilo_CSS_debería_usar">¿Cuál motor de hojas de estilo CSS debería usar?</h3> + +<p>El <em>Generador de Aplicaciones Express</em> le permite crear un proyecto que puede usar los más comunes motores de hojas de estilos CSS: <a href="http://lesscss.org/">LESS</a>, <a href="http://sass-lang.com/">SASS</a>, <a href="http://compass-style.org/">Compass</a>, <a href="http://stylus-lang.com/">Stylus</a>.</p> + +<div class="note"> +<p><strong>Nota: </strong>CSS tiene algunas limitaciones que dificultan ciertas tareas. Los motores de hojas de estilos CSS le permiten usar una sintaxis más poderosa para definir su CSS, y luego compilar la definición en texto plano para su uso en los navegadores .</p> +</div> + +<p>Como los motores de plantillas, debería usar el motor CSS que le permita a su equipo ser más productivo. Para este proyecto usaremos CSS ordinario (opción por defecto) ya que nuestros requerimientos no son lo suficientemente complicados para justificar el uso de un motor CSS. </p> + +<h3 id="¿Cuál_base_de_datos_debería_usar">¿Cuál base de datos debería usar?</h3> + +<p>El código generado no usa o incluye ninguna base de datos. Las aplicaciones <em>Express</em> pueden usar cualquier <a href="https://expressjs.com/en/guide/database-integration.html">mecanismo de bases de datos</a> soportado por <em>Node</em> (<em>Express</em> por si mismo no define ningún comportamiento o requerimiento para el manejo de bases de datos).</p> + +<p>Discutiremos la integración con una base de datos en un posterior artículo.</p> + +<h2 id="Creando_el_proyecto">Creando el proyecto</h2> + +<p>Para el ejemplo que vamos a crear la app <em>Local Library</em>, crearemos un proyecto llamado <em>express-locallibrary-tutorial usando la librería de plantillas </em><em>Pug</em> y ningún motor CSS.</p> + +<p>Primero navegue a donde quiera crear el proyecto y luego ejecute el <em>Generador de Aplicaciones Express en la línea de comandos como se muestra</em>:</p> + +<pre class="brush: bash notranslate">express express-locallibrary-tutorial --view=pug +</pre> + +<p>El generador creará (y listará) los archivos del proyecto.</p> + +<pre class="brush: bash notranslate"> create : express-locallibrary-tutorial + create : express-locallibrary-tutorial/package.json + create : express-locallibrary-tutorial/app.js + create : express-locallibrary-tutorial/public/images + create : express-locallibrary-tutorial/public + create : express-locallibrary-tutorial/public/stylesheets + create : express-locallibrary-tutorial/public/stylesheets/style.css + create : express-locallibrary-tutorial/public/javascripts + create : express-locallibrary-tutorial/routes + create : express-locallibrary-tutorial/routes/index.js + create : express-locallibrary-tutorial/routes/users.js + create : express-locallibrary-tutorial/views + create : express-locallibrary-tutorial/views/index.pug + create : express-locallibrary-tutorial/views/layout.pug + create : express-locallibrary-tutorial/views/error.pug + create : express-locallibrary-tutorial/bin + create : express-locallibrary-tutorial/bin/www + + install dependencies: + > cd express-locallibrary-tutorial && npm install + + run the app: + > SET DEBUG=express-locallibrary-tutorial:* & npm start</pre> + +<p>Al final de la lista el generador mostrará instrucciones sobre como instalar las dependencias necesarias (mostradas en el archivo <strong>package.json</strong>) y luego como ejecutar la aplicación (las instrucciones anteriores son para windows; en Linux/macOS serán ligeramente diferentes).</p> + +<h2 id="Ejecutando_el_esqueleto_del_sitio_web">Ejecutando el esqueleto del sitio web</h2> + +<p>En este punto tenemos un esqueleto completo de nuestro proyecto. El sitio web no hace mucho actualmente, pero es bueno ejecutarlo para ver como funciona.</p> + +<ol> + <li>Primero instale las dependencias (el comando <code>install</code> recuperará todas las dependencias listadas e el archivo <strong>package.json</strong> del proyecto). + + <pre class="brush: bash notranslate">cd express-locallibrary-tutorial +npm install</pre> + </li> + <li>Luego ejecute la aplicación. + <ul> + <li>En Windows, use este comando: + <pre class="brush: bash notranslate">SET DEBUG=express-locallibrary-tutorial:* & npm start</pre> + </li> + <li>En macOS o Linux, use este comando: + <pre class="brush: bash notranslate">DEBUG=express-locallibrary-tutorial:* npm start +</pre> + </li> + </ul> + </li> + <li>Luego carge en su navegador <a href="http://localhost:3000/">http://localhost:3000/</a> para acceder a la aplicación.</li> +</ol> + +<p>Debería ver una página parecida a esta:</p> + +<p><img alt="Browser for default Express app generator website" src="https://mdn.mozillademos.org/files/14375/ExpressGeneratorSkeletonWebsite.png" style="display: block; height: 403px; margin: 0px auto; width: 576px;"></p> + +<p>Tiene una aplicación Express funcional, ejecutandose en <em>localhost:3000</em>.</p> + +<div class="note"> +<p><strong>Nota:</strong> También podría ejecutar la app usando el comando <code>npm start</code>. Especificado la variable DEBUG como se muestra habilita el logging/debugging por consola. Por ejemplo, cuando visite la página mostrada arriba verá la información de depuración como esta:</p> + +<pre class="brush: bash notranslate">>SET DEBUG=express-locallibrary-tutorial:* & npm start + +> express-locallibrary-tutorial@0.0.0 start D:\express-locallibrary-tutorial +> node ./bin/www + + express-locallibrary-tutorial:server Listening on port 3000 +0ms +GET / 200 288.474 ms - 170 +GET /stylesheets/style.css 200 5.799 ms - 111 +GET /favicon.ico 404 34.134 ms - 1335</pre> +</div> + +<h2 id="Habilite_el_reinicio_del_servidor_cuando_los_archivos_sean_modificados">Habilite el reinicio del servidor cuando los archivos sean modificados</h2> + +<p>Cualquier cambio que le haga a su sitio web Express no será visible hasta que reinicie el servidor. Rapidamente, tener que detener y reiniciar el servidor cada vez que hacemos un cambio, se vuelve irritante, así que es beneficioso tomarse un tiempo y automátizar el reinicio del servidor cuando sea necesario.</p> + +<p>Una de las herramientas más sencillas para este propósito es <a href="https://github.com/remy/nodemon">nodemon</a>. Éste usualmente se instala globalmente (ya que es una "herramienta"), pero aquí lo instalaremos y usaremos localmente como una dependencia de desarrollo, así cualquier desarrollador que esté trabajando con el proyecto lo obtendrá automáticamente cuando instale la aplicación. Use el siguiente comando en el directorio raíz del esqueleto del proyecto:</p> + +<pre class="brush: bash notranslate">npm install --save-dev nodemon</pre> + +<p>Si abre el archivo <strong>package.json</strong> de su proyecto verá una nueva sección con esta dependencia:</p> + +<pre class="brush: json notranslate"> "devDependencies": { + "nodemon": "^1.14.11" + } +</pre> + +<p>Debido a que la herramienta no fue instalada globalmente no podemos ejecutarla desde la línea de comandos (a menos que la agreguemos a la ruta) pero podemos llamarla desde un script NPM porque NPM sabe todo sobre los paquetes instalados. Busque la sección <code>scripts</code> de su package.json. Inicialmente contendrá una línea, la cual comienza con <code>"start"</code>. Actualicela colocando una coma al final de la línea, y agregue la línea <code>"devstart"</code> mostrada abajo:</p> + +<pre class="brush: json notranslate"> "scripts": { + "start": "node ./bin/www"<strong>,</strong> +<strong> "devstart": "nodemon ./bin/www"</strong> + }, +</pre> + +<p>Ahora podemos iniciar el servidor casi exactamente como antes, pero especificando el comando devstart:</p> + +<ul> + <li>En Windows, use este comando: + <pre class="brush: bash notranslate">SET DEBUG=express-locallibrary-tutorial:* & npm <strong>run devstart</strong></pre> + </li> + <li>En macOS or Linux, use este comando: + <pre class="brush: bash notranslate">DEBUG=express-locallibrary-tutorial:* npm <strong>run devstart</strong> +</pre> + </li> +</ul> + +<div class="note"> +<p><strong>Nota:</strong> Ahora si modifica cualquier archivo del proyecto el servidor se reiniciará (o lo puede reiniciar <code>rs</code> en la consola de comandos en cualquier momento). Aún necesitará recargar el navegador para refrescar la página.</p> + +<p>Ahora tendremos que llamar "<code>npm run <em><nombre del script></em></code>" en vez de <code>npm start</code>, porque "start" es actualmente un comando NPM que es mapeado al nombre del script. Podríamos haber reemplazado el comando en el script <em>start</em> pero sólo queremos usar <em>nodemon</em> durante el desarrollo, así que tiene sentido crear un nuevo script para este comando.</p> +</div> + +<h2 id="El_proyecto_generado">El proyecto generado</h2> + +<p>Observemos el proyecto que hemos creado.</p> + +<h3 id="Estructura_del_directorio">Estructura del directorio</h3> + +<p>El proyecto generado, ahora que ha instalado las dependencias, tiene la siguiente estructura de archivos (los archivos son los elementos que <strong>no</strong> están precedidos con "/"). El archivo <strong>package.json</strong> define las dependencias de la aplicación y otra información. También define un script de inicio que es el punto de entrada de la aplicación, el archivo JavaScript <strong>/bin/www</strong>. Éste establece algunos de los manejadores de error de la aplicación y luego carga el archivo <strong>app.js</strong> para que haga el resto del trabajo. Las rutas se almacenan en módulos separados en el directorio <strong>/routes</strong>. las plantillas se almacenan en el directorio /<strong>views</strong>.</p> + +<pre class="notranslate">/express-locallibrary-tutorial + <strong>app.js</strong> + /bin + <strong>www</strong> + <strong>package.json</strong> + /node_modules + [about 4,500 subdirectories and files] + /public + /images + /javascripts + /stylesheets + <strong>style.css</strong> + /routes + <strong>index.js</strong> + <strong>users.js</strong> + /views + <strong>error.pug</strong> + <strong>index.pug</strong> + <strong>layout.pug</strong> + +</pre> + +<p>Las siguientes secciones describen los archivos con más detalle. </p> + +<h3 id="package.json">package.json</h3> + +<p>El archivo <strong>package.json </strong>define las dependencias de la aplicación y otra información: </p> + +<pre class="brush: json notranslate">{ + "name": "express-locallibrary-tutorial", + "version": "0.0.0", + "private": true, + "scripts": { + "start": "node ./bin/www", + "devstart": "nodemon ./bin/www" + }, + "dependencies": { + "body-parser": "~1.18.2", + "cookie-parser": "~1.4.3", + "debug": "~2.6.9", + "express": "~4.16.2", + "morgan": "~1.9.0", + "pug": "~2.0.0-rc.4", + "serve-favicon": "~2.4.5" + }, + "devDependencies": { + "nodemon": "^1.14.11" + } +} +</pre> + +<p>Las dependencias incluyen el paquete <em>express</em> y los paquetes para el motor de plantillas elegido (<em>pug</em>). Adicionalmente, tenemos los siguientes paquetes que son útiles en muchas aplicaciones web: </p> + +<ul> + <li><a href="https://www.npmjs.com/package/body-parser">body-parser</a>: Esto analiza la parte del cuerpo de una solicitud HTTP entrante y facilita la extracción de diferentes partes de la información contenida. Por ejemplo, puede usar esto para leer los parámetros POST.</li> + <li><a href="https://www.npmjs.com/package/cookie-parser">cookie-parser</a>: Se utiliza para analizar el encabezado de la cookie y rellenar req.cookies (esencialmente proporciona un método conveniente para acceder a la información de la cookie).</li> + <li><a href="https://www.npmjs.com/package/debug">debug</a>: Una pequeña utilidad de depuración de node modelada a partir de la técnica de depuración del núcleo de node.</li> + <li><a href="https://www.npmjs.com/package/morgan">morgan</a>: Un middleware registrador de solicitudes HTTP para node.</li> + <li><a href="https://www.npmjs.com/package/serve-favicon">serve-favicon</a>: Middleware de node para servir un favicon (este es el icono utilizado para representar el sitio dentro de la pestaña del navegador, marcadores, etc.).</li> +</ul> + +<p class="brush: bash">La sección de scripts define un script de "<em>start</em>", que es lo que invocamos cuando llamamos a npm start para iniciar el servidor. Desde la definición del script, puede ver que esto realmente inicia el archivo JavaScript <strong>./bin/www </strong>con <em>node</em>. También define un script "<em>devstart</em>", que invocamos cuando llamamos a npm run devstart en su lugar. Esto inicia el mismo archivo <strong>./bin/www</strong>, pero con <em>nodemon</em> en lugar de node.</p> + +<pre class="brush: json notranslate"> "scripts": { + "start": "node ./bin/www", + "devstart": "nodemon ./bin/www" + }, +</pre> + +<h3 id="www_file">www file</h3> + +<p>El archivo <strong>/bin/www</strong> es el punto de entrada de la aplicación. Lo primero que hace es require () el punto de entrada de la aplicación "real" (<strong>app.js</strong>, en la raíz del proyecto) que configura y devuelve el objeto de la aplicación express ().</p> + +<pre class="brush: js notranslate">#!/usr/bin/env node + +/** + * Module dependencies. + */ + +<strong>var app = require('../app');</strong> +</pre> + +<div class="note"> +<p><strong>Note:</strong> <code>require()</code> es una función de node global que se usa para importar módulos en el archivo actual. Aquí especificamos el módulo app.js utilizando una ruta relativa y omitiendo la extensión de archivo opcional (.js).</p> +</div> + +<p>El resto del código en este archivo configura un servidor HTTP de node con la aplicación configurada en un puerto específico (definido en una variable de entorno o 3000 si la variable no está definida), y comienza a escuchar e informar errores y conexiones del servidor. Por ahora no necesita saber nada más sobre el código (todo en este archivo es "repetitivo"), pero siéntase libre de revisarlo si está interesado.</p> + +<h3 id="app.js">app.js</h3> + +<p>Este archivo crea un objeto de aplicación rápida (aplicación denominada, por convención), configura la aplicación con varias configuraciones y middleware, y luego exporta la aplicación desde el módulo. El siguiente código muestra solo las partes del archivo que crean y exportan el objeto de la aplicación:</p> + +<pre class="brush: js notranslate"><code>var express = require('express'); +var app = express(); +... +</code>module.exports = app; +</pre> + +<p>De vuelta en el archivo de punto de entrada <strong>www</strong> anterior, es este objeto module.exports que se proporciona al llamante cuando se importa este archivo.</p> + +<p>Permite trabajar a través del archivo <strong>app.js </strong>en detalle. Primero importamos algunas bibliotecas de node útiles en el archivo usando require (), incluyendo <em>express</em>, <em>serve-favicon</em>, <em>morgan</em>, <em>cookie-parser</em> y <em>body-parser</em> que previamente descargamos para nuestra aplicación usando NPM; y <em>path</em>, que es una biblioteca central de nodos para analizar rutas de archivos y directorios.</p> + +<pre class="brush: js notranslate">var express = require('express'); +var path = require('path'); +var favicon = require('serve-favicon'); +var logger = require('morgan'); +var cookieParser = require('cookie-parser'); +var bodyParser = require('body-parser'); +</pre> + +<p>Luego require () modules de nuestro directorio de rutas. Estos modules/files contienen código para manejar conjuntos particulares de "routes" relacionadas (rutas URL). Cuando extendemos la aplicación esqueleto, por ejemplo, para enumerar todos los libros de la biblioteca, agregaremos un nuevo archivo para tratar las rutas relacionadas con los libros.</p> + +<pre class="brush: js notranslate">var index = require('./routes/index'); +var users = require('./routes/users'); +</pre> + +<div class="note"> +<p><strong>Note:</strong> En este punto, acabamos de importar el módulo; aún no hemos utilizado sus rutas (esto sucede un poco más abajo en el archivo).</p> +</div> + +<p>Next we create the <code>app</code> object using our imported <em>express</em> module, and then use it to set up the view (template) engine. There are two parts to setting up the engine. First we set the '<code>views</code>' value to specify the folder where the templates will be stored (in this case the sub folder <strong>/views</strong>). Then we set the '<code>view engine</code>' value to specify the template library (in this case "pug").</p> + +<pre class="brush: js notranslate">var app = express(); + +// view engine setup +app.set('views', path.join(__dirname, 'views')); +app.set('view engine', 'pug'); +</pre> + +<p>The next set of functions call <code>app.use()</code> to add the <em>middleware</em> libraries into the request handling chain. In addition to the 3rd party libraries we imported previously, we use the <code>express.static</code> middleware to get <em>Express</em> to serve all the static files in the <strong>/public</strong> directory in the project root.</p> + +<pre class="brush: js notranslate">// uncomment after placing your favicon in /public +//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); +app.use(logger('dev')); +app.use(bodyParser.json()); +app.use(bodyParser.urlencoded({ extended: false })); +app.use(cookieParser()); +<strong>app.use(express.static(path.join(__dirname, 'public')));</strong> +</pre> + +<p>Now that all the other middleware is set up, we add our (previously imported) route-handling code to the request handling chain. The imported code will define particular routes for the different <em>parts</em> of the site:</p> + +<pre class="brush: js notranslate">app.use('/', index); +app.use('/users', users); +</pre> + +<div class="note"> +<p><strong>Note:</strong> The paths specified above ('/' and '<code>/users'</code>) are treated as a prefix to routes defined in the imported files. So for example if the imported <strong>users</strong> module defines a route for <code>/profile</code>, you would access that route at <code>/users/profile</code>. We'll talk more about routes in a later article.</p> +</div> + +<p id="error_handling">The last middleware in the file adds handler methods for errors and HTTP 404 responses.</p> + +<pre class="brush: js notranslate">// catch 404 and forward to error handler +app.use(function(req, res, next) { + var err = new Error('Not Found'); + err.status = 404; + next(err); +}); + +// error handler +app.use(function(err, req, res, next) { + // set locals, only providing error in development + res.locals.message = err.message; + res.locals.error = req.app.get('env') === 'development' ? err : {}; + + // render the error page + res.status(err.status || 500); + res.render('error'); +}); +</pre> + +<p>The Express application object (app) is now fully configured. The last step is to add it to the module exports (this is what allows it to be imported by <strong>/bin/www</strong>).</p> + +<pre class="brush: js notranslate">module.exports = app;</pre> + +<h3 id="Routes">Routes</h3> + +<p>The route file <strong>/routes/users.js</strong> is shown below (route files share a similar structure, so we don't need to also show <strong>index.js</strong>). First it loads the <em>express</em> module, and uses it to get an <code>express.Router</code> object. Then it specifies a route on that object, and lastly exports the router from the module (this is what allows the file to be imported into <strong>app.js</strong>).</p> + +<pre class="brush: js notranslate">var express = require('express'); +var router = express.Router(); + +/* GET users listing. */ +<strong>router.get('/', function(req, res, next) { + res.send('respond with a resource'); +});</strong> + +module.exports = router; +</pre> + +<p>The route defines a callback that will be invoked whenever an HTTP <code>GET</code> request with the correct pattern is detected. The matching pattern is the route specified when the module is imported ('<code>/users</code>') plus whatever is defined in this file ('<code>/</code>'). In other words, this route will be used when an URL of <code>/users/</code> is received.</p> + +<div class="note"> +<p><strong>Tip:</strong> Try this out by running the server with node and visiting the URL in your browser: <a href="http://localhost:3000/users/">http://localhost:3000/users/</a>. You should see a message: 'respond with a resource'.</p> +</div> + +<p>One thing of interest above is that the callback function has the third argument '<code>next</code>', and is hence a middleware function rather than a simple route callback. While the code doesn't currently use the <code>next</code> argument, it may be useful in the future if you want to add multiple route handlers to the <code>'/'</code> route path.</p> + +<h3 id="Views_templates">Views (templates)</h3> + +<p>The views (templates) are stored in the <strong>/views</strong> directory (as specified in <strong>app.js</strong>) and are given the file extension <strong>.pug</strong>. The method <code><a href="http://expressjs.com/en/4x/api.html#res.render">Response.render()</a></code> is used to render a specified template along with the values of named variables passed in an object, and then send the result as a response. In the code below from <strong>/routes/index.js</strong> you can see how that route renders a response using the template "index" passing the template variable "title".</p> + +<pre class="brush: js notranslate">/* GET home page. */ +router.get('/', function(req, res) { + res.render('index', { title: 'Express' }); +}); +</pre> + +<p>The corresponding template for the above route is given below (<strong>index.pug</strong>). We'll talk more about the syntax later. All you need to know for now is that the <code>title</code> variable (with value <code>'Express'</code>) is inserted where specified in the template.</p> + +<pre class="notranslate">extends layout + +block content + h1= title + p Welcome to #{title} +</pre> + +<h2 id="Challenge_yourself">Challenge yourself</h2> + +<p>Create a new route in <strong>/routes/users.js</strong> that will display the text "<em>You're so cool"</em> at URL <code>/users/cool/</code>. Test it by running the server and visiting <a href="http://localhost:3000/users/cool/">http://localhost:3000/users/cool/</a> in your browser</p> + +<ul> +</ul> + +<h2 id="Summary">Summary</h2> + +<p>You have now created a skeleton website project for the <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Local Library</a> and verified that it runs using <em>node</em>. Most important, you also understand how the project is structured, so you have a good idea where we need to make changes to add routes and views for our local library.</p> + +<p>Next we'll start modifying the skeleton so that works as a library website.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://expressjs.com/en/starter/generator.html">Express application generator</a> (Express docs)</li> + <li><a href="https://expressjs.com/en/guide/using-template-engines.html">Using template engines with Express</a> (Express docs)</li> +</ul> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/Tutorial_local_library_website", "Learn/Server-side/Express_Nodejs/mongoose", "Learn/Server-side/Express_Nodejs")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/es/learn/server-side/express_nodejs/tutorial_local_library_website/index.html b/files/es/learn/server-side/express_nodejs/tutorial_local_library_website/index.html new file mode 100644 index 0000000000..825cc0c8c0 --- /dev/null +++ b/files/es/learn/server-side/express_nodejs/tutorial_local_library_website/index.html @@ -0,0 +1,83 @@ +--- +title: 'Express Tutorial: The Local Library website' +slug: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +translation_of: Learn/Server-side/Express_Nodejs/Tutorial_local_library_website +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}</div> + +<p class="summary"><span id="result_box" lang="es"><span>El primer artículo de nuestra serie de tutoriales prácticos explica lo que aprenderá y proporciona una descripción general del sitio web de ejemplo de la "biblioteca local" en el que trabajaremos y evolucionaremos en artículos posteriores.</span></span></p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Leer la <a href="/es/docs/Learn/Server-side/Express_Nodejs/Introduction">Introducción a Express</a>. <span id="result_box" lang="es"><span>Para los siguientes artículos, también deberá haber </span></span><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">configurado un entorno de desarrollo de Node</a>. </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td><span id="result_box" lang="es"><span>Presentar la aplicación de ejemplo utilizada en este tutorial, y permitir a los lectores comprender qué temas se tratarán.</span></span></td> + </tr> + </tbody> +</table> + +<h2 id="Visión_General">Visión General</h2> + +<p><span id="result_box" lang="es"><span>Bienvenido al tutorial de MDN "Biblioteca Local" </span></span><span lang="es"><span>Express (Node), en el cual desarrollamos un sitio web que podría usarse para administrar el catálogo de una biblioteca local.</span><br> + <br> + <span>En esta serie de artículos tutoriales, usted:</span></span></p> + +<ul> + <li><span lang="es"><span>Usará la herramienta </span></span><em>Express Application Generator</em><span lang="es"><span> para crear un sitio web esquemático y una aplicación. </span></span></li> + <li><span lang="es"><span>Iniciará y detendrá el servidor web Node</span></span>.</li> + <li><span lang="es"><span>Usará una base de datos para almacenar los datos de la aplicación</span></span>.</li> + <li><span lang="es"><span>Creará rutas para solicitar diferente información y plantillas ("vistas") para representar los datos como HTML para que se muestren en el navegador</span></span></li> + <li><span lang="es"><span>Trabajará con formularios</span></span></li> + <li><span lang="es"><span>Implementará su aplicación en producción</span></span></li> +</ul> + +<p><span id="result_box" lang="es"><span>Ya se ha aprendido sobre algunos de estos temas y se ha referido brevemente a otros.</span> <span>Al final de la serie de tutoriales, debe saber lo suficiente como para desarrollar aplicaciones Express simples usted mismo.</span></span></p> + +<h2 id="The_LocalLibrary_website">The LocalLibrary website</h2> + +<p><em>LocalLibrary</em> es el nombre del website que vamos a desarrollar en esta serie de tutoriales. Tal como esperas, el objetivo del website es proveer un catalogo online para una pequeña libreria, donde los usuarios exploren los libros disponibles y administren sus cuentas.</p> + +<p>Este ejemplo ha sido cuidadosamente elegido porque puede escalarse para mostrar tantos o pocos detalles como necesitemos, de igual forma puede usarse para presentar casi todas las caracteristicas de Express. Mas importante aún, nos permite proporcionar una ruta guiada a traves de la funcionalidad que necesita cualquier sitio web:</p> + +<ul> + <li>En los primeros articulos definiremos una biblioteca simple, <em>unicamente de navegacion, </em>que los miembros de la biblioteca usaran para saber que libros estan disponibles. Esto permite explorar las operationes mas comunes de los sitios web: lectura y presentacion de contenido de una base de datos.</li> + <li>A medida que avancemos, el ejemplo de la biblioteca se extenderá naturalmente para mostrar las caracteristicas mas avanzadas del sitio web. Por ejemplo, podemos extender la biblioteca para que se creen nuevos libros, de esta manera conoceremos como usar los formularios (forms) y la autenticacion de usuarios.</li> +</ul> + +<p>Aunque este ejemplo se puede extender mucho mas, se llama LocalLibrary por una razón , esperamos mostrar informacion minima que le ayudara a comenzar a utilizar Express rapidamente. Como resultado, almacenaremos informacion acerca de libros, copias de libros, autores y otra informacion clave. Sin embargo, no almacenaremos informacion sobre otros elementos que una biblioteca pueda tener, o proveer la infraestructura necesaria para soportar multiples sitios u otras caracteristicas de grandes bibliotecas. </p> + +<h2 id="Estoy_atascado_donde_puedo_obtener_el_codigo_fuente">Estoy atascado, donde puedo obtener el codigo fuente?</h2> + +<p>A medida que avance, le proporcionaremos los fragmentos de codigo adecuado para que usted los copie y pegue en cada punto, ademas, habrá otro código con el proposito de que usted lo complete para afianzar su conocimiento (con alguna orientacion).</p> + +<p>Si aun asi sigues atasaco, puedes encontrar la version completamente desarrollada del sitio web <a href="https://github.com/mdn/express-locallibrary-tutorial">en Github aqui</a>.</p> + +<div class="note"> +<p><strong>Note:</strong> Las versiones especificas de node, Express, y los otros modulos con los que se probó esta documentación estan enumeradas en el projecto <a href="https://github.com/mdn/express-locallibrary-tutorial/blob/master/package.json">package.json</a>.</p> +</div> + +<h2 id="Summary">Summary</h2> + +<p>Ahora que sabes un poco mas del sitio web <em>LocalLIbrary</em> y lo que vas a aprender, es tiempo de comenzar a crear un <a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">skeleton project</a>o para contener nuestro ejemplo.</p> + +<p>{{PreviousMenuNext("Learn/Server-side/Express_Nodejs/development_environment", "Learn/Server-side/Express_Nodejs/skeleton_website", "Learn/Server-side/Express_Nodejs")}}</p> + +<h2 id="In_this_module">In this module</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Introduction">Express/Node introduction</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/development_environment">Setting up a Node (Express) development environment</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Tutorial_local_library_website">Express Tutorial: The Local Library website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/skeleton_website">Express Tutorial Part 2: Creating a skeleton website</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/mongoose">Express Tutorial Part 3: Using a Database (with Mongoose)</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/routes">Express Tutorial Part 4: Routes and controllers</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/Displaying_data">Express Tutorial Part 5: Displaying library data</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/forms">Express Tutorial Part 6: Working with forms</a></li> + <li><a href="/en-US/docs/Learn/Server-side/Express_Nodejs/deployment">Express Tutorial Part 7: Deploying to production</a></li> +</ul> diff --git a/files/es/learn/server-side/index.html b/files/es/learn/server-side/index.html new file mode 100644 index 0000000000..e22f39084f --- /dev/null +++ b/files/es/learn/server-side/index.html @@ -0,0 +1,57 @@ +--- +title: Programación lado servidor +slug: Learn/Server-side +tags: + - Aprendizaje + - Aterrizaje + - Codificación de scripts + - Principiante + - Programación lado servidor + - Servidor + - Tema + - introducción +translation_of: Learn/Server-side +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">El tema<strong><em> Páginas Dinámicas </em></strong>–<em><strong> Programación lado servidor </strong></em>contiene una serie de módulos en los que se enseña como crear sitios web dinámicos, sitios que entregan información personalizada como respuesta a las peticiones HTTP. El modulo ofrece una introducción generica a la programación de lado servidor además de guías para principiantes sobre como usar frameworks como Django (Python) y Express(Node.js/JavaScript) para crear aplicaciones web basicas.</p> + +<p>La mayoría de los principales sitios web utilizan alguna forma de tecnología de lado servidor para presentar dinámicamente datos cuando sean requeridos. Por ejemplo, imagina cuántos productos están disponibles en Amazon e imagina cuántas entradas han sido escritas en Facebook. Presentar todo esto usando páginas estáticas completamente diferentes sería completamente ineficiente, por lo que estos sitios en lugar de ello presentan plantillas estáticas (construidas usando <a href="/en-US/docs/Learn/HTML">HTML</a>, <a href="/en-US/docs/Learn/CSS">CSS</a>, y <a href="/en-US/docs/Learn/JavaScript">JavaScript</a>), y actualizan dinámicamente los datos presentados dentro de esas plantillas cuando se necesiten, ej. cuando quieres ver un producto diferente en Amazon.</p> + +<p>En el mundo moderno del desarrollo web, el aprendizaje del desarrollo de lado servidor es altamente recomendado.</p> + +<h2 id="Itinerario_de_aprendizaje">Itinerario de aprendizaje</h2> + +<p>Empezar con la programación lado servidor es normalmente más fácil que con el desarrollo del lado cliente, ya que los sitios web dinámicos tienden a efectuar un montón de operaciones muy similares (recuperar datos de una base y presentarlos en una página, validar datos introducidos por los usuarios y guardarlos en la base, comprobar los permisos e inicios de sesión de los usuarios, etc.), y se construyen usando web frameworks que hacen muy facilmente éstas y otras operaciones comunes en un servidor web.</p> + +<p>Un conocimiento básico de conceptos de programación (o de un lenguaje de programación en particular) es útil, pero no imprescindible. Igualmente, no hace falta ser un experto en codificación lado cliente, pero un conocimiento básico te ayudará a trabajar mejor con los desarrolladores creando tu "front-end" de web lado cliente.</p> + +<p>Necesitarás entender "cómo tabaja la web". Te recomendamos que leas primero los siguientes temas:</p> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_web_server">¿Qué es un servidor web?</a></li> + <li><a href="/en-US/docs/Learn/Common_questions/What_software_do_I_need">¿Qué software necesito para construir un sitio web?</a></li> + <li><a href="/en-US/docs/Learn/Common_questions/Upload_files_to_a_web_server">¿Cómo subo ficheros a un servidor web?</a></li> +</ul> + +<p>Con ese conocimiento básico estarás preparado para recorrer el camino a través de los módulos de esta sección.</p> + +<h2 id="Módulos">Módulos</h2> + +<p>Este tema contiene los siguientes módulos. Deberías comenzar por el primer módulo y a continuación ir a uno de los módulos siguientes, que muestran cómo trabajar con dos lenguajes muy populares de lado servidor usando los web frameworks adecuados.</p> + +<dl> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos">Primeros pasos en la programación lado servidor de sitios web</a></dt> + <dd>Este módulo proporciona información acerca de la programación lado servidor de sitios web sin adentrarse en la tecnología de los servidores, incluyendo respuestas a las preguntas a cuestiones fundamentales acerca de la programación de lado servidor — "¿qué es?", "¿en qué se diferencia de la programación de lado cliente?" y "¿porqué es tan útil?" — y una visión general de algunos de los web frameworks de lado servidor más populares e indicaciones de cómo seleccionar el más adecuado para tu sitio. Finalmente proporcionaremos una sección de introducción a la seguridad en servidores web.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Django">Django Web Framework (Python)</a></dt> + <dd>Django es un web framework extremadamete popular y con funcionalidad completa, escrito en Python. El módulo explica porqué Django es tan buen framework de servidor web, cómo configurar un entorno de desarrollo y cómo realizar tareas comunes con él.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Express_Nodejs">Express Web Framework (Node.js/JavaScript)</a></dt> + <dd>Express es un web framework popular, escrito en JavaScript y hospedado dentro del entorno de ejecución en tiempo real "node.js". El módulo explica algunos de los beneficios clave de este framework, cómo configurar tu entorno de desarrollo y cómo realizar tareas comunes de desarrollo y despliegue web.</dd> +</dl> + +<h2 id="Ver_también">Ver también</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Node_server_without_framework">Node servidor sin framework</a></dt> + <dd>Este artículo proporciona un servidor de ficheros estático, construido con Node.js puro, para aquellos de vosotros que no os apetezca usar un framework.</dd> +</dl> diff --git a/files/es/learn/server-side/node_server_without_framework/index.html b/files/es/learn/server-side/node_server_without_framework/index.html new file mode 100644 index 0000000000..11826d3e73 --- /dev/null +++ b/files/es/learn/server-side/node_server_without_framework/index.html @@ -0,0 +1,81 @@ +--- +title: Servidor Node sin framework +slug: Learn/Server-side/Node_server_without_framework +translation_of: Learn/Server-side/Node_server_without_framework +--- +<div>{{LearnSidebar}}</div> + +<p class="summary">Este artículo proporciona un servidor de ficheros estático simple construido con Node.js puro, para aquellos de vosotros que no quieran usar un framework.</p> + +<p><a href="https://nodejs.org/en/">NodeJS</a> has many frameworks to help you get your server up and running, the most popular being:</p> + +<ul> + <li><a href="http://expressjs.com/">Express</a>: The most used framework.</li> + <li><a href="https://www.totaljs.com/">Total</a>: The all-in-one Node.js framework that has everything and does not depend on any other framework or module.</li> +</ul> + +<p>There is however not a solution that will suit every situation. A developer may need to build his/her own server, without any other dependency.</p> + +<h2 id="Example">Example</h2> + +<p>Below is a simple static file server built with NodeJS:</p> + +<pre class="brush: js">var http = require('http'); +var fs = require('fs'); +var path = require('path'); + +http.createServer(function (request, response) { + console.log('request ', request.url); + + var filePath = '.' + request.url; + if (filePath == './') { + filePath = './index.html'; + } + + var extname = String(path.extname(filePath)).toLowerCase(); + var contentType = 'text/html'; + var mimeTypes = { + '.html': 'text/html', + '.js': 'text/javascript', + '.css': 'text/css', + '.json': 'application/json', + '.png': 'image/png', + '.jpg': 'image/jpg', + '.gif': 'image/gif', + '.wav': 'audio/wav', + '.mp4': 'video/mp4', + '.woff': 'application/font-woff', + '.ttf': 'application/font-ttf', + '.eot': 'application/vnd.ms-fontobject', + '.otf': 'application/font-otf', + '.svg': 'application/image/svg+xml' + }; + + contentType = mimeTypes[extname] || 'application/octet-stream'; + + fs.readFile(filePath, function(error, content) { + if (error) { + if(error.code == 'ENOENT'){ + fs.readFile('./404.html', function(error, content) { + response.writeHead(200, { 'Content-Type': contentType }); + response.end(content, 'utf-8'); + }); + } + else { + response.writeHead(500); + response.end('Sorry, check with the site admin for error: '+error.code+' ..\n'); + response.end(); + } + } + else { + response.writeHead(200, { 'Content-Type': contentType }); + response.end(content, 'utf-8'); + } + }); + +}).listen(8125); +console.log('Server running at http://127.0.0.1:8125/');</pre> + +<h2 id="To_do">To do</h2> + +<p>It would be nice to extend this article to explain how the above code works, and perhaps also show an extended version that serves static files and also handles some kind of dynamic requests too.</p> diff --git a/files/es/learn/server-side/primeros_pasos/index.html b/files/es/learn/server-side/primeros_pasos/index.html new file mode 100644 index 0000000000..19a5454b4b --- /dev/null +++ b/files/es/learn/server-side/primeros_pasos/index.html @@ -0,0 +1,47 @@ +--- +title: Primeros Pasos en la Programación de Lado-Servidor +slug: Learn/Server-side/Primeros_pasos +tags: + - Aprendizaje + - Aterrizaje + - Codificación de scripts + - Guía + - Principiante + - Programación lado servidor + - introducción +translation_of: Learn/Server-side/First_steps +--- +<div>{{LearnSidebar}}</div> + +<p>En este, nuestro módulo sobre programación de Lado-Servidor, contestaremos a unas pocas preguntas fundamentales - "¿Qué es?", "¿En qué se diferencia de la programación de Lado-Cliente?" y "¿Porqué es tan útil?". Proporcionaremos un vistazo de algunos de los "web-frameworks" de lado-servidor más populares, junto con indicaciones de cómo seleccionar el framework más adecuado para crear tu primer sitio. Finalmente proporcionaremos un artículo introductorio de alto nivel sobre seguridad en el servidor web. </p> + +<h2 id="Prerequisitos">Prerequisitos</h2> + +<p>Antes de comenzar este módulo no necesitas tener ningún conocimiento de programación de sitios web de lado-servidor, y tampoco de ningún otro tipo de programación.</p> + +<p>Necesitarás entender "cómo funciona la web". Te recomendamos que leas primero los siguientes temas:</p> + +<ul> + <li><a href="/en-US/docs/Learn/Common_questions/What_is_a_web_server">Qué es un servidor web</a></li> + <li><a href="/en-US/docs/Learn/Common_questions/What_software_do_I_need">¿Qué software necesito para construir un sitio web?</a></li> + <li><a href="/en-US/docs/Learn/Common_questions/Upload_files_to_a_web_server">¿Cómo se suben los ficheros a un servidor web?</a></li> +</ul> + +<p>Con este conocimiento básico estarás listo para recorrer el camino a través de los módulos de esta sección.</p> + +<h2 id="Guías">Guías</h2> + +<dl> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Introducci%C3%B3n">Introducción al lado servidor</a></dt> + <dd>¡Bienvenidos al curso MDN de programación para principiantes de lado servidor! En este primer artículo enfocamos la programación de Lado-Servidor desde un nivel alto, respondiendo a preguntas tales como "¿qué es?", "¿en qué se diferencia de la programación de Lado-Cliente?" y "¿porqué es tan útil?". Después de leer este artículo entenderás el poder adicional para los sitios web <span style='background-color: transparent; color: #333333; display: inline !important; float: none; font-family: "Open Sans",arial,x-locale-body,sans-serif; font-size: 16px; font-style: normal; font-variant: normal; font-weight: 400; letter-spacing: normal; text-align: left; text-decoration: none; text-indent: 0px; text-transform: none; white-space: normal;'>disponible </span>a través de la codificación lado-servidor.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Vision_General_Cliente_Servidor">Visión general Cliente-Servidor</a></dt> + <dd>Ahora que conoces el propósito y beneficios potenciales de la programación lado-servidor examinaremos en detalle qué pasa cuando un servidor recibe una "petición dinámica" desde un explorador web. Como el código de lado-servidor de la mayoría de sitios web gestiona las peticiones y las respuestas de forma similar, ésto te ayudará entender qué necesitas hacer cuando escribes tu propio código.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Web_frameworks">Web frameworks de lado-servidor</a></dt> + <dd>El anterior artículo te mostró lo que necesita una aplicación web de lado servidor para responder a las peticiones de un explorador web. Ahora te mostraremos cómo los web frameworks pueden simplificar estas tareas y ayudarte a seleccionar el framework correcto para tu primera aplicación web de lado servidor.</dd> + <dt><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/seguridad_sitios_web">Seguridad de Sitios Web</a></dt> + <dd>La seguridad de los sitios web requiere vigilancia en todos los aspectos del diseño y uso del sitio . Este artículo introductorio no te convertirá en un gurú de la seguridad de sitios web, pero te ayudará a entender los primeros pasos importantes que deber dar para robustecer tu aplicación web contra las amenazas más comunes.</dd> +</dl> + +<h2 id="Evaluaciones">Evaluaciones</h2> + +<p>Este módulo "visión general" no hace ninguna evaluación ya que no te hemos enseñado ningún código todavía. Esperamos que en este punto tengas una comprensión de qué clase de funcionalidad puedes distribuir usando programación de lado servidor y habrás tomado una decisión sobre el web framework de lado servidor que usarás para crear tu primer sitio. </p> diff --git a/files/es/learn/server-side/primeros_pasos/introducción/index.html b/files/es/learn/server-side/primeros_pasos/introducción/index.html new file mode 100644 index 0000000000..0b0d2da59e --- /dev/null +++ b/files/es/learn/server-side/primeros_pasos/introducción/index.html @@ -0,0 +1,192 @@ +--- +title: Introducción al lado servidor +slug: Learn/Server-side/Primeros_pasos/Introducción +tags: + - Aprendizaje + - Codificación de scripts + - Guía + - Principiante + - Programación lado servidor + - Servidor + - introducción +translation_of: Learn/Server-side/First_steps/Introduction +--- +<div>{{LearnSidebar}}</div> + +<div>{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}</div> + +<p class="summary">¡Bienvenidos al curso MDN de programación para principiantes de lado servidor! En este primer artículo enfocamos la programación de Lado-Servidor desde un nivel alto, respondiendo a preguntas tales como "¿qué es?", "¿en qué se diferencia de la programación de Lado-Cliente?" y "¿porqué es tan útil?". Después de leer este artículo entenderás el poder adicional para los sitios web disponible a través de la codificación lado-servidor.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Nociones básicas de computación. Entender lo que es un servidor web.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Familiarizarse con lo que es la programación de lado servidor, qué puede hacer y en qué se diferencia de la programación de lado cliente.</td> + </tr> + </tbody> +</table> + +<p>La mayoría de los grandes sitios web usan código de lado servidor para presentar, cuando se necesitan, diferentes datos, generalmente extraidos de una base de datos almacenada en un servidor y enviada al cliente para ser presentada mediante algún código (ej, HTML y JavaScript). Quizá el beneficio más significativo de la codificación de lado servidor es que te permite confeccionar el contenido del sitio web para usuarios individuales. Los sitios dinámicos pueden resaltar contenido que es más relevante basándose en las preferencias del usuario y sus hábitos. Puede hacer también que los sitios sean más fáciles de usar al almacenar las preferencias personales y la información - por ejemplo reusando los detalles de la tarjeta de crédito guardados para agilizar los pagos siguientes. Puede incluso permitir la interacción con los usuarios fuera del sitio, enviando notificaciones y actualizaciones via email o a traves de otros canales. Todas estas capacidades permite un mayor compromiso con los usuarios. </p> + +<p>En el mundo moderno del desarrollo web, el aprendizaje sobre desarrollo de lado servidor es altamente recomendable.</p> + +<h2 id="¿Qué_es_la_programación_de_sitios_web_de_lado_servidor">¿Qué es la programación de sitios web de lado servidor?</h2> + +<p>Los exploradores web se comunican con los <a href="/es-ES/docs/Learn/Common_questions/What_is_a_web_server">servidores web</a> usando el Protocolo de Transporte de Hyper Texto (HyperText Transport Protocol ({{glossary("HTTP")}}). Cuando pinchas en un enlace en una página web, envías un formulario o ejecutas una búsqueda, se envía una peticion HTTP desde tu explorador web al servidor web de destino. La petición incluye un URL que identifica el recurso afectado, un método que define la acción requerida (por ejemplo, obtener, borrar o publicar el recurso), y puede incluir información adicional codificada en parámetros en el URL (los pares campo-valor enviados en una cadena de consulta (<a href="https://en.wikipedia.org/wiki/Query_string">query string</a>), como datos POST (datos enviados mediate el método POST de HTTP, <a href="/es/docs/Web/HTTP/Methods/POST">HTTP POST method</a>), o en {{glossary("Cookie", "associated cookies")}}.</p> + +<p>Los servidores web esperan los mensajes de petición de los clientes, los procesan cuando llegan y responden al explorador web con un mensaje de respuesta HTTP. La repuesta contiene una línea de estado indicando si la petición ha tenido éxito o no (ej, "HTTP/1.1 200 OK" en caso de éxito). El cuerpo de una respuesta exitosa a una petición podría contener el resurso solicitado (ej, una nueva página HTML, o una imagen, etc...), que el explorador web podría presetar en pantalla.</p> + +<h3 id="Sitios_Estáticos">Sitios Estáticos</h3> + +<p>El diagrama de abajo muestra una arquitectura de servidor web básica correspondiente a un <em>sitio estático</em> (un sitio estático es aquél que devuelve desde el servidor el mismo contenido insertado en el código "hard coded" siempre que se solicita un recurso en particular). Cuando un usuario quiere navegar a una página, el explorador envía una petición HTTP "GET" especificando su URL. El servidor recupera de su sistema de ficheros el documento solicitado y devuelve una respuesta HTTP que contiene el documento y un <a href="/es/docs/Web/HTTP/Status#Successful_responses">estado de éxito "success status</a>" (normalmente 200 OK). Si el fichero no puede ser recuperado por alguna razón, se devuelve un estado de error (ver <a href="/es/docs/Web/HTTP/Status#Client_error_responses">respuestas de error del cliente</a> and <a href="/es/docs/Web/HTTP/Status#Server_error_responses">respuestas de error del servidor</a>).</p> + +<p><img alt="A simplified diagram of a static web server." src="https://mdn.mozillademos.org/files/13841/Basic%20Static%20App%20Server.png" style="height: 223px; width: 800px;"></p> + +<h3 id="Sitios_Dinámicos">Sitios Dinámicos</h3> + +<p>Un sitio dinámico es aquél en que algun contenido de la respuesta está generado <em>dinámicamente</em> sólo cuando se necesita. En un sitio web dinámico las páginas HTML se crean normalmente insertando datos desde una base en variables dentro de plantillas HTML (esta es una forma mucho más eficiente de almacenar gran cantidad de contenido que la que usan los sitios web estáticos). Un sitio dinámico puede devolver datos diferentes para un URL basados en la información proporcionada por el usuario o sus preferencias almacenadas y puede realizar otras operaciones como parte de la devolución de respuesta (ej, enviar notificaciones).</p> + +<p>La mayor parte del código para soportar un sitio web dinámico debe correr en el servidor. La creación de este código se conoce como "programación de lado-servidor" (o algunas veces "back-end scripting").</p> + +<p>El diagrama de abajo muestra una arquitectura simple para un<em>sitio web dinámico.</em> Como en el diagrama previo, los exploradores web envían peticiones HTTP al servidor, el servidor procesa a continuación las peticiones y devuelve las respuestas HTTP apropiadas. Las peticiones de recursos <em>estáticos</em> son gestionadas de la misma manera que para los <em>sitios estáticos</em> (los recursos estáticos son cualquier fichero que no cambia - generalmente: CSS, JavaScript, Imágenes, ficheros PDF creados previamente, etc...)</p> + +<p><img alt="A simplified diagram of a web server that uses server-side programming to get information from a database and construct HTML from templates. This is the same diagram as is in the Client-Server overview." src="https://mdn.mozillademos.org/files/13839/Web%20Application%20with%20HTML%20and%20Steps.png"></p> + +<p>Las peticiones de recursos dinámicos, por el contrario, son reenviadas (2) al código del lado-servidor (mostrado en el diagrama como <em>Web Application</em>). Para las "peticiones dinámicas" el servidor interpreta la petición, lee de la base de datos la información requerida (3), combina los datos recuperados con las plantillas HTML (4), y envía de vuelta una respuesta que contiene el HTML generado (5,6). </p> + +<div> +<h2 id="¿Son_iguales_la_programación_del_lado-servidor_y_lado-cliente">¿Son iguales la programación del lado-servidor y lado-cliente?</h2> +</div> + +<p>Prestemos ahora nuestra atención al código involucrado en la programación de lado-servidor y lado-cliente. En cada caso, el código es significativamente diferente:</p> + +<ul> + <li>Tienen diferentes propósitos y preocupaciones.</li> + <li>Por lo general no usan los mismos lenguajes de programación (siendo la excepción el JavaScript, que puede usarse tanto en lado servidor como en lado cliente).</li> + <li>Se ejecutan entornos de diferentes sistemas operativos.</li> +</ul> + +<p>El código que se ejecuta en el explorador se conoce como código de lado-cliente, y su principal preocupación es la mejora de la apariencia y el comportamiento de una página web entregada. Esto incluye la selección y estilo de los componentes UI, la creación de layouts, navegación, validación de formularios, etc. Por otro lado, la programación de sitios web de lado servidor en su mayor parte implica la elección de <em>qué contenido</em> se ha de devolver al explorador como respuesta a sus peticiones. El código de lado-servidor gestiona tareas como la validación de los datos enviados y las peticiones, usando bases de datos para almacenar y recuperar datos, y enviando los datos correctos al cliente según se requiera.</p> + +<p>El código del lado cliente está escrito usando <a href="/es/docs/Learn/HTML">HTML</a>, <a href="/es/docs/Learn/CSS">CSS</a>, y <a href="/es/docs/Learn/JavaScript">JavaScript</a> — es ejecutado dentro del explorador web y tiene poco o ningún acceso al sistema operativo subyacente (incluyendo un acceso limitado al sistema de ficheros).</p> + +<p>Los desarrolladores web no pueden controlar qué explorador web usará cada usuario para visualizar un sitio web — los exploradores web proporcionan niveles de compatibilidad inconsistentes con las características de codificación lado cliente, y parte del reto de la programación de lado cliente es gestionar con dignidad las diferencias de soporte entre exploradores.</p> + +<div>El código del lado servidor puede escribirse en cualquier número de lenguajes de programación — ejemplos de lenguajes de programación populares incluyen PHP, Python, Ruby, C# y NodeJS(JavaScript). El código del lado servidor tiene acceso completo al sistema operativo del servidor y el desarrollador puede elegir qué lenguaje de programación (y qué versión específica) desea usar.</div> + +<div>Los desarrolladores generalmente escriben su código usando web frameworks. Los web framworks son colecciones de funciones, objetos, reglas y otras construcciones de código diseñadas para resolver problemas comunes, acelerar el desarrollo y simplificar los diferentes tipos de tareas que se han de abordar en un dominio en particular.</div> + +<div>De nuevo, mientras que, tanto el código lado cliente y el lado servidor usan frameworks, los dominios son muy diferentes, y por lo tanto también lo son los frameworks. Los frameworks del lado cliente simplifican los diseños y las tareas de presentación mientras que los del lado servidor proporcionan un montón de funcionalidades "comunes" que tendría que haber implementado uno mismo (ej, soporte para las sesiones, soporte para los usuarios y autenticación, acceso fácil a la base de datos, librerías de plantillas, etc...).</div> + +<div class="note"> +<p>Nota: Los frameworks del lado cliente se usan con frecuencia para acelerar el desarrollo del código del lado cliente, pero también se puede elegir escribir todo el código a mano; de hecho, escribir el código a mano puede ser más rápido y más eficiente si sólo se necesita una UI para sitio web pequeña y simple. Por contra, casi nunca se consideraría escribir el componente del lado servidor de una aplicación web ("web app") sin un framework — implementar una característica vital como un servidor HTTP es realmente difícil de hacer de la nada en un lenguaje como, por ejemplo, Python, pero los web frameworks de Python como Django proporcionan uno listo para usar, junto con otras herramientas muy útiles.</p> +</div> + +<h2 id="¿Qué_se_puede_hacer_en_el_lado-servidor">¿Qué se puede hacer en el lado-servidor?</h2> + +<p>La programación del lado-servidor es muy útil porque nos permite distribuir <em>eficientemente</em> información a medida para usuarios individuales y por lo tanto crear una experiencia de usuario mucho mejor.</p> + +<p>Compañías como Amazon utilizan la programación del lado-servidor para construir resultados de búsquedas de productos, hacer sugerencias sobre productos escogidos basados en las preferencias del cliente y sus hábitos de compra previos, simplificar las adquisiciones, etc. Los bancos usan la programación del lado-servidor para almacenar la información sobre las cuentas y permitir ver y realizar transacciones sólo a los usuarios autorizados. Otros servicios como Facebook, Twitter, Instagram y Wikipedia usan la programación de lado-servidor para destacar, compartir y controlar el acceso al contenido interesante.</p> + +<p>Algunos de los usos y beneficios comunes de la programación de lado-servidor se lista debajo. Notarás que hay algo de solapamiento.</p> + +<h3 id="Almacenaje_y_distribución_eficiente_de_información">Almacenaje y distribución eficiente de información</h3> + +<p>Imagina cuántos productos están disponibles en Amazon, e imagina cuántas entradas se han escrito en Facebook. Crear una página estática separada para cada producto o entrada sería completamente ineficiente.</p> + +<p>La programación de lado-servidor nos permite por el contrario almacenar la información en una base de datos y construir dinámicamente y devolver ficheros HTML y de otros tipos (ej, PDFs, imágenes, etc.). También es posible devolver simplemente datos ({{glossary("JSON")}}, {{glossary("XML")}}, etc.) para presentar mediante los web frameworks adecuados del lado-cliente (esto reduce la carga de procesamiento del servidor y la cantidad de datos que se necesitan enviar).</p> + +<p>El servidor no se limita a enviar información de las bases de datos, y podría además devolver el resultado de herramientas de software o datos de servicios de comunicación. El contenido puede incluso ser dirigido por el tipo de dispositivo cliente que lo está recibiendo.</p> + +<p>Debido a que la información está en una base de datos, puede también ser compartida y actualizada con otros sistemas de negocio (por ejemplo, cuando se venden los productos online o en una tienda, la tienda debería actualizar su base de datos de inventario.</p> + +<div class="note"> +<p>Nota: Tu imaginación no tiene que trabajar duro para ver el beneficio de la codificación de lado-servidor para el almacenaje y distribución de información:</p> + +<ol> + <li>Vete a <a href="https://www.amazon.com">Amazon</a> o a cualquier otro sitio de comercio electrónico "e-commerce".</li> + <li>Busca por un número de palabras clave y nota como la estructura de la página no cambia, incluso aunque cambien los resultados. </li> + <li>Abre dos o tres productos diferentes. Fíjate de nuevo como tienen una estructura y diseño común, pero el contenido para los diferentes productos ha sido extraido de la base de datos.</li> +</ol> + +<p>Para un término de búsqueda común (digamos "pez") puedes ver literalmente millones de valores retornados. Usar una base de datos permite que éstos sean almacenados y compartidos de forma eficiente, y permite que la presentación de la información esté controlada en un solo sitio.</p> +</div> + +<h3 id="Experiencia_de_usuario_personalizada">Experiencia de usuario personalizada</h3> + +<p>Los servidores pueden almacenar y usar la información acerca de los clientes para proporcionar una experiencia de usuario conveniente y dirigida. Por ejemplo, muchos usuarios almacenan tarjetas de crédito de forma que los detalles no tienen que ser introducidos de nuevo. Sitios como Google Maps usan la localización de tu casa y la actual para proporcionar una información sobre la ruta a seguir y resaltar los negocios locales en los resultados de búsqueda.</p> + +<p>Un análisis profundo de los hábitos del usuario se puede usar para anticipar sus intereses y personalizar las respuestas y notificaciones futuras, proporcionando, por ejemplo, una lista de las localizaciones visitadas o populares que querrías buscar en un mapa.</p> + +<div class="note"> +<p>Nota: Vete a <a href="https://maps.google.com/">Google Maps</a> como usuario anónimo, selecciona el botón Direcciones, e introduce los puntos de partida y destino de un viaje. Ahora inicia sesión en el sistema con tu cuenta de Google, si tienes una (en el panel de abajo aparece información acerca de este proceso donde seleccionas direcciones). El sitio web te permitirá ahora seleccionar las localizaciones de casa y trabajo como puntos de partida y destino (o almacenar estos detalles si no lo has hecho así).</p> +</div> + +<h3 id="Acceso_controlado_al_contenido">Acceso controlado al contenido </h3> + +<p>La programación de lado-servidor permite a los sitios restringir el acceso a usuarios autorizados y servir sólo la información que se le permite ver al usuario.</p> + +<p>Ejemplos del mundo real incluyen:</p> + +<ul> + <li>Redes sociales como Facebook permiten a los usuarios controlar totalmente sus propios datos pero permitiendo sólo a sus amigos ver o comentar sobre ellos. El usuario determina quien puede ver sus datos, y por extensión, los datos de quienes aparecen en sus notificaciones — autorización es una parte central de la experiencia de usuario!</li> + <li> + <p>El sitio en el que te encuentras ahora controla el acceso al contenido: los artículos son visibles a todos, pero sólo los usuarios que se han identificado pueden editar el contenido. Para comprobar ésto, pincha en el botón Edit en la parte superior de esta página — si te has identificado iniciando sesión se te mostrará la vista de edición; si no has iniciado sesión serás enviado a una página de registro.</p> + </li> +</ul> + +<div class="note"> +<p>Nota: Considera otros ejemplos reales donde el acceso al contenido está controlado. Por ejemplo, ¿qué puedes ver si vas al sitio online de tu banco? Inicia sesión con tu cuenta — ¿qué información adicional puedes ver y modificar? ¿Qué información puedes ver y sólo el banco puede cambiar?</p> +</div> + +<h3 id="Almacenar_información_de_sesiónestado">Almacenar información de sesión/estado</h3> + +<p>La programación de lado-servidor permite a los desarrolladores hacer uso de las sesiones — es básicamente un mecanismo que permite al servidor almacenar información sobre el usuario actual del sitio u enviar diferentes respuestas basadas en esa información. Esto permite, por ejemplo, que un sitio sepa que un usuario ha iniciado sesión previamente y presente enlaces a sus correos, o a su historial de órdenes, o quizá guardar el estado de un simple juego de forma que el usuario pueda volver al sitio de nuevo y retomar el juego donde lo dejó.</p> + +<div class="note"> +<p>Nota: Visita el sitio de un periódico que tenga un modelo de subscripción y abre un puñado de pestañas (ej, <a href="http://www.theage.com.au/">The Age</a>). Continua visitando el sitio durante unos pocos días/horas. En algún momento serás finalmente redirigido a las páginas que explican cómo suscribirte y se te impedirá el acceso a los artículos. Esta información es un ejemplo de información de sesión almacenada en cookies.</p> +</div> + +<h3 id="Notificaciones_y_comunicación">Notificaciones y comunicación</h3> + +<p>Los servidores pueden enviar notificaciones de tipo general o específicas de usuario a través del propio sitio web o vía correo electrónico, SMS, mensajería instanténea, conversaciones de video u otros servicios de comunicación.</p> + +<p>Unos pocos ejemplos incluyen:</p> + +<ul> + <li>Facebook y Twitter envían mensajes de correoy SMS para notificarte de nuevas comunicaciones.</li> + <li>Amazon envía con regularidad emails que sugieren productos similares a aquellos comprados o vistos anteriormente y en los que podrías estar interesado.</li> + <li>Un servidor web podría enviar mensajes de aviso a los administradores del sistema alertandoles de memoria baja en el servidor o de actividades de usuario sospechosas.</li> +</ul> + +<div class="note"> +<p>Nota: El tipo de notificación más común es una "confirmación de registro". Elige uno cualquiera de los grandes sitios en que estés interesado (Google, Amazon, Instagram, etc.) y crea una cuenta nueva usando tu dirección de correo. En breve recibirás un email de confirmación de registro, o solicitando un acuse de recibo para activar la cuenta.</p> +</div> + +<h3 id="Análisis_de_datos">Análisis de datos</h3> + +<p>Un sitio web puede recolectar un montón de datos acerca de los usuarios: qué es lo que buscan, qué compran, qué recomiendan, cuánto tiempo permanecen en cada página. La programación de lado-servidor puede utilizarse para refinar las respuestas basándose en el análisis de estos datos.</p> + +<p>Por ejemplo, Amazon y Google anuncian ambos productos basados en búsquedas previas (y adquisiciones).</p> + +<div class="note"> +<p>Nota: Si eres usuario de Facebook vete a tu muro y hecha un ojo a la ristra de entradas. Fíjate como algunas de las entradas no están en orden numérico - en particular las entradas con más "me-gusta" están con frecuencia en lugares más altos de la lista que las entradas más recientes. Echa un ojo también a qué clase de anuncios te están mostrando — podrías ver anuncios de cosas que has mirado en otros sitios. El algoritmo de Facebook para resaltar contenido y anuncios puede ser un poco misterioso, pero está claro que lo que hace depende de lo que te gusta y de tus hábitos de visualización!</p> +</div> + +<h2 id="Sumario">Sumario</h2> + +<p>Felicidades, has alcanzado el final de primer artículo sobre programación de lado-servidor. </p> + +<p>Ahora ya has aprendido que el código de lado-servidor se ejecuta en un servidor web y que su papel principal es controlar <em>qué </em>información se envía al usuario (mientras que el código de lado-cliente gestiona principalmente la estructura y presentación de esos datos al usuario).</p> + +<p>También deberías comprender que es útil porque nos permite crear sitios web que distribuyen <em>de forma eficiente</em> información seleccionada dirigida a usuarios individuales y tener una buena idea de algunas de las cosas que podrías ser capaz de hacer cuando seas un programador de lado-servidor.</p> + +<p>Finalmente, deberías comprender que el código de lado-servidor se puede escribir en un gran número de lenguajes de programación y que deberías usar un web framework para hacer más fácil el proceso completo.</p> + +<p>En un artículo futuro te ayudaremos a escoger el mejor web framework para tu primer sitio; Aunque a continuación te llevaremos a través de las principales interacciones cliente-servidor en un poco más de detalle.</p> + +<p>{{NextMenu("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps")}}</p> diff --git a/files/es/learn/server-side/primeros_pasos/seguridad_sitios_web/index.html b/files/es/learn/server-side/primeros_pasos/seguridad_sitios_web/index.html new file mode 100644 index 0000000000..c2630fc050 --- /dev/null +++ b/files/es/learn/server-side/primeros_pasos/seguridad_sitios_web/index.html @@ -0,0 +1,177 @@ +--- +title: Seguridad de Sitios Web +slug: Learn/Server-side/Primeros_pasos/seguridad_sitios_web +tags: + - Aprendizaje + - Codificación de scripts + - Guía + - Principiante + - Programación de lado servidor + - Seguridad + - Seguridad Web + - Seguridad de sitios Web + - introducción +translation_of: Learn/Server-side/First_steps/Website_security +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</div> + +<p class="summary">La Seguridad web require vigilancia en todos los aspectos del diseño y uso de un sitio web. Este artículo introductorio no te hará un gurú de la seguridad en sitios web, pero te ayudará a entender de donde vienen las amenazas y qué puedes hacer para fortalecer tu aplicación web contra los ataques más comunes.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Pre-requisitos:</th> + <td>Conocimientos de computación básicos.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Entender las amenazas más comunes para la seguridad de una aplicación web y lo que puedes hacer para reducir el riesgo de que tu sitio sea hackeado.</td> + </tr> + </tbody> +</table> + +<h2 id="¿Qué_es_la_seguridad_de_sitios_web">¿Qué es la seguridad de sitios web?</h2> + +<p>¡Internet es un sitio peligroso! Con mucha frecuencia escuchamos sobre sitios web que dejan de estar disponibles debido a ataques de denegación de servicio, o presentan información modificada (y con frecuencia dañada) en sus páginas de inicio. En otros casos de alto nivel, millones de contraseñas, direcciones de correo electrónico y detalles de tarjetas de crédito han sido filtrados al dominio público, exponiendo a los usuarios del sitio web tanto a bochorno personal como a riesgo finaciero.</p> + +<p>El propósito de la seguridad web es prevenir ataques de esta (o de cualquier otra) clase. Mas formalmente, <em>la seguridad es la acción/práctica de proteger sitios web del acceso, uso, modificación, destrucción o interrupción, no autorizados</em>.</p> + +<p>La seguridad de sitios web eficaz requiere de esfuerzos de diseño a lo largo de la totalidad del sitio web: en tu aplicación web, en la configuración del servidor web, en tus políticas para crear y renovar contraseñas, y en el código del lado cliente. Al mismo tiempo que todo esto suena muy inquietante, la buena noticia es que si estás usando un framework web de lado servidor, es casi seguro que habilitará por defecto mecanismos de defensa robustos y bien pensados contra gran cantidad de los ataques más comunes. Otros ataques pueden mitigarse por medio de la configuración de tu servidor web, por ejemplo habilitando HTTPS. Finalmente, hay herramientas de escaneado de vulnerabilidades disponibles públicamente que pueden ayudarte a averiguar si has cometido algún error obvio.</p> + +<p>El resto de este artículo proporciona más detalle sobre unas pocas amenazas comunes y algunos de los pasos simples que puedes dar para proterger tu sitio.</p> + +<div class="note"> +<p><strong>Nota</strong>: Este es un tema de introducción, diseñado para ayudarte a pensar sobre la seguridad de sitios web. No pretende ser exhaustivo.</p> +</div> + +<h2 id="Amenazas_contra_la_seguridad_de_sitios_web">Amenazas contra la seguridad de sitios web</h2> + +<p>Esta sección lista sólo algunas pocas de las amenazas más comunes para los sitios web y cómo son mitigadas. A medida que vayas leyendo, fíjate cómo las amenazas tienen éxito cuando la aplicación web, ¡o confía o <em>no es lo suficientemente paranoica</em> acerca de los datos que vienen del explorador web!</p> + +<h3 id="Cross-Site_Scripting_XSS">Cross-Site Scripting (XSS)</h3> + +<p>XSS es un término que se usa para describir una clase de ataques que permiten al atacante inyectar scripts de lado cliente, <em>a través </em>del sitio web, hasta los exploradores de otros usuarios. Como el código inyectado va del servidor del sitio al explorador, se supone de confianza, y de aquí que pueda hacer cosas como enviar al atacante la cookie de autorización al sitio del usuario. Una vez que el atacante tiene la cookie pueden iniciar sesión en el sitio como si fuera el verdadero usuario y hacer cualquier cosa que pueda hacer éste. Dependiendo de que sitio sea, esto podría incluir acceso a los detalles de su tarjeta de crédito, ver detalles de contactos o cambiar contraseñas, etc.</p> + +<div class="note"> +<p><strong>Nota</strong>: Las vulnerabilidades XSS han sido históricamente más comunes que las de cualquier otro tipo.</p> +</div> + +<p>Hay dos aproximaciones principales para conseguir que el sitio devuelva scripts inyectados al explorador — se conocen como vulnerabilidades XSS <em>reflejadas</em> y <em>persistentes</em>.</p> + +<ul> + <li>Una vulnerabilidad XSS <em>reflejada</em> ocurre cuando contenido del usuario que se pasa al servidor se devuelve <em>inmediatamente y sin modificar</em> par que los muestre el explorador — ¡cualquier script en el contenido original del usuario se ejecutará cuando se cargue una nueva página!<br> + Por ejemplo, considera una función de búsqueda en un sitio donde los términos de búsqueda están codificados como parámetros URL y estos términos se presentan junto con los resultados. Un atacante puede construir un enlace de búsqueda que contenga un script malicioso como parámetro (ej. <code>http://mysite.com?q=beer<script%20src="http://evilsite.com/tricky.js"></script></code>) y enviarlo como enlace en un correo electrónico a otro usuario: Si el destinatario pincha en este "enlace interesante", el script se ejecutará cuando se muestren en pantalla los resultados de la búsqueda. Como discutimos arriba, ésto da al atacante toda la información que necesita para entrar en el sitio como si fuera el usuario destinatario — realizando compras potencialmente como si fuera el usuario o compartiendo su información de contactos.</li> + <li>Una vulnerabilidad <em>XSS persistente</em> es aquella en la que el script malicioso se <em>almacena</em> en el sitio web y luego más tarde se vuelve a presentar en pantalla sin modificar para que otros usuarios lo ejecuten involuntariamente. Por ejemplo, un foro de discusión que accepta comentarios que contengan HTML sin modificar, podría almacenar un script malicioso de un atacante. Cuando se muestren los comentarios se ejecutará el script y enviará al atacante la información requerida para acceder a la cuenta del usuario. Esta clase de ataque es extremadamente popular y muy potente, porque el atacante no tiene que tener ninguna relación directa con las víctimas.<br> + <br> + Si bien los datos <code>POST</code> o <code>GET</code> son las fuentes más comunes de vulnerabilidades, cualquier dato del explorador es vulnerable potencialmente (incluyendo los datos de cookies renderizados por el explorador, o los ficheros de los usuarios que éste sube o que se muestran).</li> +</ul> + +<p>La mejor defensa contra las vulnerabilidades XSS es eliminar o deshabilitar cualquier etiqueta que pueda contener instrucciones para ejecutar código. En el caso del HTML ésto incluye etiquetas como <code><script></code>, <code><object></code>, <code><embed></code>, y <code><link></code>.</p> + +<div> +<p>El proceso de modificar los datos del usuario de manera que no puedan utilizarse para ejecutar scripts o que afecten de otra forma la ejecución del código del servidor, se conoce como "desinfección de entrada" (input sanitization). Muchos frameworks web desinfectan automáticamente la entrada del usuario desde formularios HTML, por defecto.</p> +</div> + +<h3 id="Inyección_SQL">Inyección SQL</h3> + +<p>Las vulnerabilidades de Inyección SQL habilitan que usuarios maliciosos ejecuten código SQL arbitrario en una base de datos, permitiendo que se pueda acceder a los datos, se puedan modificar o borrar, independientemente de los permisos del usuario. Un ataque de inyección con éxito, podría falsificar identidades, crear nuevas identidades con derechos de administración, acceder a todos los datos en el servidor o destruir/modificar los datos para hacerlos inutilizables.</p> + +<p>Esta vulnerabilidad está presente si la entrada del usuario que se pasa a la sentencia SQL subyacente puede cambiar el significado de la misma. Por ejemplo, considera el código de abajo, que pretende listar todos los usuarios con un nombre en particular (<code>userName</code>) que ha sido suministrado en un formulario HTML:</p> + +<pre class="brush: sql">statement = "SELECT * FROM users WHERE name = '" + <strong>userName</strong> + "';"</pre> + +<p>Si el usuario introduce su nombre real, la cosa funciona como se pretende. Sin embargo un usuario malicioso podría cambiar completamente el comportamiento de esta sentencia SQL a la nueva sentencia de abajo, simplemente especificando para <code>userName</code> el texto de abajo en "<strong>negrilla</strong>". La sentencia modificada crea una sentencia SQL válida que borra la tabla <code>users</code> y selecciona todos los datos de la tabla <code>userinfo</code> (revelando la información de todos los usuarios). Esto funciona por que la primera parte del texto inyectado (<code>a';</code>) completa la sentencia original (' es el símbolo para indicar una cadena literal en SQL).</p> + +<pre class="brush: sql">SELECT * FROM users WHERE name = '<strong>a';DROP TABLE users; SELECT * FROM userinfo WHERE 't' = 't</strong>'; +</pre> + +<p>La manera de evitar esta clase de ataque es asegurar que cualquier dato de usuario que se pasa a un query SQL no puede cambiar la naturaleza del mismo. Una forma de hacer ésto es <a href="https://en.wikipedia.org/wiki/Escape_character">eludir ('escape')</a> todos los caracteres en la entrada de usuario que tengan un significado especial en SQL.</p> + +<div class="note"> +<p><strong>Nota</strong>: La sentencia SQL trata el caracer ' como el principio y el final de una cadena de texto. Colocando el caracter barra invertida \ delante, "eludimos" el símbolo (\'), y le decimos a SQL que lo trate como un caracter de texto (como parte de la misma cadena).</p> +</div> + +<p>En la sentencia de abajo eludimos el carácter '. SQL interpretará ahora como "nombre" la cadena de texto completa mostrada en negrilla (!un nombre muy raro desde luego, pero no dañino¡)</p> + +<pre class="brush: sql">SELECT * FROM users WHERE name = '<strong>a\';DROP TABLE users; SELECT * FROM userinfo WHERE \'t\' = \'t'</strong>; + +</pre> + +<p>Los frameworks web con frecuencia tienen cuidado de hacer por tí la elusión de caracteres. Django, por ejemplo se asegura que cualquier dato de usuario que se pasa a los conjuntos de queries (modelo de queries) está corregido.</p> + +<div class="note"> +<p><strong>Nota</strong>: Esta sección se sustenta aquí en la información de <a href="https://en.wikipedia.org/wiki/SQL_injection">Wikipedia</a>.</p> +</div> + +<h3 id="Cross_Site_Request_Forgery_CSRF">Cross Site Request Forgery (CSRF)</h3> + +<p>Los ataques de CSRF permiten que un usuario malicioso ejecute acciones usando las credenciales de otro usuario sin el conocimiento o consentimiento de éste.</p> + +<p>Este tipo de ataque se explica mejor con un ejemplo. John es un usuario malicioso que sabe que un sitio en particular permite a los usuarios que han iniciado sesión enviar dinero a una cuenta específica usando una petición HTTP <code>POST</code> que incluye el nombre de la cuenta y una cantidad de dinero. John construye un formulario que incluye los detalles de su banco y una cantidad de dinero como campos ocultos, y lo envía por correo electrónico a otros usuarios del sitio (con el botón de <em>Enviar</em> camuflado como enlace a un sitio "hazte rico rápidamente").</p> + +<p>Si el usuario pincha el botón de enviar, se envía al servidor una petición HTTP <code>POST</code> que contiene los detalles de la transacción y <em>todos los cookies de lado-cliente que el explorador asocia con el sitio</em> (añadir cookies asociados con el sitio es un comportamiento normal de los exploradores). El servidor comprobará los cookies, y los usará para determinar si el usuario ha iniciado sesión o no y si tiene permiso para hacer la transacción.</p> + +<p>El resultado es que cualquier usuario que pinche en el botón <em>Enviar</em> mientras tiene la sesión iniciada en el sitio comercial hará la transacción. ¡John se hará rico!</p> + +<div class="note"> +<p><strong>Nota</strong>: El truco aquí es que John no necesita tener acceso a los cookies del usuario (o acceso a sus credenciales) — El explorador del usuario almacena esta información, y la incluye automáticamente en todas las peticiones al servidor asociado.</p> +</div> + +<p>Una manera de prevenir este tipo de ataque por parte del servidor es requerir que la petción <code>POST</code> incluya una palabra secreta específica del usuario generada por el sitio (la palabra secreta podría proporcionarla el servidor cuando envía el formulario web que se usa para hacer transferencias). Esta aproximación evita que John pueda crear su propio formulario, porque necesitaría conocer la palabra secreta que el servidor ha proporcionado para el usuario. Incluso si conociera esta palabra y creara un formulario para un usuario en particular, no podría usar el mismo formulario para atacar a todos los usuarios.</p> + +<p>Los frameworks web incluyen con frecuencia tales mecanismos de prevención de CSRF.</p> + +<h3 id="Otras_amenazas">Otras amenazas</h3> + +<p>Otros ataques/vulnerabilidades incluyen:</p> + +<ul> + <li><a href="https://www.owasp.org/index.php/Clickjacking">Clickjacking</a>. En este tipo de ataque, el usuario malicioso secuestra las pulsaciones de ratón dirigidas a un sitio visible por encima de los demás y las redirige a una página escondida por debajo. Esta técnica se usaría, por ejemplo, para presentar un sitio bancario legítimo pero capturar las credenciales de inicio de sesión en un {{htmlelement("iframe")}} invisible controlado por el atacante. Alternativamente podría usarse para conseguir que el usuario pinchara sobre un botón en un sitio visible, pero al hacerlo realmente estuviera sin advertirlo pinchando en otro botón completamente diferente. Como defensa, tu sitio puede protegerse de ser embebido en un iframe de otro sitio configurando las cabeceras HTTP apropiadamente.</li> + <li><a href="/en-US/docs/Glossary/Distributed_Denial_of_Service">Denegación de Servicio, (Denial of Service</a>, DoS). DoS se consigue normalmente inundando el sitio objetivo con peticiones espúreas de manera que se interrumpa el acceso a los usuarios legítimos. Las peticiones pueden simplemente ser numerosas, o consumir individualmente gran cantidad de recursos (ej. lecturas lentas, subidas de grandes ficheros, etc.) Las defensas contra DoS normalmente trabajan mediante la indentificación y el bloqueo de tráfico "malo" permitiendo sin embargo que atraviesen los mensajes legítimos. Estas defensas se encuentran típicamente dentro o antes del servidor (no son parte de la aplicación web misma).</li> + <li><a href="https://en.wikipedia.org/wiki/Directory_traversal_attack">Salto de Directorios</a>/Revelación de Ficheros. En este tipo de ataque un usuario malicioso intenta acceder a partes del sistema de ficheros del servidor web a los que no debería tener acceso. Esta vulnerabilidad ocurre cuando el usuario es capaz de pasar nombres de fichero que incluyen caracteres del sistema de navegación (ej. <code>../../</code>). La solución es desinfectar la entrada antes de usarla.</li> + <li><a href="https://en.wikipedia.org/wiki/File_inclusion_vulnerability">Inclusión de Ficheros</a>. En este ataque un usuario es capaz de especificar, para mostrar o ejecutar, un fichero "no intencionado para ello" en los datos que le pasa al servidor. Una vez ha sido cargado este fichero podría ejecutarse en el servidor web o en el lado cliente (llevando a un ataque XSS). La solución es desinfectar la entrada antes de usarla.</li> + <li><a href="https://www.owasp.org/index.php/Command_Injection">Inyección de Comandos</a>. Los ataques de inyección de comandos permiten a un usuario malicioso ejecutar comandos del sistema arbitrarios en el sistema operativo del host. La solución es desinfectar la entrada de usuario antes de que pueda ser usada en llamadas al sistema.</li> +</ul> + +<p>Hay muchas más. Para un lisado completo ver <a href="https://en.wikipedia.org/wiki/Category:Web_security_exploits">Category:Web security exploits</a> (Wikipedia) y <a href="https://www.owasp.org/index.php/Category:Attack">Category:Attack</a> (Open Web Application Security Project).</p> + +<h2 id="Unos_cuantos_mensajes_clave">Unos cuantos mensajes clave</h2> + +<p>Casi todos los exploits de las secciones anteriores tienen éxito cuando la aplicación web confía en los datos que vienen del explorador. Sea lo que sea que hagas para mejorar la seguridad de tu sitio web, deberías desinfectar todos los datos originados por el usuario antes de ser mostrados en el explorador, usados en queries SQL o pasados en una llamada al sistema operativo o fichero de sistema.</p> + +<div class="warning"> +<p>Importante: La lección más importante que debes aprender acerca de la seguridad de sitios web es <strong>nunca confíes en los datos del explorador web</strong>. Esto incluye los datos en parámetros URL de las peticiones<code>GET</code>, datos <code>POST</code>, cabeceras HTTP y cookies, ficheros subidos por los usuarios, etc. Comprueba siempre y desinfecta todos los datos entrantes. Siempre asume lo peor.</p> +</div> + +<p>Otras cuantas medidas concretas que puedes tomar son:</p> + +<ul> + <li>Usar una gestión de contraseñas más efectiva. Fomentar las contraseñas fuertes y que se cambien con regularidad. Considerar para tu sitio web la autenticación de dos factores, de manera que, además de la contraseña, el usuario tenga que introducir algún otro código de autenticación (normalmente alguno que se distribuye mediante algún hardware que sólo tiene el usuario, como un código en un mensaje de texto enviado a su teléfono móvil).</li> + <li>Configurar tu servidor web para usar <a href="/en-US/docs/Glossary/https">HTTPS</a> y <a href="/en-US/docs/Web/Security/HTTP_strict_transport_security">HTTP Strict Transport Security</a> (HSTS). HTTPS encripta los datos enviados entre el cliente y el servidor. Esto asegura que las credenciales de incio de sesión, cookies, datos <code>POST</code> e información de cabecera permanecen menos disponibles a los atacantes.</li> + <li>Seguir la pista a las amenazas más populares (<a href="/en-US/docs/">aquí puedes acceder a la lista actual OWASP</a>) y atacar las vulnerabilidades más comunes primero.</li> + <li>Usar herramientas de <a href="https://www.owasp.org/index.php/Category:Vulnerability_Scanning_Tools">escanéo de vulnerabilidade</a><a href="https://www.owasp.org/index.php/Category:Vulnerability_Scanning_Tools">s</a> para realizar pruebas automáticas de seguridad en tu sitio (más adelante, si tu sitio web llega a ser super exitoso puedes también encontrar bugs por medio de ofrecer recompensas por encontrar bugs <a href="https://www.mozilla.org/en-US/security/bug-bounty/faq-webapp/">como hace Mozilla aquí</a>).</li> + <li>Almacena y muestra sólo los datos que necesiten serlo. Por ejemplo, si tus usuarios deben almacenar información sensible como los detalles de las tarjetas de crédito, sólo muestra lo suficiente del número de tarjeta de manera que pueda ser identificada por el usuario, y no suficiente para que pueda ser copiado por el atacante y usado en otro sitio. El patrón más común hoy en día es mostrar sólo los 4 últimos dígitos del número de la tarjeta de crédito.</li> +</ul> + +<p>Los frameworks web pueden ayudar a mitigar muchas de las vulnerabilidades más comunes.</p> + +<h2 id="Sumario">Sumario</h2> + +<p>Este artículo ha explicado el concepto de seguridad en sitios web y algunas de las amanazas más comunes contra las que tu sitio debería empezar a protegerse. Lo más importante que deberías entender es que ¡una aplicación web no puede confiar en ningún dato que provenga de explorador web! Todos los datos de usuario deberían ser desinfectados antes de ser mostrados, o usados en queries SQL o llamadas a ficheros de sistema.</p> + +<p>Hemos llegado al final de <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos">este módulo</a>, tratando tus primeros pasos en la programación de lado servidor de un sitio web. Esperamos que hayas disfrutado del aprendizaje de los conceptos fundamentales y estés listo para seleccionar un framework web y empezar a programar.</p> + +<p>{{PreviousMenu("Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</p> + + + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Introducci%C3%B3n">Introducción al lado servidor</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Vision_General_Cliente_Servidor">Visión general Cliente-Servidor</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Web_frameworks">Frameworks web de lado servidor</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/seguridad_sitios_web">Seguridad de sitios web</a></li> +</ul> diff --git a/files/es/learn/server-side/primeros_pasos/vision_general_cliente_servidor/index.html b/files/es/learn/server-side/primeros_pasos/vision_general_cliente_servidor/index.html new file mode 100644 index 0000000000..05ce1f9451 --- /dev/null +++ b/files/es/learn/server-side/primeros_pasos/vision_general_cliente_servidor/index.html @@ -0,0 +1,334 @@ +--- +title: Visión General Cliente-Servidor +slug: Learn/Server-side/Primeros_pasos/Vision_General_Cliente_Servidor +tags: + - Aprendizaje + - Codificación de scripts + - Guía + - Principiante + - Programación lado servidor + - Servidor + - introducción +translation_of: Learn/Server-side/First_steps/Client-Server_overview +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</div> + +<p class="summary">Ahora que conoces el propósito y los beneficios potenciales de la programación de lado-servidor vamos a examinar en detalle lo que ocurre cuando un servidor recibe una "petición dinámica" desde un explorador web. Ya que el código de lado servidor de la mayoría de los sitios web gestiona peticiones y respuestas de formas similares, este artículo te ayudará a entender lo que necesitas hacer para escribir la mayor parte de tu propio código.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td>Conocimientos básicos de computación. Noción básica de lo que es un servidor.</td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td>Comprender lo que son las interacciones cliente-servidor en un sitio web dinámico, y en particular que operaciones necesita realizar el código de lado servidor.</td> + </tr> + </tbody> +</table> + +<p>No hay código real en el debate porque ¡todavía no hemos seleccionado el framework web que usaremos para escribir nuestro código! Sin embargo este debate sí que es muy relevante incluso ahora, porque el comportamiento descrito debería ser implementado por tu código de lado servidor independientemente de qué lenguaje de programación o framework web hayas seleccionado.</p> + +<h2 id="Servidores_Web_y_HTTP_(iniciación)">Servidores Web y HTTP (iniciación)</h2> + +<p>Los exploradores web se comunican con los <a href="https://developer.mozilla.org/en-US/docs/Learn/Common_questions/What_is_a_web_server">servidores web</a> usando el Protocolo de Transferencia de HyperTexto (<strong>H</strong>yper<strong>T</strong>ext<strong>T</strong>ransfer <strong>P</strong>rotocol <a href="/en-US/docs/Web/HTTP">HTTP</a>). Cuando pinchas en un enlace sobre una página web, envías un formulario o ejecutas una búsqueda, el explorador envía una petición (<em>Request) </em>HTTP al servidor.</p> + +<p>Esta petición incluye:</p> + +<ul> + <li>Una URL que identifica el servidor de destino y un recurso (ej. un fichero HTML, un punto de datos particular en el servidor, o una herramienta a ejecutar).</li> + <li>Un método que define la acción requerida (por ejemplo, obtener un fichero o salvar o actualizar algunos datos). Los diferentes métodos/verbos y sus acciones asociadas se listan debajo: + <ul> + <li><code>GET</code>: Obtener un recurso específico (ej. un fichero HTML que contiene información acerca de un producto o una lista de productos).</li> + <li><code>POST</code>: Crear un nuevo recurso (ej. añadir un nuevo artículo a una wiki, añadir un nuevo contacto a una base de datos). </li> + <li><code>HEAD</code>: Obtener la información de los metadatos sobre un recurso específico sin obtener el cuerpo entero tal como haría <code>GET</code>. Podrías, por ejemplo, usar una petición <code>HEAD</code> para encontrar la última vez que un recurso fue actualizado, y a continuación usar la petición <code>GET</code> (más "cara") para descargar el recurso sólo si éste ha cambiado. </li> + <li><code>PUT</code>: Actualizar un recurso existente (o crear uno nuevo si no existe).</li> + <li><code>DELETE</code>: Borrar el recurso específico.</li> + <li><code>TRACE</code>, <code>OPTIONS</code>, <code>CONNECT</code>, <code>PATCH</code>: Estos verbos son para tareas menos comunes/avanzadas, por lo que no los trataremos aquí.</li> + </ul> + </li> + <li>Se puede codificar información adicional con la petición (por ejemplo, datos de un formulario HTML). La información puede ser codificada como: + <ul> + <li>Parámetros URL: Las peticiones <code>GET</code> codifican los datos en la URL enviada al servidor añadiendo al final pares nombre/valor — por ejemplo, <code>http://mysite.com<strong>?name=Fred&age=11</strong></code>. Siempre encontrarás un signo de interrogación(<code>?</code>) separando los parámetros URL del resto de la misma, un signo igual (<code>=</code>) separando cada nombre de su valor asociado y un ampersand (<code>&</code>) separando cada par. Los parámetros URL son inherentemente "inseguros" ya que pueden ser modificados por los usuarios y ser enviados de nuevo. Como consecuencia los parámetros URL/peticiones <code>GET</code> no se usan para peticiones de actualización de datos en el servidor.</li> + <li>Datos <code>POST</code>. Las peticiones <code>POST</code> añaden nuevos recursos, cuyos datos están codificados dentro del cuerpo de la petición.</li> + <li>Cookies de lado cliente. Los Cookies contienen datos de sesión acerca del cliente, incluyendo las claves que el servidor puede usar para determinar su estado de incio de sesión y los permisos/accesos a los recursos.</li> + </ul> + </li> +</ul> + +<p>Los servidores web esperan los mensajes de petición de los clientes, los procesan cuando llegan y responden al explorador web con un mensaje de respuesta HTTP. La respuesta contiene un <a href="/en-US/docs/Web/HTTP/Status">código de estado de respuesta HTTP</a> que indica si la petición ha tenido éxito o no (ej. "<code>200 OK</code>" para indicar éxito, "<code>404 Not Found</code>" si el resurso no ha podido ser encontrado, "<code>403 Forbidden</code>" si el usuario no está autorizado a acceder al recurso, etc). El cuerpo de la respuesta de éxito a una petición <code>GET</code> contendría el recurso solicitado.</p> + +<p>Cuando se devuelve una página HTML es renderizada por el explorador web. Como parte del procesamiento el explorador puede descubrir enlaces a otros recursos (ej. una página HTML normalmente referencia las páginas JavaScript y CSS), y enviará peticiones HTTP separadas para descargar estos ficheros.</p> + +<p>Los sitios web tanto estáticos como dinámicos (abordados en las secciones siguientes) usan exactamente los mismos protocolos/patrones de comunicación.</p> + +<h3 id="Ejemplo_de_peticiónrespuesta_GET">Ejemplo de petición/respuesta GET</h3> + +<p>Puedes realizar una petición <code>GET</code> simplemente pinchando sobre un enlace o buscando en un sitio (como la página inicial de un motor de búsquedas). Por ejemplo, la petición HTTP que se envía cuando realizas una búsqueda en MDN del término "visión general cliente servidor" se parecerá mucho al texto que se muestra más abajo (no será idéntica porque algunas partes del mensaje dependen de tu explorador/configuración).</p> + +<div class="note"> +<p>El formato de los mensajes HTTP está definido en el "estándard web" (<a href="http://www.rfc-editor.org/rfc/rfc7230.txt">RFC7230</a>). No necesitas conocer este nivel de detalle, pero al menos ¡ahora sabes de donde viene todo esto!</p> +</div> + +<h4 id="La_petición">La petición</h4> + +<p>Cada linea de la petición contiene información sobre ella. La primera parte se llama <strong>cabecera</strong> o <strong>header</strong>, y contiene información útil sobre la petición, de la misma manera que un <a href="/en-US/docs/Learn/HTML/Introduction_to_HTML/The_head_metadata_in_HTML">HTML head</a> contiene información útil sobre un documento (pero no el contenido mismo, que está en el cuerpo):</p> + +<pre>GET https://developer.mozilla.org/en-US/search?q=client+server+overview&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev HTTP/1.1 +Host: developer.mozilla.org +Connection: keep-alive +Pragma: no-cache +Cache-Control: no-cache +Upgrade-Insecure-Requests: 1 +User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +Referer: https://developer.mozilla.org/en-US/ +Accept-Encoding: gzip, deflate, sdch, br +<code>Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7</code> +Accept-Language: en-US,en;q=0.8,es;q=0.6 +Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; csrftoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT; dwf_section_edit=False; dwf_sg_task_completion=False; _gat=1; _ga=GA1.2.1688886003.1471911953; ffo=true +</pre> + +<p>La primera y segunda líneas contienen la mayoría de la información de la que hemos hablado arriba:</p> + +<ul> + <li>El tipo de petición (<code>GET</code>).</li> + <li>La URL del recurso de destino (<code>/en-US/search</code>).</li> + <li>Los parámetros URL (<code>q=client%2Bserver%2Boverview&topic=apps&topic=html&topic=css&topic=js&topic=api&topic=webdev</code>).</li> + <li>El destino/host del sitio web (developer.mozilla.org).</li> + <li>El final de la primera linea también incluye una cadena corta que identifica la versión del protocolo utilizado (<code>HTTP/1.1</code>).</li> +</ul> + +<p>La última linea contiene información sobre los cookies del lado cliente — puedes ver que en este caso el cookie incluye un id para gestionar las sesiones (<code>Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; ...</code>).</p> + +<p>Las líneas restantes contienen información sobre el explorador web usado y la clase de respuestas que puede manejar. Por ejemplo, puedes ver aquí que:</p> + +<ul> + <li>Mi explorador (<code>User-Agent</code>) es Mozilla Firefox (<code>Mozilla/5.0</code>).</li> + <li>Puede aceptar información comprimida gzip (<code>Accept-Encoding: gzip</code>).</li> + <li>Puede aceptar el conjunto de caracteres especificado (<code>Accept-Charset: ISO-8859-1,UTF-8;q=0.7,*;q=0.7</code>) y los idiomas (<code>Accept-Language: de,en;q=0.7,en-us;q=0.3</code>).</li> + <li>La linea <code>Referer</code> indica la dirección de la página web que contenía el enlace a este recurso (es decir, el origen de la petición, <code>https://developer.mozilla.org/en-US/</code>).</li> +</ul> + +<p>Las peticiones HTTP también pueden tener un cuerpo, pero está vacío en este caso.</p> + +<h4 id="La_respuesta">La respuesta</h4> + +<p>La primera parte de la respuesta a esta petición se muestra abajo. La cabecera o header contiene información como la siguiente:</p> + +<ul> + <li>La primera linea incluye el código de respuesta <code>200 OK</code>, que nos dice que la petición ha tenido éxito.</li> + <li>Podemos ver que la respuesta está formateada (<code>Content-Type</code>) en modo <code>text/html</code>.</li> + <li>Podemos ver que usa también el conjunto de caracteres UTF-8 (<code>Content-Type: text/html; charset=utf-8</code>).</li> + <li>La cabecera también nos dice lo grande que es (<code>Content-Length: 41823</code>).</li> +</ul> + +<p>Al final del mensaje vemos el contenido del <strong>cuerpo</strong> (<strong>body</strong>) — que contiene el HTML real devuelto por la respuesta.</p> + +<pre class="brush: html">HTTP/1.1 200 OK +Server: Apache +X-Backend-Server: developer1.webapp.scl3.mozilla.com +Vary: Accept,Cookie, Accept-Encoding +Content-Type: text/html; charset=utf-8 +Date: Wed, 07 Sep 2016 00:11:31 GMT +Keep-Alive: timeout=5, max=999 +Connection: Keep-Alive +X-Frame-Options: DENY +Allow: GET +X-Cache-Info: caching +Content-Length: 41823 + + + +<!DOCTYPE html> +<html lang="en-US" dir="ltr" class="redesign no-js" data-ffo-opensanslight=false data-ffo-opensans=false > +<head prefix="og: http://ogp.me/ns#"> + <meta charset="utf-8"> + <meta http-equiv="X-UA-Compatible" content="IE=Edge"> + <script>(function(d) { d.className = d.className.replace(/\bno-js/, ''); })(document.documentElement);</script> + ... +</pre> + +<p>El resto de la cabecera de la respuesta incluye información sobre la respuesta (ej. cuándo se generó), el servidor, y cómo espera el explorador manejar la página (ej. la linea <code>X-Frame-Options: DENY</code> le dice que al explorador que no está permitido incrustar esta página en un {{htmlelement("iframe")}} en otro sitio).</p> + +<h3 id="Ejemplo_de_peticiónrespuesta_POST">Ejemplo de petición/respuesta POST</h3> + +<p>Un HTTP <code>POST</code> se realiza cuando se envía un formulario que contiene información para ser guardada en el servidor.</p> + +<h4 id="La_petición_2">La petición</h4> + +<p>El texto de abajo muestra la petición HTTP realizada cuando un usuario envía al sitio los detalles de un nuevo perfil. El formato de la petición es casi el mismo que en la petición <code>GET</code> del ejemplo mostrado previamente, aunque la primera linea identifica esta petición como <code>POST</code>. </p> + +<pre class="brush: html">POST https://developer.mozilla.org/en-US/profiles/hamishwillee/edit HTTP/1.1 +Host: developer.mozilla.org +Connection: keep-alive +Content-Length: 432 +Pragma: no-cache +Cache-Control: no-cache +Origin: https://developer.mozilla.org +Upgrade-Insecure-Requests: 1 +User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36 +Content-Type: application/x-www-form-urlencoded +Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 +Referer: https://developer.mozilla.org/en-US/profiles/hamishwillee/edit +Accept-Encoding: gzip, deflate, br +Accept-Language: en-US,en;q=0.8,es;q=0.6 +Cookie: sessionid=6ynxs23n521lu21b1t136rhbv7ezngie; _gat=1; csrftoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT; dwf_section_edit=False; dwf_sg_task_completion=False; _ga=GA1.2.1688886003.1471911953; ffo=true + +csrfmiddlewaretoken=zIPUJsAZv6pcgCBJSCj1zU6pQZbfMUAT&user-username=hamishwillee&user-fullname=Hamish+Willee&user-title=&user-organization=&user-location=Australia&user-locale=en-US&user-timezone=Australia%2FMelbourne&user-irc_nickname=&user-interests=&user-expertise=&user-twitter_url=&user-stackoverflow_url=&user-linkedin_url=&user-mozillians_url=&user-facebook_url=</pre> + +<p>La principal diferencia es que la URL no tiene parámetros. Como puedes ver, la información del formulario se codifica en el cuerpo de la petición (por ejemplo, el nombre completo del nuevo usuario se establece usando: <code>&user-fullname=Hamish+Willee</code>).</p> + +<h4 id="La_respuesta_2">La respuesta</h4> + +<p>La respuesta a la petición se muestra abajo. El código de estado "<code>302 Found</code>" le dice al explorador que el POST ha tenido éxito, y que debe realizar una segunda petición HTTP para cargar la página especificada en el campo <code>Location</code>. La información es de lo contrario similar a la respuesta a una petición <code>GET</code>.</p> + +<pre class="brush: html">HTTP/1.1 302 FOUND +Server: Apache +X-Backend-Server: developer3.webapp.scl3.mozilla.com +Vary: Cookie +Vary: Accept-Encoding +Content-Type: text/html; charset=utf-8 +Date: Wed, 07 Sep 2016 00:38:13 GMT +Location: https://developer.mozilla.org/en-US/profiles/hamishwillee +Keep-Alive: timeout=5, max=1000 +Connection: Keep-Alive +X-Frame-Options: DENY +X-Cache-Info: not cacheable; request wasn't a GET or HEAD +Content-Length: 0 +</pre> + +<div class="note"> +<p><strong>Nota</strong>: Las repuestas y las peticiones HTTP mostradas en estos ejemplos fueron capturadas usando la aplicación <a href="https://www.telerik.com/download/fiddler">Fiddler</a>, pero puedes obtener información similar usando sniffers web (ej. <a href="http://web-sniffer.net/">http://web-sniffer.net/</a>) o usando extensiones del explorador como <a href="https://addons.mozilla.org/en-US/firefox/addon/httpfox/">HttpFox</a>. Puedes probarlo por tí mismo. Usa una de las herramientas enlazadas, y a continuación navega a través de un sitio y edita información del perfil para ver las diferentes peticiones y respuestas. La mayoría de los exploradores modernos también tienen herramientas que monitorizan las peticiciones de red (Por ejemplo, la herramienta <a href="/en-US/docs/Tools/Network_Monitor">Network Monitor</a> en Firefox).</p> +</div> + +<h2 id="Sitios_estáticos">Sitios estáticos</h2> + +<p>Un <em>sitio estático</em> es aquél que devuelve desde el servidor el mismo contenido establecido de forma fija en el código cada vez que se solicita una página en particular. De manera que si por ejemplo tienes una página sobre un producto en <code>/static/myproduct1.html</code> , a todos los usuarios se les devolverá la misma página. Si añades otro producto similar a tu sitio necesitarás añadir otra página (ej. <code>myproduct2.html</code>) etc... Esto puede llegar a ser realmente muy poco eficiente — ¿qué sucede cuando alcanzas miles de páginas de productos? Repetirías un montón de código a lo largo de cada página (la plantilla básica de la página, la estructura, etc), y si quisieras cambiar cualquier cosa de la estructura de la página — como añadir una nueva sección de "productos relacionados" por ejemplo — tendrías que cambiar cada página individualmente. </p> + +<div class="note"> +<p><strong>Nota</strong>: Los sitios estáticos son excelentes cuando tienes un pequeño número de páginas y quieres enviar el mismo contenido a todos los usuarios. Sin embargo pueden tener un coste de mantenimiento significante a medida que es número de páginas se hace grande.</p> +</div> + +<p>Recapitulemos cómo funciona ésto, mirando otra vez el diagrama de la arquitectura de un sitio estático que vimos en el anterior artículo.</p> + +<p><img alt="A simplified diagram of a static web server." src="https://mdn.mozillademos.org/files/13841/Basic%20Static%20App%20Server.png"></p> + +<p>Cuando un usuario quiere navegar a una página, el explorador envía una petición HTTP <code>GET</code> especificando la URL de su página HTML. El servidor recupera el documento solicitado de su sistema de ficheros y devuelve una respuesta HTTP conteniendo el documento y un <a href="/en-US/docs/Web/HTTP/Status">código de estado de respuesta HTTP</a> "<code>200 OK</code>" (indicando éxito). El servidor podría devolver un código de estado diferente, por ejemplo "<code>404 Not Found</code>" si el fichero no está presente en el servidor, o "<code>301 Moved Permanently</code>" si el fichero existe pero ha sido redirigido a una localización diferente.</p> + +<p>El servidor de un sitio estático sólo tendrá que procesar peticiones GET, ya que el servidor no almacena ningún dato modificable. Tampoco cambia sus respuestas basádonse en los datos de la petición HTTP (ej. parámetros URL o cookies). </p> + +<p>Entendiendo cómo funcionan los sitios estáticos es útil sin embargo cuando se aprende programación de lado servidor, porque los sitios dinámicos gestionan las peticiones de ficheros estáticos (CSS, JavaScript, imágenes estáticas, etc.) exactamente de la misma forma.</p> + +<h2 id="Sitios_dinámicos">Sitios dinámicos</h2> + +<p>Un <em>sitio dinámico</em> es aquél que puede generar y devolver contenido basándose en la URL y los datos específicos de la petición (en vez de devolver siempre para una URL en particular el mismo fichero especificado en el código de forma fija). Usando el ejemplo de un sitio de productos, el servidor almacenaría "datos" del producto en una base de datos en vez de ficheros HTML individuales. Cuando se reciba una petición HTTP <code>GET</code> para un producto, el servidor determina el ID del mismo, extrae los datos de la base y construye la página HTML de la respuesta insertando los datos dentro de la plantilla HTML. Esto tiene una ventaja primordial sobre un sitio estático: </p> + +<p>Usar una base de datos permite que la información del producto se almacene de forma eficiente y que se pueda ampliar, modificar y buscar fácilmente.</p> + +<p>Usar plantillas HTML hace que sea muy fácil cambiar la estructura HTML, porque sólo se necesita hacer en un sólo lugar, en una única plantilla y no a lo largo de miles de páginas estáticas.</p> + +<h3 id="Anatomía_de_una_petición_dinámica">Anatomía de una petición dinámica</h3> + +<p>Esta sección proporciona una visión general paso a paso de un ciclo de petición y respuesta HTTP "dinámicas", construyendo con más detalle lo que vimos en el último artículo. Para "hacer cosas reales" usaremos el contexto del sitio web de un manager de equipos deportivos donde un entrenador puede seleccionar el nombre y tamaño de su equipo en un formulario HTML y obtener de vuelta una sugerencia de "mejor alineación" para el próximo partido. </p> + +<p>El diagrama de abajo muestra los elementos principales del sitio web del "entrenador del equipo", junto con etiquetas numeradas de la secuencia de operaciones cuando el entrenador accede a su lista de "mejor equipo". Las partes del sitio que lo hacen dinámico son las <em>Aplicaciones Web</em> (que es como llamaremos al código del lado servidor que procesa las peticiones HTTP y devuelve respuestas HTTP), la <em>Base de Datos</em>, que contiene la información sobre los jugadores, equipos, entrenadores y sus relaciones, y las <em>Plantillas HTML</em>.</p> + +<p><img alt="This is a diagram of a simple web server with step numbers for each of step of the client-server interaction." src="https://mdn.mozillademos.org/files/13829/Web%20Application%20with%20HTML%20and%20Steps.png" style="height: 584px; width: 1226px;"></p> + +<p>Después de que el entrenador envíe el formulario con el nombre del equipo y el número de jugadores, la secuencia de operaciones es la siguiente:</p> + +<ol> + <li>El explorador web crea una petición HTTP <code>GET</code> al servidor usando la URL base del recurso (<code>/best</code>) y codifica el equipo y número de jugadores como parámetros URL (ej. <code>/best?team=my_team_name&show=11)</code> o formando parte de un patrón URL (ej. <code>/best/my_team_name/11/</code>). Se usa una petición <code>GET</code> porque la petición sólo recoge datos (no modifica ninguno).</li> + <li>El S<em>ervidor Web</em> detecta que la petición es "dinámica" y la reenvía a la <em>Aplicación</em> para que la procese (el servidor web determina como manejar diferentes URLs basándose en reglas de emparejamiento de patrones definidas en su configuración).</li> + <li>La <em>Aplicación Web</em> identifica que la intención de la petición es obtener la "lista del mejor equipo" basándose en la URL (<code>/best/</code>) y encuentra el nombre del equipo y el número de jugadores requeridos a partir de la URL. La <em>Aplicación Web</em> obtiene entonces la información solicitada de la base de datos (usando parámetros "internos" adicionales que definen qué jugadores son los "mejores", y posiblemente también obteniendo la identidad del entrenador que ha iniciado sesión a partir de un cookie del lado cliente).</li> + <li>La <em>Aplicación Web</em> crea dinámicamente una página HTML por medio de colocar los datos (de la <em>base</em>) en marcadores de posición dentro de la plantilla HTML.</li> + <li>La <em>Aplicación Web</em> devuelve el HTML generado al explorador web (via el <em>Servidor Web</em>), junto con un código de estado HTTP de 200 ("éxito"). Si algo impide que se pueda devolver el HTML entonces la <em>Aplicación Web</em> devolverá otro código — por ejemplo "404" para indicar que el equipo no existe.</li> + <li>El Explorador Web comenzará a continuación a procesar el HTML devuelto, enviando peticiones separadas para obtener cualquier otro fichero CSS o JavaScript que sea referenciado (ver paso 7).</li> + <li>El Servidor Web carga ficheros estáticos del sistema de ficheros y los devuelve al explorador directamente (de nuevo, la gestión correcta de los ficheros está basada en las reglas de configuración y de emparejamiento de patrones URL).</li> +</ol> + +<p>La operación de actualizar un registro de la base de datos se gestionaría de forma similar, excepto que, como para cualquier actualización de la base de datos, la petición HTTP desde el explorador debería ser codificada como petición <code>POST</code>. </p> + +<h3 id="Realización_de_otros_trabajos">Realización de otros trabajos</h3> + +<p>La misión de una <em>Aplicación Web</em> es recibir peticiones HTTP y devolver respuestas HTTP. Mientras que interactuar con la base datos para obtener o actualizar información son tareas muy comunes, el código puede hacer otras cosas al mismo tiempo, o no interactuar con una base de datos en absoluto.</p> + +<p>Un buen ejemplo de una tarea adicional que una <em> Aplicación Web</em> podría realizar sería el envío de un correo electrónico a los usuarios para confirmar su registro en el sitio. El sito podría también realizar logging u otras operaciones.</p> + +<h3 id="Devolución_de_alguna_otra_cosa_distinta_a_HTML">Devolución de alguna otra cosa distinta a HTML</h3> + +<p>El código lado servidor de un sitio web no tiene que devolver fragmentos/ficheros HTML en la respuesta. Puede en vez de eso crear dinámicamente y devolver otros tipos de ficheros (texto, PDF, CSV, etc.) o incluso datos (jSON, XML, etc.).</p> + +<p>La idea de devolver datos a un explorador web de forma que pueda actualizar su propio contenido dinámicamente ({{glossary("AJAX")}}) ha estado dando vueltas durante bastante tiempo. Más recientemente han llegado a ser muy populares las "apps de una sola página", donde el sitio web entero está escrito con un solo fichero HTML que es actualizado dinámicamente cuando se necesita. Los sitios web creados usando este estilo de aplicación transfieren una gran parte del coste computacional desde el servidor al explorador web, y pueden dar como resultado sitios web que se comportan mucho más como aplicaciones nativas (con una respuesta rápida "highly responsive", etc.).</p> + +<h2 id="Los_frameworks_Web_simplifican_la_programación_de_lado_servidor">Los frameworks Web simplifican la programación de lado servidor</h2> + +<p>Los frameworks de lado servidor hacen mucho más fácil escribir código para gestionar las operaciones descritas más arriba.</p> + +<p>Una de las operaciones más importantes que realizan es proporcionar mecanismos simples para mapear las URLs de diferentes recursos/páginas a funciones para su gestión específicas. Esto hace más fácil mantener separado el código asociado con cada recurso. Esto tiene también beneficios en términos de mantenimiento, ya que puedes cambiar la URL usada para entregar una característica particular en un sitio, sin tener que cambiar la función de gestión.</p> + +<p>Por ejemplo, considera el siguiente código Django (Python) que mapea dos patrones URL a dos funciones de visualización. El primer patrón asegura que una petición HTTP con una URL de <code>/best</code> sea pasada a la función llamada <code>index()</code> en el módulo <code>views</code>. En cambio, una petición que tiene el patrón "<code>/best/junior</code>", se pasará a la función de visualización <code>junior()</code>.</p> + +<pre class="brush: python"># file: best/urls.py +# + +from django.conf.urls import url + +from . import views + +urlpatterns = [ + # example: /best/ + url(r'^$', views.index), + # example: /best/junior/ + url(r'^junior/$', views.junior), +]</pre> + +<div class="note"> +<p><strong>Nota</strong>: El primer parámetro en las funciones <code>url()</code> puede parecer un poco extraño (ej. <code>r'^junior/$'</code>) porque usan una técnica de emparejamiento de patrones llamada "expresiones regulares" ("regular expressions", RegEx, o RE). No necesitas saber cómo funcionan las expresiones regulares en este momento, tan sólo que nos permiten emparejar patrones en el URL (en vez de los valores insertados en el código de forma fija que veíamos más arriba) y los usan como parámetros en nuestras funciones de visualización. Como ejemplo, una RegEx simple podría decir "empareja una simple letra mayúscula, seguida de entre 4 y 7 letras minúsculas."</p> +</div> + +<p>El framework web también hace fácil a una función de visualización extraer información de la base de datos. La estructura de nuestros datos está definida en modelos, que son las clases Python que definen los campos que serán almacenados en la base de datos subyacente. Si tenemos un modelo llamado <em>Team</em> con un campo de "<em>team_type</em>" podemos usar un query de sintaxis simple para recuperar todos los equipos que son de un tipo particular.</p> + +<p>Los ejemplos de abajo recuperan una lista de todos los equipos que tienen el <code>team_type</code> de "junior" exacto (teniendo en cuenta la capitalización, mayúsculas o minúsculas) — nota de formato: el nombre del campo (<code>team_type</code>) seguido de un guión bajo doble, y a continuación el tipo de emparejamiento a usar (en este caso <code>exact</code>). Hay muchos otros tipos de emparejamiento y podemos encadenarlos fácilmente. Podemos controlar el orden y número de resultados que se devuelven. </p> + +<pre class="brush: python">#best/views.py + +from django.shortcuts import render + +from .models import Team + + +def junior(request): + list_teams = Team.objects.filter(team_type__exact="junior") + context = {'list': list_teams} + return render(request, 'best/index.html', context) +</pre> + +<p>Después de que la función <code>junior()</code> obtenga la lista de equipos junior, llama a la función <code>render()</code>, pasándole el <code>HttpRequest</code> original, una plantilla HTML, y un objeto "contexto" que define la información a ser incluida en la plantilla. La función <code>render()</code> es una función de conveniencia que genera HTML usando un contexto y una plantilla HTML, y devuelve un objeto <code>HttpResponse</code>.</p> + +<p>Obviamente los frameworks web pueden ayudarte con un monton de otras tareas. Debatiremos sobre un montón más de beneficios y opciones de frameworks web en el próximo artículo.</p> + +<h2 id="Sumario">Sumario</h2> + +<p>En este punto deberías tener una buena visión general de las operaciones que el código de lado servidor tiene que realizar, y conocer algunas de las formas en que un framework web de lado servidor las puede hacer más fáciles.</p> + +<p>En el módulo siguiente te ayudaremos a elegir el mejor Framework Web para tu primer sitio.</p> + +<p>{{PreviousMenuNext("Learn/Server-side/First_steps/Introduction", "Learn/Server-side/First_steps/Web_frameworks", "Learn/Server-side/First_steps")}}</p> + +<p> </p> + +<h2 id="En_este_módulo">En este módulo</h2> + +<ul> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Introduction">Introducción al lado servidor</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Client-Server_overview">Visión general Cliente-Servidor</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Web_frameworks">Frameworks Web de lado servidor</a></li> + <li><a href="/en-US/docs/Learn/Server-side/First_steps/Website_security">Seguridad Web</a></li> +</ul> + +<p> </p> diff --git a/files/es/learn/server-side/primeros_pasos/web_frameworks/index.html b/files/es/learn/server-side/primeros_pasos/web_frameworks/index.html new file mode 100644 index 0000000000..8c381a772e --- /dev/null +++ b/files/es/learn/server-side/primeros_pasos/web_frameworks/index.html @@ -0,0 +1,306 @@ +--- +title: Frameworks Web de lado servidor +slug: Learn/Server-side/Primeros_pasos/Web_frameworks +tags: + - Aprendizaje + - Codificación de scripts + - Frameworks web + - Guía + - Principiante + - Programación lado servidor + - Servidor + - introducción +translation_of: Learn/Server-side/First_steps/Web_frameworks +--- +<div>{{LearnSidebar}}</div> + +<div>{{PreviousMenuNext("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps/Website_security", "Learn/Server-side/First_steps")}}</div> + +<p class="summary">El artículo anterior te mostró que pinta tiene la comunicación entre los clientes web y los servidores, la naturaleza de las peticiones y respuestas HTTP, y lo que necesita hacer una aplicación web de lado servidor para responder a las peticiones de un explorador web. Con este conocimiento en nuestra mochila, es hora de explorar cómo los frameworks web pueden simplificar estas tareas, y darte una idea de cómo escogerías un framework para tu primera aplicación web de lado servidor.</p> + +<table class="learn-box standard-table"> + <tbody> + <tr> + <th scope="row">Prerequisitos:</th> + <td> + <p>Conocimientos de computación básicos. Comprensión de alto nivel de cómo gestiona y responde a las peticiones HTTP el código de lado servidor (ver <a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Vision_General_Cliente_Servidor">Visión general Cliente-Servidor</a>).</p> + </td> + </tr> + <tr> + <th scope="row">Objetivo:</th> + <td> + <p>Entender cómo los frameworks web pueden simplificar el desarrollo/mantenimiento de código de lado servidor y conseguir que los lectores piensen sobre la elección del framework para su propio desarrollo.</p> + </td> + </tr> + </tbody> +</table> + +<p>Las siguientes secciones ilustran algunos puntos usando fragmentos de código tomados de frameworks web reales. No te preocupes si no todo tiene sentido ahora; te pondremos a trabajar sobre el código en nuestros módulos de framework específicos.</p> + +<h2 id="Visión_general">Visión general</h2> + +<p>Los frameworks de lado servidor (es decir, "los frameworks de aplicaciones web") son frameworks software que hacen más fácil escribir, mantener y escalar aplicaciones web. Proporcionan herramientas y bibliotecas que simplifican tareas comunes de desarrollo web, incluyendo enrutado de URLs a los manejadores apropiados, interactuación con bases de datos, soporte de sesiones y autorizaciones de usuario, formateado de la salida (ej, HTML, JSON, XML), y mejora de la seguridad contra los ataques web.</p> + +<p>La sección siguiente proporciona un poco más detalle sobre cómo los frameworks web pueden facilitar el desarrollo de aplicaciones web. Explicaremos a continuación algunos de los criterios que puedes usar para elegir un framework web, y luego hacer una lista de algunas de tus opciones.</p> + +<h2 id="¿Qué_puede_hacer_por_tí_un_framework_web">¿Qué puede hacer por tí un framework web?</h2> + +<p>Los frameworks web proporcionan herramientas y bibliotecas para simplificar operaciones comunes de desarrollo web. No <em>tienes</em> que usar un framework web de lado servidor, pero se recomienda encarecidamente — te hará la vida mucho más fácil.</p> + +<p>Esta sección debate algo de la funcionalidad que proporcionan con frecuencia los frameworks web (!no todo framework proporcionará necesariamente todas estas caracteríticas!)</p> + +<h3 id="Trabajar_directamente_con_peticiones_y_respuestas_HTTP">Trabajar directamente con peticiones y respuestas HTTP</h3> + +<p>Como vimos en el último artículo, los servidores web y los exploradores se comunican vía el protocolo HTTP — los servidores esperan las peticiones HTTP del explorador y devuelven información en respuestas HTTP. Los frameworks web te permiten escribir sintaxis simplificada que generará el código de lado servidor para trabajar con estas peticiones y respuestas. Esto significa que tendrás un trabajo más fácil, interacción más fácil, código de más alto nivel en vez de primitivas de red de bajo nivel.</p> + +<p>El ejemplo de más abajo muestra cómo funciona ésto en el framework web Django (Python). Cada función de visualización "view" (un manejador de peticiones) recibe un objeto <code>HttpRequest</code> que contiene información de petición, y se le pide devolver un objeto <code>HttpResponse</code> con la salida formateada (en este caso una cadena de texto).</p> + +<pre class="brush: python"># Django view function +from django.http import HttpResponse + +def index(request): + # Get an HttpRequest (request) + # perform operations using information from the request. + # Return HttpResponse + return HttpResponse('Output string to return') +</pre> + +<h3 id="Enrutado_de_peticiones_al_manejador_adecuado">Enrutado de peticiones al manejador adecuado</h3> + +<p>La mayoría de sitios proporcionan un gran número de recursos diferentes, accesibles a través de distintas URLs. La gestión de todo esto en una sola función sería difiicil de mantener, de manera que los frameworks web proporcionan mecanismos simples para mapear patrones URL a funciones de gestión específicas. Esta aproximación tiene también beneficios en términos de mantenimiento, porque puedes cambiar el URL que se usa para entregar una característica en particular sin tener que cambiar el código subyacente.</p> + +<p>Diferentes frameworks usan diferentes mencanismos para el mapeo. Por ejemplo, el framework web Flask (Python) añade rutas a las funciones de visualización usando un "decorador".</p> + +<pre class="brush: python">@app.route("/") +def hello(): + return "Hello World!"</pre> + +<p>Por el contrario Django espera que los desarrolladores definan una lista de mapeos URL entre un patrón URL y una función de visualización.</p> + +<pre class="brush: python">urlpatterns = [ + url(r'^$', views.index), + # example: /best/myteamname/5/ + url(r'^(?P<team_name>\w.+?)/(?P<team_number>[0-9]+)/$', views.best), +] +</pre> + +<h3 id="Fácil_acceso_a_los_datos_en_la_petición">Fácil acceso a los datos en la petición</h3> + +<p>Los datos pueden codificarse en una petición HTTP de muchas maneras. Una petición <code>GET</code> para recuperar ficheros o datos de un servidor puede codificar los datos que se necesitan en parámetros URL o dentro de una estructura URL. Una petición <code>POST</code> para actualizar un recurso en el servidor puede en cambio incluir la información de actualización como "datos POST" dentro del cuerpo de la petición. La petición HTTP puede también incluir información sobre la sesión o usuario actual en un cookie de lado cliente.</p> + +<p>Los frameworks web proporcionan mecanismos apropiados del lenguaje de programación para acceder a esta información. Por ejemplo, el objeto <code>HttpRequest</code> que pasa Django a toda función de visualización contiene métodos y propiedades para acceder a la URL de destino, el tipo de petición (ej. HTTP <code>GET</code>), parámetros <code>GET</code> o <code>POST</code>, cookie y datos de session, etc. Django puede también pasar información codificada en la estructura de la URL definiendo "patrones de captura" en el mapeador URL (mira el último fragmento de código de la sección de arriba).</p> + +<h3 id="Abstraer_y_simplificar_el_acceso_a_bases_de_datos">Abstraer y simplificar el acceso a bases de datos</h3> + +<p>Los sitios web utilizan bases de datos para almacenar información tanto para ser compartida con los usuarios como sobre los propios usuarios. Los frameworks web proporcionan frecuentemente una capa de base de datos que abstrae las operaciones de lectura, escritura, consulta y borrado de la base. Nos referimos a esta capa de abstracción como Mapeador de Objetos Relacionados (Object-Relational Mapper, ORM).</p> + +<p>Usar un ORM tiene dos beneficios:</p> + +<ul> + <li>Puedes reemplazar la base de datos subyacente sin tener necesariamente que cambiar el código que la usa: Esto permite a los desarrolladores optimizar las características de las diferentes bases de datos en función de su uso.</li> + <li>la validación básica de datos puede implementarse dentro del framework. Esto hace más fácil y seguro comprobar que los datos se almacenan en el campo correcto de la base, que tienen el formato adecuado (ej. una dirección de correo electrónico), y que no son maliciosos de ninguna manera (los craqueadores utilizan ciertos patrones de código para hacer cosas malas como borrar registros de las bases de datos).</li> +</ul> + +<p>Por ejemplo, el framework web de Django proporciona un ORM, y utiliza la referencia del objeto usado para definir la estructura de un registro similar al <em>modelo</em>. El modelo especifica los <em>tipos</em> de campos que se almacenarán, lo que puede proporcionar una validación a nivel de campo sobre qué información se puede guardar (ej. un campo de email sólo permitiría direcciones válidas de correo electrónico). Las definiciones de campos pueden también especificar su tamaño máximo, etiquetas de texto para los formularios, etc. El modelo no establece ninguna información sobre la base de datos subyacente ya que ese es un ajuste de configuración que se puede cambiar de forma separada de nuestro código.</p> + +<p>El primer fragmento de código más abajo muestra un modelo de Django muy simple para un objeto <code>Team</code>. Éste almacena el nombre y nivel del equipo como campos de caracteres y especifica el número máximo de éstos que pueden almacenarse en cada registro. El <code>team_level</code> es un campo de selección, de manera que proporcionamos un mapeo entre las opciones a mostrar en pantalla y los datos a almacenar, junto con un valor por defecto.</p> + +<pre class="brush: python">#best/models.py + +from django.db import models + +class Team(models.Model): + team_name = models.CharField(max_length=40) + + TEAM_LEVELS = ( + ('U09', 'Under 09s'), + ('U10', 'Under 10s'), + ('U11, 'Under 11s'), + ... #list our other teams + ) + team_level = models.CharField(max_length=3,choices=TEAM_LEVELS,default='U11') +</pre> + +<p>El modelo de Django proporciona una API de consulta simple para buscar en la base de datos. Ésta puede comprobar coincidencias contra un gran número de campos al mismo tiempo usando diferentes criterios (ej. exacto, insensible a las mayúsculas, mayor que, etc.), y puede soportar sentencias complejas (por ejemplo, puedes especificar una búsqueda de equipos U11 que tengan un nombre de equipo que empiece por "Fr" or finalice con "al").</p> + +<p>El segundo fragmento de código muestra una función de visualización (manejador de recurso) para mostrar en pantalla todos nuestros equipos U09. En este caso especificamos que queremos filtrar todos los registros donde el campo <code>team_level</code> tenga exactamente el texto 'U09' (fíjate debajo cómo este criterio se pasa como argumento a la función <code>filter()</code> con el nombre de campo y tipo de coincidencia separados por guiones bajos dobles: <strong>team_level__exact</strong>).</p> + +<pre class="brush: python">#best/views.py + +from django.shortcuts import render +from .models import Team + +def youngest(request): + <strong>list_teams = Team.objects.filter(team_level__exact="U09")</strong> + context = {'youngest_teams': list_teams} + return render(request, 'best/index.html', context) +</pre> + +<dl> +</dl> + +<h3 id="Renderización_de_datos">Renderización de datos</h3> + +<p>Los frameworks web proporcionan con frecuencia sistemas de plantillas. Éstas te permiten especificar la estructura de un documento de salida, usando marcadores de posición para los datos que serán añadidos cuando se genere la página. Las plantillas se usan con frecuencia para crear HTML, pero también pueden crear otros tipos de documentos.</p> + +<p>Los frameworks web proporcionan con frecuencia un mecanismo para facilitar la generación de otros formatos a partir de los datos almacenados, incluyendo {{glossary("JSON")}} y {{glossary("XML")}}.</p> + +<p>Por ejemplo, el sistema de plantillas de Django te permite especificar variables usando una sintaxis de "llaves dobles" (ej. <code>{</code><code>{ <em>variable_name</em> </code><code>}</code><code>}</code>), que serán reemplazadas por valores pasados desde la función de visualización cuando la página sea renderizada. El sistema de plantillas también proporciona soporte para expresiones (con la sintaxis: <code>{% <em>expression</em> %}</code>), que permite a las plantillas realizar operaciones simples como iterar sobre la lista de valores pasados a la misma.</p> + +<div class="note"> +<p><strong>Nota</strong>: Muchos otros sistemas de plantillas usan una sintaxis similar, ej.: Jinja2 (Python), Handlebars (JavaScript), Moustache (JavaScript), etc.</p> +</div> + +<p>El fragmento de código de abajo muestra como hacer este trabajo. Continuando el ejemplo del "equipo más joven" de la sección anterior, la "view" pasa a la plantilla HTML una variable tipo lista llamada <code>youngest_teams</code>. Dentro del esqueleto HTML tenemos una expresión que primero comprueba que la variable <code>youngest_teams</code> existe, y luego itera sobre ella en un bucle <code>for</code>. En cada iteración la plantilla presenta en pantalla el valor del <code>team_name</code> del equipo de uno de los elementos de la lista.</p> + +<pre class="brush: html">#best/templates/best/index.html + +<!DOCTYPE html> +<html lang="en"> +<body> + + {% if youngest_teams %} + <ul> + {% for team in youngest_teams %} + <li>\{\{ team.team_name \}\}</li> + {% endfor %} + </ul> +{% else %} + <p>No teams are available.</p> +{% endif %} + +</body> +</html> +</pre> + +<h2 id="Como_escoger_un_framework_web">Como escoger un framework web</h2> + +<p>Existen muchos frameworks web para casi todos los lenguajes de programación que quieras usar (listamos unos pocos de los frameworks más populares en la sección siguiente). Con tantas opciones, llega a ser difícil deducir qué framework proporciona el mejor punto de partida para tu nueva aplicación web. </p> + +<p>Algunos de los factores que pueden afectar tu decisión son:</p> + +<ul> + <li><strong>Esfuerzo en el aprendizaje:</strong> El esfuerzo en el aprendizaje de un framework web depende de lo familiarizado que estés con el lenguaje de programación subyacente, la consistencia de su API, la calidad de su documentación, y el tamaño y actividad de su comunidad. Si estás partiendo de una nula experiencia en programación, considera entonces Django (es uno de los más fáciles de aprender basándose en los criterios anteriores). Si formas parte de un equipo de desarrolladores que tienen ya una experiencia significante con un framework web o lenguaje de programación en particular tiene sentido entonces que sigas fiel a él.</li> + <li><strong>Productividad:</strong> Productividad es una medida de cuán rápido puedes crear nuevas características una vez que te familiarices con el framework, incluidos tanto el esfuerzo para escribir como para mantener el código (ya que puedes escribir nuevas características mientras se rompen las antiguas). Muchos de los factores que afectan a la productividad son similares a los de el "Esfuerzo para aprender" — ej. documentación, comunidad, experiencia en programación, etc. — otros factores incluyen: + <ul> + <li><em>Propósito/Origen del framework</em>: Algunos frameworks web fueron creados inicialmente para resolver ciertos tipos de problemas, y se mantienen <em>mejor</em> en la creación de apllicaciones web con problemática similar. Por ejemplo, Django fue creado para soportar el desarrollo de un sitio web de un periódico, por lo que es bueno para blogs y otros sitios que impliquen la publicación de cosas. Por contra, Flask es un framework de peso mucho más ligero y es fantástico en la creación de aplicaciones web que se ejecuten en dispositivos embebidos.</li> + <li><em>Dogmático versus No Dogmático</em>: Un framework dogmático es aquél en el que hay recomendaciones sobre el "mejor" método de resolver un problema en particular. Los frameworks dogmáticos tienden a ser más productivos cuando estás tratando de resolver problemas comunes, porque te llevan en la dirección correcta, sin embargo son menos flexibles a veces.</li> + <li><em>Con baterías incluidas versus Hazlo tu mismo</em>: Aalgunos frameworks web incluyen herramientas/bibliotecas que abordan por defecto todos los problemas que sus desarrolladores pueden pensar, mientras que los frameworks más ligeros esperan que los desarrolladores web escojan y elijan las soluciones a sus problemas en bibliotecas separadas (Django es un ejemplo del primero, mientras que Flask es un ejemplo de un framework mucho más ligero). Los frameworks que incluyen todo son con frecuencia más fáciles para empezar con ellos porque ya tienes todo lo que necesitas, y las probabilidades son altas de que esté bien integrado y bien documentado. Sin embargo si un framework más pequeño tiene todo lo que puedas necesitar funcionará en entornos mas constreñidos y tendrán un subconjunto de cosas más pequeñas y más fáciles de aprender.</li> + <li><em>Si el framework potencia o no buenas prácticas de desarrollo</em>: Por ejemplo, un framework que promueve una arquitectura <a href="/en-US/docs/Web/Apps/Fundamentals/Modern_web_app_architecture/MVC_architecture">Modelo-View-Controlador</a> para separar el código en funciones lógicas resultará más mantenible que uno que no tiene espectativas en los desarrolladores. Similarmente, el diseño del framework puede tener un gran impacto en cómo de fácil sea probar y reusar el código.</li> + </ul> + </li> + <li><strong>Desempeño del framework/lenguaje de programación: </strong>Normalmente la "velocidad" no es el factor más grande en la selección porque, incluso, con tiempos de ejecución relativamente lentos como Python, son más que suficientemente buenos para sitios de tamaño medio ejecutándose en hardware moderado. Los beneficios percibidos en velocidad de otro lenguaje, ej. C++ o JavaScript, pueden verse compensados por los costes de aprendizaje y mantenimiento.</li> + <li><strong>Soporte de Cache:</strong> A medida que tu sitio web adquiere más éxito puedes encontrarte que no sea capaz de soportar el número de peticiones que recibe cuando acceden los usuarios. En este punto puedes considerar añadir soporte de cache. La cache es una optimización en la que almacenas todo o parte de una petición web de manera que no tiene que ser recalculada en subsiguientes peticiones. Devolver una respuesta cacheada es más rápido que calcular una la primera vez. El cacheo puede implementarse en tu código o en el servidor (ver <a href="https://en.wikipedia.org/wiki/Reverse_proxy">proxy inverso</a>). Los frameworks web tienen diferentes niveles de soporte para definir qué contenido debe ser cacheado.</li> + <li><strong>Escalabilidad:</strong> Una vez que tu sitio tenga un éxito fabuloso agotarás los beneficios del cacheo e incluso alcanzarás los límites del <em>escalado vertical </em>(ejecutar tu aplicación en un hardware más potente). En este punto podrás necesitar <em>escalar horizontalmente</em> (compartir la carga distribuyendo tu sitio a lo largo de un número de servidores web o bases de datos) o escalar "geográficamente" porque algunos de tus clientes están localizados muy lejos de tu servidor. El framework web que elijas puede marcar una gran diferencia en cómo de fácil sea escalar tu sitio.</li> + <li><strong>Seguridad web:</strong> Algunos frameworks web proporcionan mejor soporte para manejar ataques web comunes. Django por ejemplo desinfecta todas las entradas de los usuarios de las plantillas HTML de manera que el posible código JavaScript introducido por el usuario no pueda ejecutarse. Otros frameworks proporcionan protección similar, pero no siempre está habilitada por defecto.</li> +</ul> + +<p>Hay muchos otros posibles factores, incluyendo licenciamiento, si el framework está bajo desarrollo activo o no, etc.</p> + +<p>Si eres un completo principiante en la programación probablemente escogerás tu framework basándote en la "facilidad de aprendizaje". Además de la "facilidad de uso" del lenguaje mismo, la alta calidad de la documentación/tutoriales y una comunidad activa que ayuda a nuevos usuarios son tus recursos más valiosos. Nosotros hemos escogido <a href="https://www.djangoproject.com/">Django</a> (Python) y <a href="http://expressjs.com/">Express</a> (Node/JavaScript) para escribir nuestros ejemplos de más adelante en el curso, principalmente porque son fáciles de aprender y tienen un buen soporte.</p> + +<div class="note"> +<p><strong>Nota</strong>: Vayamos a los sitios principales de <a href="https://www.djangoproject.com/">Django</a> (Python) y <a href="http://expressjs.com/">Express</a> (Node/JavaScript) y comprobemos su documentación y su comunidad.</p> + +<ol> + <li>Navega a los sitios principales (enlazados abajo) + <ul> + <li>Pincha en los enlaces de los menus de Documentación (cosas que se llaman como "Documentación, Guía, Referencia API, Primeros Pasos".</li> + <li>¿Puedes ver temas que te muestran como configurar enrutado URL, plantillas y bases de datos/modelos?</li> + <li>¿Son los documentos suficientemente claros?</li> + </ul> + </li> + <li>Navega a las listas de correo de cada sitio (accesible desde los enlaces de Comunidad). + <ul> + <li>¿Cuántas preguntas se han realizado en unos pocos días recientes?</li> + <li>¿Cuántas tienen respuestas?</li> + <li>¿Tienen una comunidad activa?</li> + </ul> + </li> +</ol> +</div> + +<h2 id="¿Unos_pocos_frameworks_web_buenos">¿Unos pocos frameworks web buenos?</h2> + +<p>Avancemos ahora, y debatamos unos pocos frameworks web específicos de lado servidor.</p> + +<p>Los frameworks de lado servidor de más abajo representan unos pocos de los más populares disponibles en el momento de escribir este artículo. Todos ellos tienen todo lo que necesitas para ser productivo — son de código abierto, están bajo desarrollo activo, tienen comunidades entusiastas creando documentación y ayudando a los usuarios en paneles de debate, y se usan en un gran número de sitios web de perfil alto. Hay muchos otros frameworks de lado servidor fantásticos que puedes descubrir usando una búsqueda básica en internet. </p> + +<div class="note"> +<p><strong>Nota</strong>: ¡Las descripciones vienen (parcialmente) de los sitios web de los frameworks!</p> +</div> + +<h3 id="Django_(Python)">Django (Python)</h3> + +<p><a href="https://www.djangoproject.com/">Django</a> es un Framework Web Python de alto nivel que promueve el desarrollo rápido y limpio y el diseño pragmático. Construido por desarrolladores experimentados, tiene en cuenta muchos de los problemas del desarrollo web, de manera que puedes focalizarte en escribir el código de tu app sin necesidad de reinventar la rueda. Es gratis y de código abierto.</p> + +<p>Django sigue la filosofía de "Baterias incluidas" y proporciona casi todo lo que la mayoría de desarrolladores querría hacer "de fábrica". Como todo está incluido, todo funciona en conjunto, sigue principios de diseño consistentes y tiene una extensa documentación actualizada. Es también veloz, seguro y muy escalable. Al estar basado en Python, el código de Django es fácil de leer y de mantener.</p> + +<p>Entre los sitios populares que usan Django (según su página web) se incluyen: Disqus, Instagram, Knight Foundation, MacArthur Foundation, Mozilla, National Geographic, Open Knowledge Foundation, Pinterest, Open Stack.</p> + +<h3 id="Flask_(Python)">Flask (Python)</h3> + +<p><a href="http://flask.pocoo.org/">Flask</a> es un microframework para Python. </p> + +<p>A pesar de ser minimalista, Flask puede crear sitios web "de fábrica". Contiene un servidor de desarrollo y depurador, e incluye soporte para plantillas <a href="https://github.com/pallets/jinja">Jinja2</a>, cookies seguros, <a href="https://en.wikipedia.org/wiki/Unit_testing">prueba de unidades</a>, y distribución de peticiones <a href="http://www.restapitutorial.com/lessons/restfulresourcenaming.html">RESTful</a>. Tiene buena documentación y una comunidad activa. </p> + +<p>Flask se ha vuelto extremadamente popular, particularmente entre desarrolladores que necesitan proporcionar servicios web en sistemas pequeños, y con recursos escasos (ej. ejecutar un servidor web en una <a href="https://www.raspberrypi.org/">Raspberry Pi</a>, <a href="http://blogtarkin.com/drone-definitions-learning-the-drone-lingo/">Controladores de Drones</a>, etc.)</p> + +<h3 id="Express_(Node.jsJavaScript)">Express (Node.js/JavaScript)</h3> + +<p><a href="http://expressjs.com/">Express</a> es un framework web veloz, no dogmático, flexible y minimalista para <a href="https://nodejs.org/en/">Node.js</a> (Node es un entorno sin explorador web para ejecutar JavaScript). Proporciona un conjunto de características robusto para aplicaciones web y móviles y entrega valiosos métodos de utilidades HTTP y <a href="/en-US/docs/Glossary/Middleware">middleware</a>.</p> + +<p>Express es extremadamente popular, en parte porque facilita la migración de programadores web de JavaScript de lado cliente a desarrollo de lado servidor, y en parte porque es eficiente con los recursos (el entorno de node subyacente usa multitarea ligera dentro de un thread en vez de expandirse en procesos separados para cada nueva petición web).</p> + +<p>Debido a que Express es un framework web minimalista no incorpora cada componente que querrías usar (por ejemplo, el acceso a bases de datos y el soporte de usuarios y sesiones se proporciona a través de bibliotecas independientes). Hay muchos componentes independientes excelentes, !pero algunas veces puede ser difícil deducir cuál es el mejor para un propósito en particular!</p> + +<p>Muchos frameworks populares y completamente equipados (incluyendo ambos tipos de frameworks de lado servidor y de lado cliente) están basados en Express, como <a href="http://feathersjs.com/">Feathers</a>, <a href="https://www.itemsapi.com/">ItemsAPI</a>, <a href="http://keystonejs.com/">KeystoneJS</a>, <a href="http://krakenjs.com/">Kraken</a>, <a href="http://lean-stack.io/">LEAN-STACK</a>, <a href="http://loopback.io/">LoopBack</a>, <a href="http://mean.io/">MEAN</a>, and <a href="http://sailsjs.org/">Sails</a>.</p> + +<p>Un montón de compañías de perfil alto usan Express, como: Uber, Accenture, IBM, etc. (a<a href="http://expressjs.com/en/resources/companies-using-express.html">quí</a> tienes una lista).</p> + +<h3 id="Ruby_on_Rails_(Ruby)">Ruby on Rails (Ruby)</h3> + +<p><a href="http://rubyonrails.org/">Rails</a> (normalmente referenciado como "Ruby on Rails") es un framework web escrito para el lenguaje de programación Ruby.</p> + +<p>Rails sigue una filosofía de diseño muy similar a Django. Como Django proporciona mecanismos estándard para el enrutado de URLs, acceso a datos de bases, generación de plantillas y formateo de datos como {{glossary("JSON")}} o {{glossary("XML")}}. Promueve de forma similar el uso de patrones de diseño como DRY ("dont repeat yourself", no te repitas — escribir el código una única vez si es posible), MVC (model-view-controller) y numerosos otros.</p> + +<p>Hay por supuesto muchas diferencias debido a decisiones específicas de diseño y la naturaleza de los lenguajes.</p> + +<p>Rails se usa en sitios de perfil alto, como:<strong> </strong><a href="https://basecamp.com/">Basecamp</a>, <a href="https://github.com/">GitHub</a>, <a href="https://shopify.com/">Shopify</a>, <a href="https://airbnb.com/">Airbnb</a>, <a href="https://twitch.tv/">Twitch</a>, <a href="https://soundcloud.com/">SoundCloud</a>, <a href="https://hulu.com/">Hulu</a>, <a href="https://zendesk.com/">Zendesk</a>, <a href="https://square.com/">Square</a>, <a href="https://highrisehq.com/">Highrise</a>.</p> + +<h3 id="ASP.NET">ASP.NET</h3> + +<p><a href="http://www.asp.net/">ASP.NET</a> es un framework web de código abierto desarrollado por Microsoft para construir aplicaciones y servicios modernos. Con ASP.NET puedes crear rápidamente sitios web basados en HTML, CSS, y JavaScript, escalarlos para ser usados por milllones de usuarios y añadir fácilmente capacidades complejas como APIs web, formularios sobre datos o comunicaciones en tiempo real.</p> + +<p>Uno de los diferenciadores de ASP.NET es que está construido sobre el <a href="https://en.wikipedia.org/wiki/Common_Language_Runtime">Common Language Runtime</a> (CLR), permitiendo a los programadores escribir código ASP.NET usando cualquier lenguaje .NET soportado (C#, Visual Basic, etc.). Como muchos productos Microsoft se beneficia de herramientas excelentes (frecuentemente gratuitas), y una comunidad de desarrolladores activa, y documentación bien escrita.</p> + +<p>ASP.NET se usa por Microsoft, Xbox.com, Stack Overflow, y muchos otros.</p> + +<h3 id="Mojolicious_(Perl)">Mojolicious (Perl)</h3> + +<p><a href="http://mojolicious.org/">Mojolicious</a> es un framework web de nueva generación para el lenguaje de programación Perl.</p> + +<p>Hace tiempo en los primeros días de la Web, mucha gente aprendió Perl gracias a una magnífica biblioteca llamada <a href="https://metacpan.org/module/CGI">CGI</a>. Era lo suficientemente simple para empezar sin saber mucho sobre el lenguaje y lo suficientemente potente para mantenerte en marcha. Mojolicious implementa esta idea usando el último grito de las tecnologías.</p> + +<p>Algunas de las caracteríticas que proporciona Mojolicious son: <strong>Framework Web en tiempo real</strong>, para crecer fácilmente desde prototipos de un solo fichero hasta aplicaciones web MVC bien estructuradas; rutas RESTful, plugins, comandos, plantillas especificas de Perl, negociación de contenidos, gestión de sesiones, validación de formatos, framework de pruebas, servidor de ficheros estáticos, detección de CGI/<a href="http://plackperl.org">PSGI</a>, soporte Unicode de primera clase; Implementación cliente/servidor completamente equipada de HTTP y WebSocket con IPv6, TLS, SNI, IDNA, HTTP/SOCKS5 proxy, UNIX domain socket, Comet (long polling), keep-alive, connection pooling, timeout, cookie, y soporte de compresión multipart y gzip; parseadores JSON y HTML/XML y generadores con soporte de selector CSS; Muy limpio, portable y API orientada a objetos y Perl puro sin magia oculta; Código fresco basado en años de experiencia, gratis y de código abierto.</p> + +<h2 id="Sumario">Sumario</h2> + +<p>Este artículo ha mostrado que los frameworks web pueden hacer fácil el desarrollo y mantenimiento del código de lado servidor. También ha proporcionado una visión general de alto nivel de unos pocos frameworks más populares y debatido los criterios para elegir el framework para una aplicación web. Deberías tener en este momento una idea de cómo elegir un framework web para tu propio desarrollo de lado servidor. Si no, no te preocupes — más tarde a lo largo del curso te daremos tutoriales detallados de Django y Express para darte algo de experiencia de funcionamiento real con un framework web.</p> + +<p>Para el próximo artículo de este módulo cambiaremos de dirección ligeramente y consideraremos la seguridad web.</p> + +<p>{{PreviousMenuNext("Learn/Server-side/First_steps/Client-Server_overview", "Learn/Server-side/First_steps/Website_security", "Learn/Server-side/First_steps")}}</p> + +<p> </p> + +<h2 id="En_este_modulo">En este modulo</h2> + +<ul> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Introducci%C3%B3n">Introducción al lado servidor </a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Vision_General_Cliente_Servidor">Visión general Cliente-Servidor</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/Web_frameworks">Frameworks web de lado servidor</a></li> + <li><a href="https://developer.mozilla.org/es/docs/Learn/Server-side/Primeros_pasos/seguridad_sitios_web">Seguridad de sitios Web</a></li> +</ul> + +<p> </p> diff --git a/files/es/learn/using_github_pages/index.html b/files/es/learn/using_github_pages/index.html new file mode 100644 index 0000000000..81a7138430 --- /dev/null +++ b/files/es/learn/using_github_pages/index.html @@ -0,0 +1,103 @@ +--- +title: ¿Cómo se utiliza Github pages? +slug: Learn/Using_Github_pages +translation_of: Learn/Common_questions/Using_Github_pages +--- +<p class="summary"><a href="https://github.com/">GitHub</a> es un sitio "social coding". Te permite subir repositorios de código para almacenarlo en el <strong>sistema de control de versiones</strong> <a href="http://git-scm.com/">Git</a>. Tu puedes colaborar en proyectos de código, y el sistema es código abierto por defecto, lo que significa que cualquiera en el mundo puede encontrar tu código en GitHub, usarlo, aprender de el, y mejorarlo. ¡Tú puedes hacer eso con el código de otras personas tambien! Este artículo provee una guía básica para publicar contenido usando la característica gh-pages de Github.</p> + +<h2 id="Publicando_contenido">Publicando contenido</h2> + +<p>Github es una comunidad muy importante y útil para involucrarse, y Git/GitHub es un <a href="http://git-scm.com/book/en/v2/Getting-Started-About-Version-Control">sistema de control de versiones</a> muy popular — la mayoría de las empresas de tecnología ahora lo utilizan en su flujo de trabajo. GitHub tiene una característica muy útil llamada <a href="https://pages.github.com/">GitHub pages</a>, que te permite publicar el código del sitio en vivo en la Web.</p> + +<h3 id="Configuración_básica_de_Github"><span class="short_text" id="result_box" lang="es"><span class="hps">Configuración básica</span> de <span class="hps">Github</span></span></h3> + +<ol> + <li>Primero que todo, <a href="http://git-scm.com/downloads">instala Git</a> en tu máquina. <span id="result_box" lang="es"><span class="hps">Este es el</span> <span class="hps">software del sistema</span> <span class="hps">de control de versiones</span> <span class="hps">subyacente en el que</span> <span class="hps">GitHub</span> <span class="hps">funciona</span><span>.</span></span></li> + <li>Seguido, <a href="https://github.com/join">Regístrate para una cuenta de GitHub</a>. Es simple y fácil.</li> + <li>Una vez te hayas registrado, inicia sesión en <a href="https://github.com">github.com</a> con tu nombre de usuario y contraseña.</li> +</ol> + +<h3 id="Preparando_tu_código_para_subirlo">Preparando tu código para subirlo</h3> + +<p>Tú puedes almacenar cualquier código que tu quieras en un repositorio de Github, pero para usar la característica páginas de Github con pleno efecto, tu código debe estar estructurado como un sitio web típico, por ejemplo que el punto de entrada primario sea un archivo HTML llamado<code> index.html</code>.</p> + +<p>La otra cosa que necesitas hacer <span id="result_box" lang="es"><span class="hps">antes de seguir adelante</span> <span class="hps">es</span> <span class="hps">inicializar</span> <span class="hps">el directorio de</span> <span class="hps">código como</span> <span class="hps">un repositorio</span> <span class="hps">Git</span></span>. para hacer esto:</p> + +<ol> + <li>Apunta la línea de comandos a tu directorio <code>test-site</code> (<span id="result_box" lang="es"><span class="hps">o como se</span> <span class="hps">llame</span> <span class="hps">el directorio que contiene</span> tu<span class="hps"> sitio web</span></span>). Para esto, usa el comando <code>cd</code> (Es decir "<em>cambio de</em> <em>d</em>irectorio"). Esto es lo que deberías digitar si has puesto tu sitio web en un directorio llamado <code>test-site</code> en tu escritorio: + + <pre class="brush: bash">cd Desktop/test-site</pre> + </li> + <li>Cuando la línea comandos está apuntando hacia el interior del directorio de tu sitio web, digita el siguiente comando, que le dice a la herramienta <code>git</code> para convertir el directorio en un repositorio git:</li> + <li> + <pre class="brush: bash">git init</pre> + </li> +</ol> + +<h4 id="An_aside_on_command_line_interfaces">An aside on command line interfaces</h4> + +<p>La mejor manera de subir tu código a Github es mediante la linea de comandos — esta es una ventana donde tú escribe <span id="result_box" lang="es"><span class="hps">comandos</span> <span class="hps">para hacer cosas como</span> <span class="hps">crear</span> <span class="hps">archivos y ejecutar programas</span></span>, en lugar de hacer clic dentro de una interfaz de usuario. Se verá algo como esto:</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/9483/command-line.png" style="display: block; height: 478px; margin: 0px auto; width: 697px;"></p> + +<div class="note"> +<p><strong>Nota</strong>: Tú también podrías considerar una <a href="http://git-scm.com/downloads/guis">interfaz gráfica de usuario de Git</a> para hacer el mismo trabajo, si te sientes incómodo con la linea de comandos.</p> +</div> + +<p><span id="result_box" lang="es"><span class="hps">Cada sistema operativo</span> <span class="hps">viene con</span> <span class="hps">una herramienta de línea</span> <span class="hps">de comandos</span><span>:</span></span></p> + +<ul> + <li><strong>Windows</strong>: <strong>Command Prompt</strong> se puede acceder pulsando la tecla Windows, tipeando <em>Command Prompt</em>, Y elegirlo de la lista que aparece. Nota que Windows tiene sus propias convenciones de comando diferentes de Linux y OS X, así que los comandos abajo pueden variar en su máquina.</li> + <li><strong>OS X</strong>: <strong>Terminal</strong> se puede encontrar en <em>Aplicaciones > Utilidades</em>.</li> + <li><strong>Linux</strong>: Por lo general, puede extraer una terminal con <em>Ctrl + Alt + T</em>. <span class="short_text" id="result_box" lang="es"><span class="hps">Si</span> <span class="hps">eso no funciona</span></span>, busca <strong>Terminal</strong> en una barra de aplicaciones o menú.</li> +</ul> + +<p><span class="short_text" id="result_box" lang="es"><span class="hps">Esto puede</span> <span class="hps">parecer un poco</span> espantoso<span class="hps"> al principio</span></span>, pero no te preocupes — que pronto conseguiras la <span id="result_box" lang="es"><span class="hps">caída de</span> <span class="hps">los conceptos básicos</span></span>. Tú<span id="result_box" lang="es"><span class="hps"> le dices a</span> <span class="hps">la computadora que </span><span class="hps">haga algo en la</span> <span class="hps">terminal, digitando</span> <span class="hps">un comando y</span> <span class="hps">oprimiendo la tecla Enter</span><span>,</span> <span class="hps">como se ha visto</span> <span class="hps">anteriormente.</span></span></p> + +<h3 id="Creando_un_repositorio_para_tu_código">Creando un repositorio para tu código</h3> + +<ol> + <li> + <p><span id="result_box" lang="es"><span class="hps">A continuación</span></span>, tu necesitas crear un nuevo repositorio para colocar tus archivos en el. Has clic en el signo más (+) en la parte superior derecha de la página de inicio de GitHub, luego escoge <em>Nuevo Repositorio</em>.</p> + </li> + <li><span class="short_text" id="result_box" lang="es"><span class="hps">En esta página,</span></span> en la caja <em>Nombre del Repositorio</em>, digita el nombre para tu repositorio de código, por ejemplo <em>my-repository</em>.</li> + <li>También llena una descripción <span class="short_text" id="result_box" lang="es"><span class="hps">para decir lo que</span> tu <span class="hps">repositorio</span> <span class="hps">va a</span> <span class="hps">contener</span></span>. Tu pantalla debe mostrar algo como esto:<br> + <img alt="" src="https://mdn.mozillademos.org/files/12143/create-new-repo.png" style="display: block; height: 548px; margin: 0px auto; width: 800px;"></li> + <li>Has Clic en <em>Crear repositorio</em>; Esto debería llevarte a la siguiente página: <br> + <img alt="" src="https://mdn.mozillademos.org/files/12141/github-repo.png" style="display: block; height: 520px; margin: 0px auto; width: 800px;"></li> +</ol> + +<h3 id="Subiendo_tus_archivos_a_GitHub">Subiendo tus archivos a GitHub</h3> + +<ol> + <li>En la página actual, tú estás interesado en la sección <em>…o empujar un repositorio existente desde la línea de comandos</em>. Tú deberias ver dos lineas de código listado en esta sección. <span class="short_text" id="result_box" lang="es"><span class="hps">Copia</span> <span class="hps">la totalidad de la</span> <span class="hps">primera</span> <span class="hps">línea</span></span>, pégala en la línea de comandos, presiona la tecla Enter. El comando debería mostrarte algo como esto: + + <pre class="copyable-terminal-content js-zeroclipboard-target"><span class="user-select-contain">git remote add origin <span class="js-live-clone-url">https://github.com/chrisdavidmills/my-repository.git</span></span></pre> + </li> + <li><span id="result_box" lang="es"><span class="hps">A continuación</span></span>, digita los siguientes dos comandos, presionando Enter despues de cada uno. Estos preparán el código para subirlo a GitHub, y pida a GIt que administre estos archivos. + <pre class="brush: bash">git add --all +git commit -m 'adding my files to my repository'</pre> + </li> + <li>Por último,<span class="short_text" id="result_box" lang="es"><span class="hps"> empuja el</span> <span class="hps">código</span> <span class="hps">hasta</span></span> GitHub yendo a la página de GitHub en la que estas e ingresando en la terminal el segundo de los dos comandos que vimos <em>…o empuje un repositorio existente desde la sección de línea de comandos</em>: + <pre class="brush: bash">git push -u origin master</pre> + </li> + <li>Ahora necesitas crear la rama gh-pages de tu repositorio; actualiza la página actual <span id="result_box" lang="es"><span class="hps">y verá</span> <span class="hps">una página</span> del <span class="hps">repositorio</span> <span class="hps">algo así como</span> <span class="hps">la de abajo.</span></span> Tú necesitas presionar el boton que dice <em>Branch: <strong>master</strong></em>, digita <em>gh-pages</em> en el campo de texto, luego presiona el boton azul que dice <em>Create branch: gh-pages</em>. Esto crea una rama de código especial llamada gh-pages que es publicada en una ubicación especial. La URL toma la forma <em>username.github.io/my-repository-name</em>, asi en mi caso de ejemplo, la URL debería ser <em>https://chrisdavidmills.github.io/my-repository</em>. La página mostrada es la página index.html.<br> + <img alt="" src="https://mdn.mozillademos.org/files/12145/repo-site.png" style="display: block; margin: 0px auto;"></li> + <li>Navega tu dirección web de GitHub pages en un nuevo ta del navegador, y tu deberias ver tu sitio en linea! Mandalo <span id="result_box" lang="es"><span class="hps">por correo electrónico a</span> <span class="hps">tus</span> <span class="hps">amigos</span> <span class="hps">y muestra tu</span> <span class="hps">dominio</span><span>.</span></span></li> +</ol> + +<div class="note"> +<p><strong>Nota</strong>: <span class="short_text" id="result_box" lang="es"><span class="hps">Si te atascas</span></span>, la <a href="https://pages.github.com/">página de inicio de GitHub Pages</a> <span class="short_text" id="result_box" lang="es"><span class="hps">también</span> <span class="hps">es</span> <span class="hps">muy</span> <span class="hps">útil</span></span>.</p> +</div> + +<h3 id="Un_mayor_conocimiento_de_GitHub"><span class="short_text" id="result_box" lang="es"><span class="hps">Un mayor conocimiento</span> <span class="hps">de GitHub</span></span></h3> + +<p><span id="result_box" lang="es"><span>Si deseas realizar más cambios en su sitio de prueba y cargarlos en GitHub, simplemente tendrás que realizar el cambio en tus archivos como antes.</span> <span>A continuación, debes introducir los siguientes comandos (pulsando Intro después de cada uno) para empujar los cambios a GitHub</span></span>:</p> + +<pre>git add --all +git commit -m 'another commit' +git push</pre> + +<p>Puedes reemplazar <em>otro commit</em> con un mensaje más adecuado para describir qué cambio acaba de hacer.</p> + +<p>Apenas hemos arañado la superficie de Git.Para obtener más información, comience con el <a href="https://help.github.com/index.html">sitio de ayuda de GitHub</a>.</p> |