diff options
Diffstat (limited to 'files/es/web/api')
109 files changed, 10491 insertions, 1748 deletions
diff --git a/files/es/web/api/animation/animación/index.html b/files/es/web/api/animation/animation/index.html index 770036b76d..770036b76d 100644 --- a/files/es/web/api/animation/animación/index.html +++ b/files/es/web/api/animation/animation/index.html diff --git a/files/es/web/api/animation/tiempoactual/index.html b/files/es/web/api/animation/currenttime/index.html index acd56f9170..acd56f9170 100644 --- a/files/es/web/api/animation/tiempoactual/index.html +++ b/files/es/web/api/animation/currenttime/index.html diff --git a/files/es/web/api/animation/terminado/index.html b/files/es/web/api/animation/finished/index.html index 5d321ba012..5d321ba012 100644 --- a/files/es/web/api/animation/terminado/index.html +++ b/files/es/web/api/animation/finished/index.html diff --git a/files/es/web/api/battery_status_api/index.html b/files/es/web/api/battery_status_api/index.html new file mode 100644 index 0000000000..9cdc7259be --- /dev/null +++ b/files/es/web/api/battery_status_api/index.html @@ -0,0 +1,39 @@ +--- +title: API de Estado de Bateria +slug: WebAPI/Estado_de_Bateria +tags: + - API + - Apps + - Firefox OS + - Mobile +translation_of: Web/API/Battery_Status_API +--- +<p>La <strong>API de Estado de Batería</strong>, también conocida como "<strong>Battery API</strong>", provee información acerca del sistema de carga de la batería y permite notificar mediante eventos que son enviados cuando el nivel de la batería cambia. Este puede ser usado para ajustar el uso de recursos por parte de una aplicación y evitar un gasto innecesario de energía cuando la batería esta baja o para guardar cambios en un archivo antes de que la batería se agote y así prevenir perdida de información.</p> +<p>La API de Estado de Batería se puede extender mediante {{domxref("window.navigator")}} con una propiedad {{domxref("window.navigator.battery")}} que pertenece al objeto {{domxref("BatteryManager")}} y agrega algunos nuevos eventos que usted puede recibir en el monitor de estado de la batería.</p> +<h2 id="Ejemplo">Ejemplo</h2> +<p>En este ejemplo, observamos los cambios en el estado de la carga (este o no conectado y cargando) y en el nivel de la batería. Esto se hace escuchando el evento {{event("chargingchange")}} y el evento {{event("levelchange")}} respectivamente.</p> +<pre class="brush: js">var battery = navigator.battery || navigator.mozBattery || navigator.webkitBattery; + +function updateBatteryStatus() { + console.log("Battery status: " + battery.level * 100 + " %"); + + if (battery.charging) { + console.log("Battery is charging"); + } +} + +battery.addEventListener("chargingchange", updateBatteryStatus); +battery.addEventListener("levelchange", updateBatteryStatus); +updateBatteryStatus(); +</pre> +<p>Vea también: <a class="external" href="http://dev.w3.org/2009/dap/system-info/battery-status.html#introduction">El ejemplo en las especificaciones</a></p> +<h2 id="Especificaciones">Especificaciones</h2> +<p>{{page("/en-US/docs/Web/API/BatteryManager","Specifications")}}</p> +<h2 id="Compatibilidad_del_Navegador">Compatibilidad del Navegador</h2> +<p>{{page("/en-US/docs/Web/API/BatteryManager","Browser_compatibility")}}</p> +<h2 id="Vea_también">Vea también</h2> +<ul> + <li><a class="external" href="http://hacks.mozilla.org/2012/02/using-the-battery-api-part-of-webapi/">Hacks blog post - Usando la API de Batería</a></li> + <li>{{domxref("BatteryManager")}}</li> + <li>{{domxref("window.navigator.battery","navigator.battery")}}</li> +</ul> diff --git a/files/es/web/api/canvas_api/a_basic_ray-caster/index.html b/files/es/web/api/canvas_api/a_basic_ray-caster/index.html new file mode 100644 index 0000000000..7917541554 --- /dev/null +++ b/files/es/web/api/canvas_api/a_basic_ray-caster/index.html @@ -0,0 +1,59 @@ +--- +title: A basic ray-caster +slug: Web/HTML/Canvas/A_basic_ray-caster +tags: + - Avanzado + - Canvas + - Ejemplo + - Espanol(2) + - Gráficos(2) + - HTML + - Necesita traducción + - Web +translation_of: Web/API/Canvas_API/A_basic_ray-caster +--- +<div>{{CanvasSidebar}}</div> + +<div class="summary"> +<p>Este artículo proporciona un interesante ejemplo de la vida real usando el elemento {{HTMLElement("canvas")}} para renderizar un sencillo entorno 3D usando una técnica de render llamada ray-casting.</p> +</div> + +<p>{{EmbedGHLiveSample("canvas-raycaster/index.html", 900, 300)}}</p> + +<p><strong><a href="http://mdn.github.io/canvas-raycaster/">Abrir en una nueva ventana</a></strong></p> + +<h2 id="Why.3F" name="Why.3F">¿Por qué?</h2> + +<p> </p> + +<p>Después de darme cuenta, para mi satisfacción, de que el ingenioso elemento <canvas> sobre el que había estado leyendo, no sólo iba a recibir soporte por parte de Firefox, sino que <strong>ya estaba</strong> soportado por la versión actual de Safari, así que tenía que ponerme manos a la obra y hacer un pequeño experimento.</p> + +<p>El <a href="https://developer.mozilla.org/en-US/docs/Canvas_tutorial">tutorial</a> y el <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API">resumen</a> que encontré en la MDN son geniales, pero nadie había escrito nada (todavía) sobre animación, así que pensé que sería una buena oportunidad para portar un sencillo raycaster en el que había trabajado hacía tiempo y comprobar qué tipo de rendimiento podía esperar de un buffer de pixeles controlado por JavaScript.</p> + +<h2 id="How.3F" name="How.3F">¿Cómo?</h2> + +<p>La idea es sencilla, usar {{domxref("WindowTimers.setInterval","setInterval()")}} con un retraso arbitrario que se corresponde con la velocidad de fotogramas deseada. Por cada llamada al intervalo se ejecutará una función que volverá a pintar el elemento <canvas> en el que se muestra la vista actual del usuario. Sé que podría haber empezado con un ejemplo más simple, pero creo que el <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">tutorial</a> sobre <canvas> vale para eso, y quería ver si podía hacer esto.</p> + +<p>Continuemos, por cada actualización, el raycaster comprueba si has presionado alguna tecla, si no has presionado ninguna se mantendrán los cálculos para ahorrar tiempo de ejecución. Si se ha presionado alguna tecla, el <canvas> es borrado, el suelo y el cielo son pintados, la posición y la orientación de la cámara son actualizados, y los rayos son lanzados. Según van intersectando los rayos con las paredes se van pintando líneas verticales de pared del color de la pared con la que han colisionado, mezcladas con una versión más oscura del color en función de la distancia a la que se encuentra la pared. La altura de la línea vertical depende directamente de la distancia a la que el rayo es interesectado, dibujándose centrada con respecto la línea del horizonte.</p> + +<p>El código que he terminado usando es una amalgama regurgitada del código que aparece en los capítulos sobre raycasting del libro de André LaMothe <em>Tricks of the Game Programming Gurus</em> y una <a class="external" href="http://www.shinelife.co.uk/java-maze/">versión en java de un raycaster</a> que encontré online, a su vez pasado por el filtro de mi pulsión a renombrar todo para que tenga sentido para mí y todo el chapuceo necesario para que las cosas funcionen bien.</p> + +<h2 id="Results" name="Results">Resultados</h2> + +<p>El <canvas> en Safari 2.0.1 rindió sorprendentemente bien. Renderizando columnas de 8 pixeles de ancho, puedo correr una ventana de 320 x 240 a 24 FPS en mi Apple Mini. Firefox 1.5 Beta 1 es incluso más rápido; puedo correr una ventana de 320 x 240 a 24 FPS con columnas de 4 píxeles de ancho. No es exactamente un nuevo miembro de la familia de ID Software, pero es bastante decente teniendo en cuenta que es un entorno completamente interpretado, y que no me he tenido que preocupar de reservar memoria, ni modos de vídeo o escribir rutinas en ensamblador. Aún así el código intenta ser lo más eficiente posible, usando tablas de acceso rápido para valores precalculados, pero no soy ningún gurú de la optimización, así que seguramente haya varias cosas que se puedan escribir más rápido.</p> + +<p>Además, deja bastante que desear en términos de intentar convertir esto en un motor de juego - no hay texturas en las paredes, no hay sprites, no hay puertas, ni siquiera hay teletransportadores que te permitan ir a otro nivel. Pero tengo bastante confianza en que todas esas cosas se podrían añadir con el suficiente tiempo disponible. La API de canvas soporta copiado de píxeles de imágenes, así que tener texturas parece bastante factible. Dejaré esto para otro artículo, seguramente para otra persona. =)</p> + +<h2 id="The_RayCaster" name="The_RayCaster">El ray-caster</h2> + +<p>El gente tan maravillosa que hay aquí han copiado manualmente mis archivos así vosotros podéis echarle un <a href="http://mdn.github.io/canvas-raycaster/">vistazo</a>, y para vuestro disfrute he puesto los archivos individuales como listados de código (ver abajo).</p> + +<p>¡Así que aquí lo tenéis, arrancad Safari 1.3+ o Firefox 1.5+ o cualquier otro navegador que soporte el elemento <code><canvas></code> y a disfrutar!<br> + <br> + <small><a href="https://github.com/mdn/canvas-raycaster/blob/master/input.js">input.js</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/Level.js">Level.js</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/Player.js">Player.js</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/index.html">RayCaster.html</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/RayCaster.js">RayCaster.js</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/trace.css">trace.css</a> | <a href="https://github.com/mdn/canvas-raycaster/blob/master/trace.js">trace.js</a> </small></p> + +<h2 id="See_also" name="See_also">Ver también</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/Canvas_API/Tutorial">Tutorial de canvas</a></li> +</ul> diff --git a/files/es/web/api/canvas_api/index.html b/files/es/web/api/canvas_api/index.html new file mode 100644 index 0000000000..dfdde2bf63 --- /dev/null +++ b/files/es/web/api/canvas_api/index.html @@ -0,0 +1,170 @@ +--- +title: API Canvas +slug: Web/HTML/Canvas +tags: + - API + - Canvas + - JavaScript + - Referencia + - introducción +translation_of: Web/API/Canvas_API +--- +<div>{{CanvasSidebar}}</div> + +<p class="summary">Añadido en <a href="/es/docs/HTML/HTML5">HTML5</a>, el <strong>elemento HTML {{HTMLElement("canvas")}}</strong> se puede usar para dibujar gráficos mediante scripting en <a href="/es/docs/Web/JavaScript">JavaScript</a>. Por ejemplo, se puede usar para hacer gráficas, composiciones fotográficas, crear animaciones, o incluso procesado o renderizado de vídeo en tiempo real.</p> + +<p>Las aplicaciones de Mozilla soportan <code><canvas></code> desde Gecko 1.8 (es decir, <a href="/es/docs/Mozilla/Firefox/Releases/1.5">Firefox 1.5</a>). El elemento fue inicialmenmte presentado por Apple para el Dashboard de OS X y Safari. Internet Explorer soporta <code><canvas></code> desde la versión 9 en adelante; para versiones anteriores de IE, se puede añadir soporte para <code><canvas></code> a una página incluyendo un script del proyecto de Google <a href="https://github.com/arv/explorercanvas">Explorer Canvas</a>. Google Chrome y Opera 9 también soportan <code><canvas></code>.</p> + +<p>El elemento <code><canvas></code> también se usa en <a href="/es/docs/Web/WebGL">WebGL</a> para dibujar gráficos 3D con aceleración por hardware en páginas web.</p> + +<h2 id="Ejemplo">Ejemplo</h2> + +<p>Esto es un trozo de código que usa el método {{domxref("CanvasRenderingContext2D.fillRect()")}}.</p> + +<h3 id="HTML">HTML</h3> + +<pre class="brush: html"><canvas id="canvas"></canvas> +</pre> + +<h3 id="JavaScript">JavaScript</h3> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); + +ctx.fillStyle = 'green'; +ctx.fillRect(10, 10, 100, 100); +</pre> + +<p>Edita este código para ver tus cambios en tiempo real en este canvas:</p> + +<div class="hidden"> +<h6 id="Código_editable">Código editable</h6> + +<pre class="brush: html"><canvas id="canvas" width="400" height="200" class="playable-canvas"></canvas> +<div class="playable-buttons"> + <input id="edit" type="button" value="Edit" /> + <input id="reset" type="button" value="Reset" /> +</div> +<textarea id="code" class="playable-code"> +ctx.fillStyle = 'green'; +ctx.fillRect(10, 10, 100, 100);</textarea> +</pre> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext("2d"); +var textarea = document.getElementById('code'); +var reset = document.getElementById('reset'); +var edit = document.getElementById('edit'); +var code = textarea.value; + +function drawCanvas() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + eval(textarea.value); +} + +reset.addEventListener('click', function() { + textarea.value = code; + drawCanvas(); +}); + +edit.addEventListener('click', function() { + textarea.focus(); +}) + +textarea.addEventListener('input', drawCanvas); +window.addEventListener('load', drawCanvas); +</pre> +</div> + +<p>{{ EmbedLiveSample('Código_editable', 700, 360) }}</p> + +<h2 id="Referencia">Referencia</h2> + +<div class="index"> +<ul> + <li>{{domxref("HTMLCanvasElement")}}</li> + <li>{{domxref("CanvasRenderingContext2D")}}</li> + <li>{{domxref("CanvasGradient")}}</li> + <li>{{domxref("CanvasImageSource")}}</li> + <li>{{domxref("CanvasPattern")}}</li> + <li>{{domxref("ImageBitmap")}}</li> + <li>{{domxref("ImageData")}}</li> + <li>{{domxref("RenderingContext")}}</li> + <li>{{domxref("TextMetrics")}}</li> + <li>{{domxref("OffscreenCanvas")}}{{experimental_inline}}</li> + <li>{{domxref("Path2D")}} {{experimental_inline}}{{domxref("ImageBitmapRenderingContext")}}{{experimental_inline}}</li> +</ul> +</div> + +<p>Las interfaces relacionadas con <code>WebGLRenderingContext</code> están en <a href="/es/docs/Web/WebGL" title="/en-US/docs/Web/WebGL">WebGL</a>.</p> + +<p>{{domxref("CanvasCaptureMediaStream")}} está relacionado..</p> + +<h2 id="Guías_y_tutoriales">Guías y tutoriales</h2> + +<dl> + <dt><a href="/es/docs/Web/API/Canvas_API/Tutorial">Tutorial Canvas</a></dt> + <dd>Tutorial exhaustivo que cubre tanto el uso básico de <code><canvas></code> como sus características avanzadas.</dd> + <dt><a href="/es/Add-ons/Code_snippets/Canvas">Fragmentos de código: Canvas</a></dt> + <dd>Algunos fragmentos de código orientados al desarrollador de extensiones usando <code><canvas></code>.</dd> + <dt><a href="/es/docs/Web/API/Canvas_API/A_basic_ray-caster">Demo: Un laberinto básico</a></dt> + <dd>Una demo de una animación de laberinto usando canvas.</dd> + <dt><a href="/es/docs/Web/API/Canvas_API/Drawing_DOM_objects_into_a_canvas">Dibujar objetos DOM en un canvas</a></dt> + <dd>Cómo dibujar contenido DOM, como elementos HTML, en un canvas.</dd> + <dt><a href="/es/docs/Web/API/Canvas_API/Manipulating_video_using_canvas">Manipulación de vídeo usando canvas</a></dt> + <dd>Combinando {{HTMLElement("video")}} y {{HTMLElement("canvas")}} para manipular datos de vídeo en tiempo real.</dd> +</dl> + +<h2 id="Recursos">Recursos</h2> + +<h3 id="Genéricos">Genéricos</h3> + +<ul> + <li><a href="http://joshondesign.com/p/books/canvasdeepdive/title.html">Profundizando en HTML5 Canvas</a></li> + <li><a href="http://bucephalus.org/text/CanvasHandbook/CanvasHandbook.html">Manual de Canvas</a></li> +</ul> + +<h3 id="Librerías">Librerías</h3> + +<ul> + <li><a href="http://fabricjs.com">Fabric.js</a> es una librería open-source para canvas con capacidad de parsear SVG.</li> + <li><a href="https://github.com/ericdrowell/KineticJS">Kinetic.js</a> es una librería open-source de canvas enfocada en la interactividad para aplicaciones móviles y de escritorio.</li> + <li><a href="http://paperjs.org/">Paper.js</a> es un framework para gráficos vectoriales open source que funciona sobre Canvas HTML5.</li> + <li><a href="http://origamijs.com/docs/">Origami.js</a> es una librería ligera open-source para canvas.</li> + <li><a href="http://libcanvas.github.com/">libCanvas</a> es un framework ligero y potente para canvas.</li> + <li><a href="http://processingjs.org">Processing.js</a> es un port de PVL (Processing visualization language).</li> + <li><a href="https://playcanvas.com/">PlayCanvas</a> es un motor open source de juegos.</li> + <li><a href="http://www.pixijs.com/">Pixi.js</a> es un motor open source de juegos.</li> + <li><a href="http://www.liquidx.net/plotkit/">PlotKit</a> es una librería para hacer gráficas.</li> + <li><a class="link-https" href="https://github.com/jeremyckahn/rekapi">Rekapi</a> es una API para animación por frames para Canvas.</li> + <li><a href="http://senchalabs.github.com/philogl/">PhiloGL</a> es un framework WebGL para visualización de datos, programación creativa y desarrollo de juegos.</li> + <li><a href="http://thejit.org/">JavaScript InfoVis Toolkit</a> crea visualizaciones de datos 2D interactivas para Web.</li> + <li><a href="http://www.createjs.com/easeljs">EaselJS</a> es una librería open source/libre que facilita el uso de canvas para arte y juegos</li> + <li><a href="http://scrawl.rikweb.org.uk/">Scrawl-canvas</a> es otra librería open-source javascript para crear y manipular elementos canvas en 2D</li> + <li><a href="https://www.patrick-wied.at/static/heatmapjs/">heatmap.js</a> es una librería open-source para crear mapas (heatmaps)</li> +</ul> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Especificación</th> + <th scope="col">Estado</th> + <th scope="col">Comentarios</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('HTML WHATWG', 'scripting.html#the-canvas-element', '<canvas>')}}</td> + <td>{{Spec2('HTML WHATWG')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="/es/docs/Web/WebGL">WebGL</a></li> +</ul> diff --git a/files/es/web/api/canvas_api/manipulating_video_using_canvas/index.html b/files/es/web/api/canvas_api/manipulating_video_using_canvas/index.html new file mode 100644 index 0000000000..a3ae61673d --- /dev/null +++ b/files/es/web/api/canvas_api/manipulating_video_using_canvas/index.html @@ -0,0 +1,126 @@ +--- +title: Manipular video por medio de canvas +slug: Web/HTML/anipular_video_por_medio_de_canvas +tags: + - Canvas + - Firefox 3.5 + - Video + - para_revisar +translation_of: Web/API/Canvas_API/Manipulating_video_using_canvas +--- +<p><span class="goog-gtc-unit" id="goog-gtc-unit-2"><span class="goog-gtc-translatable goog-gtc-from-tm goog-gtc-from-tm-score-100" dir="ltr" style="">{{ fx_minversion_header (3.5) }}</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-3"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Al combinar las capacidades del elemento </span></span><a class="internal" href="/En/HTML/Element/Video" title="En/HTML/Element/Video"><code>video</code></a><span class="goog-gtc-unit" id="goog-gtc-unit-3"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style=""> introducido en Firefox 3.5 con un elemento </span></span><a class="internal" href="/en/HTML/Canvas" title="En/Canvas"><code>canvas</code></a><span class="goog-gtc-unit" id="goog-gtc-unit-3"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style=""> , puedes manipular los datos de video en tiempo real para incorporar una variedad de efectos visuales que se mostrarán en el video.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-4"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Este artículo, adaptado de <a class="external" href="http://blog.mozbox.org/post/2009/02/25/video-canvas%3A-special-effects" title="http://blog.mozbox.org/post/2009/02/25/video-canvas:-special-effects">esta entrada del blog</a> de Paul Rouget, muestra cómo realizar una inserción croma (también conocida como el "efecto pantalla verde") utilizando el código JavaScript.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-5"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style=""><a href="/samples/video/chroma-key/index.xhtml" title="samples/video/chroma-key/index.xhtml">Ver este ejemplo en vivo</a> .</span></span></p> +<h2 id="El_contenido_del_documento"><span class="goog-gtc-unit" id="goog-gtc-unit-6"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">El contenido del documento</span></span></h2> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-7"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El documento XHTML que se utiliza para representar este contenido se muestra a continuación.</span></span></p> +<pre class="brush: html"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" + "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head> + <style> + body { + background: black; + color:#CCCCCC; + } + #c2 { + background-image: url(foo.png); + background-repeat: no-repeat; + } + div { + float: left; + border :1px solid #444444; + padding:10px; + margin: 10px; + background:#3B3B3B; + } + </style> + <script type="text/javascript;version=1.8" src="main.js"></script> + </head> + + <body onload="processor.doLoad()"> + <div> + <video id="video" src="video.ogv" controls="true"/> + </div> + <div> + <canvas id="c1" width="160" height="96"/> + <canvas id="c2" width="160" height="96"/> + </div> + </body> +</html> +</pre> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-42"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Los puntos clave a tener en cuenta son:</span></span></p> +<ol> + <li><span class="goog-gtc-unit" id="goog-gtc-unit-43"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Este documento establece dos elemento <a class="internal"><code>canvas</code></a> , con los identificadores de <code>c1</code> y <code>c2</code> .</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-44"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Canvas <code>c1</code> se utiliza para mostrar la imagen actual del video original, mientras que <code>c2</code> se utiliza para mostrar el video después de realizar la manipulación con el efecto croma; <code>c2</code> se carga previamente con la imagen fija que se utilizará para sustituir el fondo verde en el video.</span></span></li> + <li><span class="goog-gtc-unit" id="goog-gtc-unit-45"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El código JavaScript es importado de un script llamado <code>main.js</code> ; este script utiliza JavaScript 1.8 características, de modo que la versión se especifica en la línea 22 al importar la secuencia de comandos.</span></span></li> + <li><span class="goog-gtc-unit" id="goog-gtc-unit-46"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Cuando se carga el documento, se ejecuta el método <code>processor.doLoad()</code> de <code>main.js</code>.</span></span></li> +</ol> +<h2 id="El_código_JavaScript"><span class="goog-gtc-unit" id="goog-gtc-unit-47"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">El código JavaScript</span></span></h2> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-48"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">El código JavaScript en <code>main.js</code> consta de tres métodos.</span></span></p> +<h3 id="Inicializar_el_reproductor_de_croma"><span class="goog-gtc-unit" id="goog-gtc-unit-49"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Inicializar el reproductor de croma</span></span></h3> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-50"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El método <code>doLoad()</code> se llama cuando el documento XHTML se carga inicialmente.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-51"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">La función de este método es preparar las variables necesarias para el código de procesamiento del croma y la creación de un detector de eventos para que podamos detectar cuándo inicia el usuario la reproducción del video.</span></span></p> +<pre class="brush: js"> doLoad: function() { + this.video = document.getElementById("video"); + this.c1 = document.getElementById("c1"); + this.ctx1 = this.c1.getContext("2d"); + this.c2 = document.getElementById("c2"); + this.ctx2 = this.c2.getContext("2d"); + let self = this; + this.video.addEventListener("play", function() { + self.width = self.video.videoWidth / 2; + self.height = self.video.videoHeight / 2; + self.timerCallback(); + }, false); + }, +</pre> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-65"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Este código obtiene referencias a los elementos del documento XHTML que son de particular interés, a saber, el elemento <code>video</code> y los dos elementos <code>canvas</code>.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-66"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">También recupera las referencias a los contextos gráficos para cada uno de los dos elementos canvas.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-67"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Estos serán utilizados cuando estamos haciendo de verdad el efecto croma.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-68"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Luego <code>addEventListener()</code> es llamado para empezar a ver el elemento <code>video</code> de forma que podamos obtener una notificación cuando el usuario presione el botón de reproducción en el video.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-69"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">En respuesta al usuario que inicia la reproducción, el código obtiene la anchura y la altura de video, reduciendo a la mitad cada uno (vamos a reducir a la mitad el tamaño del video, cuando llevamos a cabo la manipulación efecto croma). A continuación, llama al método <code>timerCallback()</code> para iniciar el visionado del video y la computación del efecto visual.</span></span></p> +<h3 id="La_devolución_de_llamada_del_temporizador"><span class="goog-gtc-unit" id="goog-gtc-unit-70"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">La devolución de llamada del temporizador</span></span></h3> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-71"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">La devolución de llamada del temporizador se llama inicialmente cuando el video comienza a reproducirse (cuando tiene lugar el evento "reproducir"), a continuación, toma la responsabilidad por la que se establece a sí mismo para ser llamado periódicamente, a fin de poner en marcha el efecto croma para cada imagen.</span></span></p> +<pre class="brush: js"> timerCallback: function() { + if (this.video.paused || this.video.ended) { + return; + } + this.computeFrame(); + let self = this; + setTimeout(function () { + self.timerCallback(); + }, 0); + }, +</pre> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-82"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Lo primero que la devolución de llamada hace es comprobar si el video se está aún reproduciendo, y si no lo está, la devolución de llamada regresa inmediatamente sin hacer nada.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-83"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">A continuación, llama al método <code>computeFrame()</code>, que lleva a cabo la manipulación del efecto croma en la imagen de video actual.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-84"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Lo último que la devolución de llamada hace es llamar a <code>setTimeout()</code> para programarse para ser llamado lo más pronto posible.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-85"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">En el mundo real, es probable que programes esto en función de la velocidad de fotogramas del video.</span></span></p> +<h3 id="Manipulación_de_los_datos_de_la_imagen_del_video"><span class="goog-gtc-unit" id="goog-gtc-unit-86"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Manipulación de los datos de la imagen del video</span></span></h3> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-87"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El método <code>computeFrame()</code>, que se muestra a continuación, se encarga de ir a buscar realmente un fotograma de datos y realizar el efecto croma.</span></span></p> +<pre class="brush: js"> computeFrame: function() { + this.ctx1.drawImage(this.video, 0, 0, this.width, this.height); + let frame = this.ctx1.getImageData(0, 0, this.width, this.height); + let l = frame.data.length / 4; + + for (let i = 0; i < l; i++) { + let r = frame.data[i * 4 + 0]; + let g = frame.data[i * 4 + 1]; + let b = frame.data[i * 4 + 2]; + if (g > 100 && r > 100 && b < 43) + frame.data[i * 4 + 3] = 0; + } + this.ctx2.putImageData(frame, 0, 0); + return; + } +</pre> +<p>Cuando esta rutina es llamada, el elemento video muestra el fotograma de datos de video más reciente, que tiene este aspecto:</p> +<p><img alt="video.png" class="internal default" src="/@api/deki/files/3282/=video.png" style="width: 320px; height: 192px;"></p> +<p>En la línea 2, ese fotograma de video se copia al contexto gráfico <code>ctx1</code> del primer lienzo, especificando como alto y ancho los valores que previamente guardamos para dibujar el fotograma a mitad de tamaño. <span class="goog-gtc-unit" id="goog-gtc-unit-104"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Ten en cuenta que puedes pasar simplemente el elemento de video al método <code>drawImage()</code> del contexto para dibujar el fotograma de video actual en dicho contexto.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-105"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">El resultado es:</span></span></p> +<p><img alt="sourcectx.png" class="internal default" src="/@api/deki/files/3284/=sourcectx.png" style="width: 160px; height: 96px;"></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-106"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Línea 3 obtiene una copia de los datos gráficos del actual fotograma de video llamando al método <code>getImageData()</code> en el primer contexto.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-107"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Esto proporciona los datos de imagen en píxeles de 32 bits sin procesar que podemos después manipular.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-108"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Línea 4 calcula el número de píxeles de la imagen al dividir entre cuatro el tamaño total de los datos de la imagen del fotograma.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-109"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">El bucle <code>for</code> que comienza en la línea 6 explora a través de los píxeles del fotograma, extrayendo los valores rojo, verde y azul para cada píxel, y compara los valores frente a números predeterminados que se utilizan para detectar la pantalla verde que se reemplazará por la imagen de fondo fija importada de <code>foo.png</code> .</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-110"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Cada píxel de datos de imagen del fotograma que se encuentra que está dentro de los parámetros que se consideran parte de la pantalla verde tiene su valor alfa reemplazado por un cero, lo que indica que el píxel es totalmente transparente.</span></span> <span class="goog-gtc-unit" id="goog-gtc-unit-111"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Como resultado, la imagen final tiene toda el área de pantalla verde 100% transparente, de modo que cuando se dibuja en el contexto de destino en la línea 13, el resultado es una superposición sobre el fondo estático.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-112"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style="">La imagen resultante tiene este aspecto:</span></span></p> +<p><img alt="output.png" class="internal default" src="/@api/deki/files/3283/=output.png" style="width: 161px; height: 96px;"></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-113"><span class="goog-gtc-translatable goog-gtc-from-human" dir="ltr" style="">Esto se hace en varias ocasiones mientras el video se reproduce, de manera que fotograma tras fotograma se procesa y se muestra con el efecto de croma.</span></span></p> +<p><span class="goog-gtc-unit" id="goog-gtc-unit-114"><span class="goog-gtc-translatable goog-gtc-from-mt" dir="ltr" style=""><a href="/samples/video/chroma-key/index.xhtml" title="samples/video/chroma-key/index.xhtml">Ver este ejemplo en vivo</a> .</span></span></p> +<h2 id="Consulta_también"><span class="goog-gtc-unit" id="goog-gtc-unit-115"><span class="goog-gtc-translatable goog-gtc-from-tm goog-gtc-from-tm-score-100" dir="ltr" style="">Consulta también</span></span></h2> +<ul> + <li><a class="internal" href="/es/Usando_audio_y_video_en_Firefox" title="es/Usando audio y video en Firefox"><span class="goog-gtc-unit" id="goog-gtc-unit-116"><span class="goog-gtc-translatable goog-gtc-from-tm goog-gtc-from-tm-score-100" dir="ltr" style="">Usar audio y video en Firefox</span></span></a></li> +</ul> +<p>{{ languages ( { "en": "En/Manipulating_video_using_canvas" } ) }}</p> diff --git a/files/es/web/api/canvas_api/tutorial/advanced_animations/index.html b/files/es/web/api/canvas_api/tutorial/advanced_animations/index.html new file mode 100644 index 0000000000..15ab72ee7f --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/advanced_animations/index.html @@ -0,0 +1,380 @@ +--- +title: Advanced animations +slug: Web/Guide/HTML/Canvas_tutorial/Advanced_animations +tags: + - Canvas + - Tutoria + - graficos +translation_of: Web/API/Canvas_API/Tutorial/Advanced_animations +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Basic_animations", "Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas")}}</div> + +<div class="summary"> +<p>En el último capítulo hicimos unas <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">animaciones básicas</a> y nos familiarizamos con varias maneras de mover cosas. En esta parte examinaremos la moción misma y agregaremos la física para hacer nuestras animaciones más avanzadas.</p> +</div> + +<h2 id="Dibujar_una_bola">Dibujar una bola</h2> + +<p>Vamos a usar una bola para nuestro estudio de la animación, entonces primero dibujamos la bola dentro del canvas. El siguente código lo configurará.</p> + +<pre class="brush: html"><canvas id="canvas" width="600" height="300"></canvas> +</pre> + +<p>Como siempre, necesitamos un entorno para dibujar. Para dibujar la bola, creamos un contenido <code>ball</code> lo cual contiene propiedades y un método <code>draw()</code>.</p> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); + +var ball = { + x: 100, + y: 100, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +ball.draw();</pre> + +<p>Nada especial aquí; la bola es en realidad un circulo sencillo y se dibuja con el método {{domxref("CanvasRenderingContext2D.arc()", "arc()")}}.</p> + +<h2 id="Agregar_velocidad">Agregar velocidad</h2> + +<p>Ya que tenemos una bola, estamos listos agregar una animación básica así como aprendimos en el <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">último capítulo</a> de esta tutoría. De nuevo, {{domxref("window.requestAnimationFrame()")}} nos ayuda controlar la animación. La bola empieza moverse por agregar un vector de velocidad a la posición. Para cada fotograma, también {{domxref("CanvasRenderingContext2D.clearRect", "clear", "", 1)}} el canvas para quitar los circulos viejos de los fotogramas anteriores.</p> + +<pre class="brush: js; highlight:[8,9,24,25]">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 2, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function draw() { + ctx.clearRect(0,0, canvas.width, canvas.height); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mouseover', function(e) { + raf = window.requestAnimationFrame(draw); +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); +}); + +ball.draw(); +</pre> + +<h2 id="Límites">Límites</h2> + +<p>Si no probamos los límites, de repente nuestra bola se agota el canvas. Necesitamos verificar si las posiciones <code>x</code> e <code>y</code> están fuera de las dimensiones del canvas y invertir la direción de los vectores de velocidad. Para hacer eso, agregamos los siguentes pasos al método <code>draw</code>:</p> + +<pre class="brush: js">if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { + ball.vy = -ball.vy; +} +if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { + ball.vx = -ball.vx; +}</pre> + +<h3 id="Primera_demo">Primera demo</h3> + +<p>Veamos como se ve en acción hasta este punto. Dirige el ratón dentro del canvas para empezar la animación.</p> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" style="border: 1px solid" width="600" height="300"></canvas></pre> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 2, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function draw() { + ctx.clearRect(0,0, canvas.width, canvas.height); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + + if (ball.y + ball.vy > canvas.height || + ball.y + ball.vy < 0) { + ball.vy = -ball.vy; + } + if (ball.x + ball.vx > canvas.width || + ball.x + ball.vx < 0) { + ball.vx = -ball.vx; + } + + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mouseover', function(e) { + raf = window.requestAnimationFrame(draw); +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); +}); + +ball.draw();</pre> +</div> + +<p>{{EmbedLiveSample("First_demo", "610", "310")}}</p> + +<h2 id="Aceleración">Aceleración</h2> + +<p>Para convertir la moción en más auténtica, puedes jugar con la velocidad, así por ejemplo:</p> + +<pre class="brush: js">ball.vy *= .99; +ball.vy += .25;</pre> + +<p>Esto reduce el vector vertical de velocidad para cada fotograma para que la bola termina rebotando en el suelo.</p> + +<div class="hidden"> +<h6 id="Second_demo">Second demo</h6> + +<pre class="brush: html"><canvas id="canvas" style="border: 1px solid" width="600" height="300"></canvas></pre> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 2, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function draw() { + ctx.clearRect(0,0, canvas.width, canvas.height); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + ball.vy *= .99; + ball.vy += .25; + + if (ball.y + ball.vy > canvas.height || + ball.y + ball.vy < 0) { + ball.vy = -ball.vy; + } + if (ball.x + ball.vx > canvas.width || + ball.x + ball.vx < 0) { + ball.vx = -ball.vx; + } + + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mouseover', function(e) { + raf = window.requestAnimationFrame(draw); +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); +}); + +ball.draw();</pre> +</div> + +<p>{{EmbedLiveSample("Second_demo", "610", "310")}}</p> + +<h2 id="Efecto_de_rezagar">Efecto de rezagar</h2> + +<p>Hasta este punto hemos limpiado los fotogramas anteriores con el método {{domxref("CanvasRenderingContext2D.clearRect", "clearRect")}}. Si reemplazas este método con un semi-transparente {{domxref("CanvasRenderingContext2D.fillRect", "fillRect")}}, puedes facilmente crear un efecto de rezagar.</p> + +<pre class="brush: js">ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; +ctx.fillRect(0, 0, canvas.width, canvas.height);</pre> + +<div class="hidden"> +<h6 id="Third_demo">Third demo</h6> + +<pre class="brush: html"><canvas id="canvas" style="border: 1px solid" width="600" height="300"></canvas></pre> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 2, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function draw() { + ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; + ctx.fillRect(0, 0, canvas.width, canvas.height); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + ball.vy *= .99; + ball.vy += .25; + + if (ball.y + ball.vy > canvas.height || + ball.y + ball.vy < 0) { + ball.vy = -ball.vy; + } + if (ball.x + ball.vx > canvas.width || + ball.x + ball.vx < 0) { + ball.vx = -ball.vx; + } + + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mouseover', function(e) { + raf = window.requestAnimationFrame(draw); +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); +}); + +ball.draw();</pre> +</div> + +<p>{{EmbedLiveSample("Third_demo", "610", "310")}}</p> + +<h2 id="Agregar_control_de_ratón">Agregar control de ratón</h2> + +<p>Para controlar la bola, podemos hacerla seguir nuestro ratón usando el evento <code><a href="/en-US/docs/Web/Reference/Events/mousemove">mousemove</a></code>, por ejemplo. El evento <code><a href="/en-US/docs/Web/Events/click">click</a></code> solta la bola y la deja rebotar de nuevo.</p> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" style="border: 1px solid" width="600" height="300"></canvas></pre> +</div> + +<pre class="brush: js">var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +var raf; +var running = false; + +var ball = { + x: 100, + y: 100, + vx: 5, + vy: 1, + radius: 25, + color: 'blue', + draw: function() { + ctx.beginPath(); + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, true); + ctx.closePath(); + ctx.fillStyle = this.color; + ctx.fill(); + } +}; + +function clear() { + ctx.fillStyle = 'rgba(255, 255, 255, 0.3)'; + ctx.fillRect(0,0,canvas.width,canvas.height); +} + +function draw() { + clear(); + ball.draw(); + ball.x += ball.vx; + ball.y += ball.vy; + + if (ball.y + ball.vy > canvas.height || ball.y + ball.vy < 0) { + ball.vy = -ball.vy; + } + if (ball.x + ball.vx > canvas.width || ball.x + ball.vx < 0) { + ball.vx = -ball.vx; + } + + raf = window.requestAnimationFrame(draw); +} + +canvas.addEventListener('mousemove', function(e) { + if (!running) { + clear(); + ball.x = e.clientX; + ball.y = e.clientY; + ball.draw(); + } +}); + +canvas.addEventListener('click', function(e) { + if (!running) { + raf = window.requestAnimationFrame(draw); + running = true; + } +}); + +canvas.addEventListener('mouseout', function(e) { + window.cancelAnimationFrame(raf); + running = false; +}); + +ball.draw(); +</pre> + +<p>Mueve la bola usando el ratón y suéltala haciendo click.</p> + +<p>{{EmbedLiveSample("Adding_mouse_control", "610", "310")}}</p> + +<h2 id="Breakout">Breakout</h2> + +<p>Este capítulo corto sólo explica algunas técnicas para crear animaciones más avanzadas. ¡Hay muchos más! ¿Qué tal agregar una raqueta, algunos ladrillos, y convertir esta demo en un partido <a href="http://en.wikipedia.org/wiki/Breakout_%28video_game%29">Breakout</a>? Visita nuestra área de <a href="/en-US/docs/Games">Game development</a> para mayor información.</p> + +<h2 id="Vea_también">Vea también</h2> + +<ul> + <li>{{domxref("window.requestAnimationFrame()")}}</li> + <li><a href="/en-US/docs/Games/Techniques/Efficient_animation_for_web_games">Efficient animation for web games</a></li> +</ul> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Basic_animations", "Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/applying_styles_and_colors/index.html b/files/es/web/api/canvas_api/tutorial/applying_styles_and_colors/index.html new file mode 100644 index 0000000000..ab76918132 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/applying_styles_and_colors/index.html @@ -0,0 +1,726 @@ +--- +title: Applying styles and colors +slug: Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors +translation_of: Web/API/Canvas_API/Tutorial/Applying_styles_and_colors +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Drawing_shapes", "Web/API/Canvas_API/Tutorial/Drawing_text")}}</div> + +<div class="summary"> +<p>En el capítulo acerca de dibujar formas, usamos unicamente los estilos de linea y de relleno por defecto. Aqui exploraremos las opciones del canvas que tenemos a nuestra disposición para hacer los dibujos un tanto más atractivos. Aprenderas como agregar diferentes colores, estilos de linea, gradiantes, patrones y sombras a tus dibujos.</p> +</div> + +<h2 id="Colors" name="Colors">Colors</h2> + +<p>Hasta ahrora nosotros solo me hemos visto metodos en el contexto de dibujo. Si quisieramos aplicar colores a las formas, hay dos importantes propiedades que podemos usar: <code>fillStyle</code> y <code>strokeStyle</code>.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.fillStyle", "fillStyle = color")}}</dt> + <dd>Configura el estilo cuando se rellenan las formas.</dd> + <dt>{{domxref("CanvasRenderingContext2D.strokeStyle", "strokeStyle = color")}}</dt> + <dd>Configura el estilo al contorno perimetral de las formas.</dd> +</dl> + +<p><code>color</code> es una cadena que representa un CSS {{cssxref("<color>")}}, un objeto gradiante, o un objeto patron. Miraremos en objetos de gradientes y patrones mas tarde. Por defecto, el color del trazo y del relleno son configurados en negro (valor de color CSS <code>#000000</code>).</p> + +<div class="note"> +<p><strong>Nota: </strong> Cuando configuras la propiedad <code>strokeStyle</code> y/o <code>fillStyle</code>, el nuevo valor llega a ser el vador por defecto para los dibujos posteriores. Para cada forma que tu quieras en un color difrente, necesitaras reasignar las propiedades anteriores.</p> +</div> + +<p>Las cadenas validas que tu pueden entrar deberian, segun la especificación, ser valores de {{cssxref("<color>")}} CSS. En el siguiente ejemplo, describimos en mismo color.</p> + +<pre class="brush: js">// these all set the fillStyle to 'orange' + +ctx.fillStyle = 'orange'; +ctx.fillStyle = '#FFA500'; +ctx.fillStyle = 'rgb(255, 165, 0)'; +ctx.fillStyle = 'rgba(255, 165, 0, 1)'; +</pre> + +<h3 id="A_fillStyle_example" name="A_fillStyle_example">A <code>fillStyle</code> example</h3> + +<p>En este ejemplo, usamos dos bucles for para dibujar una cuadrícula de rectangulos, cada uno de diferente color. La imagen resultante deberia ser similar a la de la screenhot. No hay nada demasiado espectacular en el proceso. Usamos dos variables i y j para generar un unico color RGB para cada celda cuadrada, modificando las componentes rojo y verde. El canal azul tiene un valor fijo. Modificando los canales, puedes generar todo tipo de paletas. Incrementando los paos, puedes lograr algo similar que se parezca a las paletas de colores que Photoshop usa.</p> + +<pre class="brush: js;highlight[5,6]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + for (var i = 0; i < 6; i++) { + for (var j = 0; j < 6; j++) { + ctx.fillStyle = 'rgb(' + Math.floor(255 - 42.5 * i) + ', ' + + Math.floor(255 - 42.5 * j) + ', 0)'; + ctx.fillRect(j * 25, i * 25, 25, 25); + } + } +}</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>The result looks like this:</p> + +<p>{{EmbedLiveSample("A_fillStyle_example", 160, 160, "https://mdn.mozillademos.org/files/5417/Canvas_fillstyle.png")}}</p> + +<h3 id="A_strokeStyle_example" name="A_strokeStyle_example">A <code>strokeStyle</code> example</h3> + +<p>Este ejemplo es similar al de arriba, pero usa la propiedad <code>strokeStyle</code> para cambiar el color del contorno de las formas. Usamos el método <code>arc()</code> para dibujar circulos en lugar de celdas cuadradas.</p> + +<pre class="brush: js;highlight[5,6]"> function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + for (var i = 0; i < 6; i++) { + for (var j = 0; j < 6; j++) { + ctx.strokeStyle = 'rgb(0, ' + Math.floor(255 - 42.5 * i) + ', ' + + Math.floor(255 - 42.5 * j) + ')'; + ctx.beginPath(); + ctx.arc(12.5 + j * 25, 12.5 + i * 25, 10, 0, Math.PI * 2, true); + ctx.stroke(); + } + } + } +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>The result looks like this:</p> + +<p>{{EmbedLiveSample("A_strokeStyle_example", "180", "180", "https://mdn.mozillademos.org/files/253/Canvas_strokestyle.png")}}</p> + +<h2 id="Transparency" name="Transparency">Transparency</h2> + +<p>Ademas de dibujar formas opacas en el canvas, podemos dibujar formas semi-transparentes(o translucidas). Esto se logra bien configurando la propiedad <code>globalAlpha</code> o asignando un color semi-transparente al estilo del trazo u u/y al de relleno.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.globalAlpha", "globalAlpha = transparencyValue")}}</dt> + <dd>Applies the specified transparency value to all future shapes drawn on the canvas. The value must be between 0.0 (fully transparent) to 1.0 (fully opaque). This value is 1.0 (fully opaque) by default.</dd> +</dl> + +<p>The <code>globalAlpha</code> property can be useful if you want to draw a lot of shapes on the canvas with similar transparency, but otherwise it's generally more useful to set the transparency on individual shapes when setting their colors.</p> + +<p>Debido qaque las propiedades <code>strokeStyle</code> y <code>fillStyle</code> aceptan valores de color rgba de CSS, podemos usar la siguiente notacion para asignar una color transparente a ellos.</p> + +<pre class="brush: js">// Assigning transparent colors to stroke and fill style + +ctx.strokeStyle = 'rgba(255, 0, 0, 0.5)'; +ctx.fillStyle = 'rgba(255, 0, 0, 0.5)'; +</pre> + +<p>The <code>rgba()</code> function is similar to the <code>rgb()</code> function but it has one extra parameter. The last parameter sets the transparency value of this particular color. The valid range is again between 0.0 (fully transparent) and 1.0 (fully opaque).</p> + +<h3 id="A_globalAlpha_example" name="A_globalAlpha_example">A <code>globalAlpha</code> example</h3> + +<p>In this example, we'll draw a background of four different colored squares. On top of these, we'll draw a set of semi-transparent circles. The <code>globalAlpha</code> property is set at <code>0.2</code> which will be used for all shapes from that point on. Every step in the <code>for</code> loop draws a set of circles with an increasing radius. The final result is a radial gradient. By overlaying ever more circles on top of each other, we effectively reduce the transparency of the circles that have already been drawn. By increasing the step count and in effect drawing more circles, the background would completely disappear from the center of the image.</p> + +<pre class="brush: js;highlight[15]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + // draw background + ctx.fillStyle = '#FD0'; + ctx.fillRect(0, 0, 75, 75); + ctx.fillStyle = '#6C0'; + ctx.fillRect(75, 0, 75, 75); + ctx.fillStyle = '#09F'; + ctx.fillRect(0, 75, 75, 75); + ctx.fillStyle = '#F30'; + ctx.fillRect(75, 75, 75, 75); + ctx.fillStyle = '#FFF'; + + // set transparency value + ctx.globalAlpha = 0.2; + + // Draw semi transparent circles + for (var i = 0; i < 7; i++) { + ctx.beginPath(); + ctx.arc(75, 75, 10 + 10 * i, 0, Math.PI * 2, true); + ctx.fill(); + } +}</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_globalAlpha_example", "180", "180", "https://mdn.mozillademos.org/files/232/Canvas_globalalpha.png")}}</p> + +<h3 id="An_example_using_rgba" name="An_example_using_rgba()">An example using <code>rgba()</code></h3> + +<p>In this second example, we do something similar to the one above, but instead of drawing circles on top of each other, I've drawn small rectangles with increasing opacity. Using <code>rgba()</code> gives you a little more control and flexibility because we can set the fill and stroke style individually.</p> + +<pre class="brush: js;highlight[16]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // Draw background + ctx.fillStyle = 'rgb(255, 221, 0)'; + ctx.fillRect(0, 0, 150, 37.5); + ctx.fillStyle = 'rgb(102, 204, 0)'; + ctx.fillRect(0, 37.5, 150, 37.5); + ctx.fillStyle = 'rgb(0, 153, 255)'; + ctx.fillRect(0, 75, 150, 37.5); + ctx.fillStyle = 'rgb(255, 51, 0)'; + ctx.fillRect(0, 112.5, 150, 37.5); + + // Draw semi transparent rectangles + for (var i = 0; i < 10; i++) { + ctx.fillStyle = 'rgba(255, 255, 255, ' + (i + 1) / 10 + ')'; + for (var j = 0; j < 4; j++) { + ctx.fillRect(5 + i * 14, 5 + j * 37.5, 14, 27.5); + } + } +}</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("An_example_using_rgba()", "180", "180", "https://mdn.mozillademos.org/files/246/Canvas_rgba.png")}}</p> + +<h2 id="Line_styles" name="Line_styles">Line styles</h2> + +<p>There are several properties which allow us to style lines.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.lineWidth", "lineWidth = value")}}</dt> + <dd>Sets the width of lines drawn in the future.</dd> + <dt>{{domxref("CanvasRenderingContext2D.lineCap", "lineCap = type")}}</dt> + <dd>Sets the appearance of the ends of lines.</dd> + <dt>{{domxref("CanvasRenderingContext2D.lineJoin", "lineJoin = type")}}</dt> + <dd>Sets the appearance of the "corners" where lines meet.</dd> + <dt>{{domxref("CanvasRenderingContext2D.miterLimit", "miterLimit = value")}}</dt> + <dd>Establishes a limit on the miter when two lines join at a sharp angle, to let you control how thick the junction becomes.</dd> + <dt>{{domxref("CanvasRenderingContext2D.getLineDash", "getLineDash()")}}</dt> + <dd>Returns the current line dash pattern array containing an even number of non-negative numbers.</dd> + <dt>{{domxref("CanvasRenderingContext2D.setLineDash", "setLineDash(segments)")}}</dt> + <dd>Sets the current line dash pattern.</dd> + <dt>{{domxref("CanvasRenderingContext2D.lineDashOffset", "lineDashOffset = value")}}</dt> + <dd>Specifies where to start a dash array on a line.</dd> +</dl> + +<p>You'll get a better understanding of what these do by looking at the examples below.</p> + +<h3 id="A_lineWidth_example" name="A_lineWidth_example">A <code>lineWidth</code> example</h3> + +<p>This property sets the current line thickness. Values must be positive numbers. By default this value is set to 1.0 units.</p> + +<p>The line width is the thickness of the stroke centered on the given path. In other words, the area that's drawn extends to half the line width on either side of the path. Because canvas coordinates do not directly reference pixels, special care must be taken to obtain crisp horizontal and vertical lines.</p> + +<p>In the example below, 10 straight lines are drawn with increasing line widths. The line on the far left is 1.0 units wide. However, the leftmost and all other odd-integer-width thickness lines do not appear crisp, because of the path's positioning.</p> + +<pre class="brush: js;highlight[4]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + for (var i = 0; i < 10; i++) { + ctx.lineWidth = 1 + i; + ctx.beginPath(); + ctx.moveTo(5 + i * 14, 5); + ctx.lineTo(5 + i * 14, 140); + ctx.stroke(); + } +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_lineWidth_example", "180", "180", "https://mdn.mozillademos.org/files/239/Canvas_linewidth.png")}}</p> + +<p>Obtaining crisp lines requires understanding how paths are stroked. In the images below, the grid represents the canvas coordinate grid. The squares between gridlines are actual on-screen pixels. In the first grid image below, a rectangle from (2,1) to (5,5) is filled. The entire area between them (light red) falls on pixel boundaries, so the resulting filled rectangle will have crisp edges.</p> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/201/Canvas-grid.png"></p> + +<p>If you consider a path from (3,1) to (3,5) with a line thickness of <code>1.0</code>, you end up with the situation in the second image. The actual area to be filled (dark blue) only extends halfway into the pixels on either side of the path. An approximation of this has to be rendered, which means that those pixels being only partially shaded, and results in the entire area (the light blue and dark blue) being filled in with a color only half as dark as the actual stroke color. This is what happens with the <code>1.0</code> width line in the previous example code.</p> + +<p>To fix this, you have to be very precise in your path creation. Knowing that a <code>1.0</code> width line will extend half a unit to either side of the path, creating the path from (3.5,1) to (3.5,5) results in the situation in the third image—the <code>1.0</code> line width ends up completely and precisely filling a single pixel vertical line.</p> + +<div class="note"> +<p><strong>Note:</strong> Be aware that in our vertical line example, the Y position still referenced an integer gridline position—if it hadn't, we would see pixels with half coverage at the endpoints (but note also that this behavior depends on the current <code>lineCap</code> style whose default value is <code>butt</code>; you may want to compute consistent strokes with half-pixel coordinates for odd-width lines, by setting the <code>lineCap</code> style to <code>square</code>, so that the outer border of the stroke around the endpoint will be automatically extended to cover the whole pixel exactly).</p> + +<p>Note also that only start and final endpoints of a path are affected: if a path is closed with <code>closePath()</code>, there's no start and final endpoint; instead, all endpoints in the path are connected to their attached previous and next segment using the current setting of the <code>lineJoin</code> style, whose default value is <code>miter</code>, with the effect of automatically extending the outer borders of the connected segments to their intersection point, so that the rendered stroke will exactly cover full pixels centered at each endpoint if those connected segments are horizontal and/or vertical). See the next two sections for demonstrations of these additional line styles.</p> +</div> + +<p>For even-width lines, each half ends up being an integer amount of pixels, so you want a path that is between pixels (that is, (3,1) to (3,5)), instead of down the middle of pixels.</p> + +<p>While slightly painful when initially working with scalable 2D graphics, paying attention to the pixel grid and the position of paths ensures that your drawings will look correct regardless of scaling or any other transformations involved. A 1.0-width vertical line drawn at the correct position will become a crisp 2-pixel line when scaled up by 2, and will appear at the correct position.</p> + +<h3 id="A_lineCap_example" name="A_lineCap_example">A <code>lineCap</code> example</h3> + +<p>The <code>lineCap</code> property determines how the end points of every line are drawn. There are three possible values for this property and those are: <code>butt</code>, <code>round</code> and <code>square</code>. By default this property is set to <code>butt</code>.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/236/Canvas_linecap.png" style="float: right; height: 190px; width: 190px;"></p> + +<dl> + <dt><code>butt</code></dt> + <dd>The ends of lines are squared off at the endpoints.</dd> + <dt><code>round</code></dt> + <dd>The ends of lines are rounded.</dd> + <dt><code>square</code></dt> + <dd>The ends of lines are squared off by adding a box with an equal width and half the height of the line's thickness.</dd> +</dl> + +<p>In this example, we'll draw three lines, each with a different value for the <code>lineCap</code> property. I also added two guides to see the exact differences between the three. Each of these lines starts and ends exactly on these guides.</p> + +<p>The line on the left uses the default <code>butt</code> option. You'll notice that it's drawn completely flush with the guides. The second is set to use the <code>round</code> option. This adds a semicircle to the end that has a radius half the width of the line. The line on the right uses the <code>square</code> option. This adds a box with an equal width and half the height of the line thickness.</p> + +<pre class="brush: js;highlight[18]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + var lineCap = ['butt', 'round', 'square']; + + // Draw guides + ctx.strokeStyle = '#09f'; + ctx.beginPath(); + ctx.moveTo(10, 10); + ctx.lineTo(140, 10); + ctx.moveTo(10, 140); + ctx.lineTo(140, 140); + ctx.stroke(); + + // Draw lines + ctx.strokeStyle = 'black'; + for (var i = 0; i < lineCap.length; i++) { + ctx.lineWidth = 15; + ctx.lineCap = lineCap[i]; + ctx.beginPath(); + ctx.moveTo(25 + i * 50, 10); + ctx.lineTo(25 + i * 50, 140); + ctx.stroke(); + } +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_lineCap_example", "180", "180", "https://mdn.mozillademos.org/files/236/Canvas_linecap.png")}}</p> + +<h3 id="A_lineJoin_example" name="A_lineJoin_example">A <code>lineJoin</code> example</h3> + +<p>The <code>lineJoin</code> property determines how two connecting segments (of lines, arcs or curves) with non-zero lengths in a shape are joined together (degenerate segments with zero lengths, whose specified endpoints and control points are exactly at the same position, are skipped).</p> + +<p>There are three possible values for this property: <code>round</code>, <code>bevel</code> and <code>miter</code>. By default this property is set to <code>miter</code>. Note that the <code>lineJoin</code> setting has no effect if the two connected segments have the same direction, because no joining area will be added in this case.</p> + +<p><img alt="" src="https://mdn.mozillademos.org/files/237/Canvas_linejoin.png" style="float: right; height: 190px; width: 190px;"></p> + +<dl> + <dt><code>round</code></dt> + <dd>Rounds off the corners of a shape by filling an additional sector of disc centered at the common endpoint of connected segments. The radius for these rounded corners is equal to half the line width.</dd> + <dt><code>bevel</code></dt> + <dd>Fills an additional triangular area between the common endpoint of connected segments, and the separate outside rectangular corners of each segment.</dd> + <dt><code>miter</code></dt> + <dd>Connected segments are joined by extending their outside edges to connect at a single point, with the effect of filling an additional lozenge-shaped area. This setting is effected by the <code>miterLimit</code> property which is explained below.</dd> +</dl> + +<p>The example below draws three different paths, demonstrating each of these three <code>lineJoin</code> property settings; the output is shown above.</p> + +<pre class="brush: js;highlight[6]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + var lineJoin = ['round', 'bevel', 'miter']; + ctx.lineWidth = 10; + for (var i = 0; i < lineJoin.length; i++) { + ctx.lineJoin = lineJoin[i]; + ctx.beginPath(); + ctx.moveTo(-5, 5 + i * 40); + ctx.lineTo(35, 45 + i * 40); + ctx.lineTo(75, 5 + i * 40); + ctx.lineTo(115, 45 + i * 40); + ctx.lineTo(155, 5 + i * 40); + ctx.stroke(); + } +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_lineJoin_example", "180", "180", "https://mdn.mozillademos.org/files/237/Canvas_linejoin.png")}}</p> + +<h3 id="A_demo_of_the_miterLimit_property" name="A_demo_of_the_miterLimit_property">A demo of the <code>miterLimit</code> property</h3> + +<p>As you've seen in the previous example, when joining two lines with the <code>miter</code> option, the outside edges of the two joining lines are extended up to the point where they meet. For lines which are at large angles with each other, this point is not far from the inside connection point. However, as the angles between each line decreases, the distance (miter length) between these points increases exponentially.</p> + +<p>The <code>miterLimit</code> property determines how far the outside connection point can be placed from the inside connection point. If two lines exceed this value, a bevel join gets drawn instead. Note that the maximum miter length is the product of the line width measured in the current coordinate system, by the value of this <code>miterLimit</code> property (whose default value is 10.0 in the HTML {{HTMLElement("canvas")}}), so the <code>miterLimit</code> can be set independently from the current display scale or any affine transforms of paths: it only influences the effectively rendered shape of line edges.</p> + +<p>More exactly, the miter limit is the maximum allowed ratio of the extension length (in the HTML canvas, it is measured between the outside corner of the joined edges of the line and the common endpoint of connecting segments specified in the path) to half the line width. It can equivalently be defined as the maximum allowed ratio of the distance between the inside and outside points of jonction of edges, to the total line width. It is then equal to the cosecant of half the minimum inner angle of connecting segments below which no miter join will be rendered, but only a bevel join:</p> + +<ul> + <li><code>miterLimit</code> = <strong>max</strong> <code>miterLength</code> / <code>lineWidth</code> = 1 / <strong>sin</strong> ( <strong>min</strong> <em>θ</em> / 2 )</li> + <li>The default miter limit of 10.0 will strip all miters for sharp angles below about 11 degrees.</li> + <li>A miter limit equal to √2 ≈ 1.4142136 (rounded up) will strip miters for all acute angles, keeping miter joins only for obtuse or right angles.</li> + <li>A miter limit equal to 1.0 is valid but will disable all miters.</li> + <li>Values below 1.0 are invalid for the miter limit.</li> +</ul> + +<p>Here's a little demo in which you can set <code>miterLimit</code> dynamically and see how this effects the shapes on the canvas. The blue lines show where the start and endpoints for each of the lines in the zig-zag pattern are.</p> + +<p>If you specify a <code>miterLimit</code> value below 4.2 in this demo, none of the visible corners will join with a miter extension, but only with a small bevel near the blue lines; with a <code>miterLimit</code> above 10, most corners in this demo should join with a miter far away from the blue lines, and whose height is decreasing between corners from left to right because they connect with growing angles; with intermediate values, the corners on the left side will only join with a bevel near the blue lines, and the corners on the right side with a miter extension (also with a decreasing height).</p> + +<pre class="brush: js;highlight[18]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // Clear canvas + ctx.clearRect(0, 0, 150, 150); + + // Draw guides + ctx.strokeStyle = '#09f'; + ctx.lineWidth = 2; + ctx.strokeRect(-5, 50, 160, 50); + + // Set line styles + ctx.strokeStyle = '#000'; + ctx.lineWidth = 10; + + // check input + if (document.getElementById('miterLimit').value.match(/\d+(\.\d+)?/)) { + ctx.miterLimit = parseFloat(document.getElementById('miterLimit').value); + } else { + alert('Value must be a positive number'); + } + + // Draw lines + ctx.beginPath(); + ctx.moveTo(0, 100); + for (i = 0; i < 24 ; i++) { + var dy = i % 2 == 0 ? 25 : -25; + ctx.lineTo(Math.pow(i, 1.5) * 2, 75 + dy); + } + ctx.stroke(); + return false; +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><table> + <tr> + <td><canvas id="canvas" width="150" height="150"></canvas></td> + <td>Change the <code>miterLimit</code> by entering a new value below and clicking the redraw button.<br><br> + <form onsubmit="return draw();"> + <label>Miter limit</label> + <input type="number" size="3" id="miterLimit"/> + <input type="submit" value="Redraw"/> + </form> + </td> + </tr> +</table></pre> + +<pre class="brush: js">document.getElementById('miterLimit').value = document.getElementById('canvas').getContext('2d').miterLimit; +draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_demo_of_the_miterLimit_property", "400", "180", "https://mdn.mozillademos.org/files/240/Canvas_miterlimit.png")}}</p> + +<h3 id="Using_line_dashes">Using line dashes</h3> + +<p>The <code>setLineDash</code> method and the <code>lineDashOffset</code> property specify the dash pattern for lines. The <code>setLineDash</code> method accepts a list of numbers that specifies distances to alternately draw a line and a gap and the <code>lineDashOffset</code> property sets an offset where to start the pattern.</p> + +<p>In this example we are creating a marching ants effect. It is an animation technique often found in <span class="new">selection</span> tools of computer graphics programs. It helps the user to distinguish the selection border from the image background by animating the border. In a later part of this tutorial, you can learn how to do this and other <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_animations">basic animations</a>.</p> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="110" height="110"></canvas></pre> +</div> + +<pre class="brush: js;highlight[6]">var ctx = document.getElementById('canvas').getContext('2d'); +var offset = 0; + +function draw() { + ctx.clearRect(0, 0, canvas.width, canvas.height); + ctx.setLineDash([4, 2]); + ctx.lineDashOffset = -offset; + ctx.strokeRect(10, 10, 100, 100); +} + +function march() { + offset++; + if (offset > 16) { + offset = 0; + } + draw(); + setTimeout(march, 20); +} + +march();</pre> + +<p>{{EmbedLiveSample("Using_line_dashes", "120", "120", "https://mdn.mozillademos.org/files/9853/marching-ants.png")}}</p> + +<h2 id="Gradients" name="Gradients">Gradients</h2> + +<p>Just like any normal drawing program, we can fill and stroke shapes using linear and radial gradients. We create a {{domxref("CanvasGradient")}} object by using one of the following methods. We can then assign this object to the <code>fillStyle</code> or <code>strokeStyle</code> properties.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.createLinearGradient", "createLinearGradient(x1, y1, x2, y2)")}}</dt> + <dd>Creates a linear gradient object with a starting point of (<code>x1</code>, <code>y1</code>) and an end point of (<code>x2</code>, <code>y2</code>).</dd> + <dt>{{domxref("CanvasRenderingContext2D.createRadialGradient", "createRadialGradient(x1, y1, r1, x2, y2, r2)")}}</dt> + <dd>Creates a radial gradient. The parameters represent two circles, one with its center at (<code>x1</code>, <code>y1</code>) and a radius of <code>r1</code>, and the other with its center at (<code>x2</code>, <code>y2</code>) with a radius of <code>r2</code>.</dd> +</dl> + +<p>For example:</p> + +<pre class="brush: js">var lineargradient = ctx.createLinearGradient(0, 0, 150, 150); +var radialgradient = ctx.createRadialGradient(75, 75, 0, 75, 75, 100); +</pre> + +<p>Once we've created a <code>CanvasGradient</code> object we can assign colors to it by using the <code>addColorStop()</code> method.</p> + +<dl> + <dt>{{domxref("CanvasGradient.addColorStop", "gradient.addColorStop(position, color)")}}</dt> + <dd>Creates a new color stop on the <code>gradient</code> object. The <code>position</code> is a number between 0.0 and 1.0 and defines the relative position of the color in the gradient, and the <code>color</code> argument must be a string representing a CSS {{cssxref("<color>")}}, indicating the color the gradient should reach at that offset into the transition.</dd> +</dl> + +<p>You can add as many color stops to a gradient as you need. Below is a very simple linear gradient from white to black.</p> + +<pre class="brush: js">var lineargradient = ctx.createLinearGradient(0, 0, 150, 150); +lineargradient.addColorStop(0, 'white'); +lineargradient.addColorStop(1, 'black'); +</pre> + +<h3 id="A_createLinearGradient_example" name="A_createLinearGradient_example">A <code>createLinearGradient</code> example</h3> + +<p>In this example, we'll create two different gradients. As you can see here, both the <code>strokeStyle</code> and <code>fillStyle</code> properties can accept a <code>canvasGradient</code> object as valid input.</p> + +<pre class="brush: js;highlight[5,11]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // Create gradients + var lingrad = ctx.createLinearGradient(0, 0, 0, 150); + lingrad.addColorStop(0, '#00ABEB'); + lingrad.addColorStop(0.5, '#fff'); + lingrad.addColorStop(0.5, '#26C000'); + lingrad.addColorStop(1, '#fff'); + + var lingrad2 = ctx.createLinearGradient(0, 50, 0, 95); + lingrad2.addColorStop(0.5, '#000'); + lingrad2.addColorStop(1, 'rgba(0, 0, 0, 0)'); + + // assign gradients to fill and stroke styles + ctx.fillStyle = lingrad; + ctx.strokeStyle = lingrad2; + + // draw shapes + ctx.fillRect(10, 10, 130, 130); + ctx.strokeRect(50, 50, 50, 50); + +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>The first is a background gradient. As you can see, we assigned two colors at the same position. You do this to make very sharp color transitions—in this case from white to green. Normally, it doesn't matter in what order you define the color stops, but in this special case, it does significantly. If you keep the assignments in the order you want them to appear, this won't be a problem.</p> + +<p>In the second gradient, we didn't assign the starting color (at position 0.0) since it wasn't strictly necessary, because it will automatically assume the color of the next color stop. Therefore, assigning the black color at position 0.5 automatically makes the gradient, from the start to this stop, black.</p> + +<p>{{EmbedLiveSample("A_createLinearGradient_example", "180", "180", "https://mdn.mozillademos.org/files/235/Canvas_lineargradient.png")}}</p> + +<h3 id="A_createRadialGradient_example" name="A_createRadialGradient_example">A <code>createRadialGradient</code> example</h3> + +<p>In this example, we'll define four different radial gradients. Because we have control over the start and closing points of the gradient, we can achieve more complex effects than we would normally have in the "classic" radial gradients we see in, for instance, Photoshop (that is, a gradient with a single center point where the gradient expands outward in a circular shape).</p> + +<pre class="brush: js;highlight[5,10,15,20]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // Create gradients + var radgrad = ctx.createRadialGradient(45, 45, 10, 52, 50, 30); + radgrad.addColorStop(0, '#A7D30C'); + radgrad.addColorStop(0.9, '#019F62'); + radgrad.addColorStop(1, 'rgba(1, 159, 98, 0)'); + + var radgrad2 = ctx.createRadialGradient(105, 105, 20, 112, 120, 50); + radgrad2.addColorStop(0, '#FF5F98'); + radgrad2.addColorStop(0.75, '#FF0188'); + radgrad2.addColorStop(1, 'rgba(255, 1, 136, 0)'); + + var radgrad3 = ctx.createRadialGradient(95, 15, 15, 102, 20, 40); + radgrad3.addColorStop(0, '#00C9FF'); + radgrad3.addColorStop(0.8, '#00B5E2'); + radgrad3.addColorStop(1, 'rgba(0, 201, 255, 0)'); + + var radgrad4 = ctx.createRadialGradient(0, 150, 50, 0, 140, 90); + radgrad4.addColorStop(0, '#F4F201'); + radgrad4.addColorStop(0.8, '#E4C700'); + radgrad4.addColorStop(1, 'rgba(228, 199, 0, 0)'); + + // draw shapes + ctx.fillStyle = radgrad4; + ctx.fillRect(0, 0, 150, 150); + ctx.fillStyle = radgrad3; + ctx.fillRect(0, 0, 150, 150); + ctx.fillStyle = radgrad2; + ctx.fillRect(0, 0, 150, 150); + ctx.fillStyle = radgrad; + ctx.fillRect(0, 0, 150, 150); +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>In this case, we've offset the starting point slightly from the end point to achieve a spherical 3D effect. It's best to try to avoid letting the inside and outside circles overlap because this results in strange effects which are hard to predict.</p> + +<p>The last color stop in each of the four gradients uses a fully transparent color. If you want to have a nice transition from this to the previous color stop, both colors should be equal. This isn't very obvious from the code because it uses two different CSS color methods as a demonstration, but in the first gradient <code>#019F62 = rgba(1,159,98,1)</code>.</p> + +<p>{{EmbedLiveSample("A_createRadialGradient_example", "180", "180", "https://mdn.mozillademos.org/files/244/Canvas_radialgradient.png")}}</p> + +<h2 id="Patterns" name="Patterns">Patterns</h2> + +<p>In one of the examples on the previous page, we used a series of loops to create a pattern of images. There is, however, a much simpler method: the <code>createPattern()</code> method.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.createPattern", "createPattern(image, type)")}}</dt> + <dd>Creates and returns a new canvas pattern object. <code>image</code> is a {{domxref("CanvasImageSource")}} (that is, an {{domxref("HTMLImageElement")}}, another canvas, a {{HTMLElement("video")}} element, or the like. <code>type</code> is a string indicating how to use the image.</dd> +</dl> + +<p>The type specifies how to use the image in order to create the pattern, and must be one of the following string values:</p> + +<dl> + <dt><code>repeat</code></dt> + <dd>Tiles the image in both vertical and horizontal directions.</dd> + <dt><code>repeat-x</code></dt> + <dd>Tiles the image horizontally but not vertically.</dd> + <dt><code>repeat-y</code></dt> + <dd>Tiles the image vertically but not horizontally.</dd> + <dt><code>no-repeat</code></dt> + <dd>Doesn't tile the image. It's used only once.</dd> +</dl> + +<p>We use this method to create a {{domxref("CanvasPattern")}} object which is very similar to the gradient methods we've seen above. Once we've created a pattern, we can assign it to the <code>fillStyle</code> or <code>strokeStyle</code> properties. For example:</p> + +<pre class="brush: js">var img = new Image(); +img.src = 'someimage.png'; +var ptrn = ctx.createPattern(img, 'repeat'); +</pre> + +<div class="note"> +<p><strong>Note:</strong> Like with the <code>drawImage()</code> method, you must make sure the image you use is loaded before calling this method or the pattern may be drawn incorrectly.</p> +</div> + +<h3 id="A_createPattern_example" name="A_createPattern_example">A <code>createPattern</code> example</h3> + +<p>In this last example, we'll create a pattern to assign to the <code>fillStyle</code> property. The only thing worth noting is the use of the image's <code>onload</code> handler. This is to make sure the image is loaded before it is assigned to the pattern.</p> + +<pre class="brush: js;highlight[10]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + // create new image object to use as pattern + var img = new Image(); + img.src = 'https://mdn.mozillademos.org/files/222/Canvas_createpattern.png'; + img.onload = function() { + + // create pattern + var ptrn = ctx.createPattern(img, 'repeat'); + ctx.fillStyle = ptrn; + ctx.fillRect(0, 0, 150, 150); + + } +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> + +<pre class="brush: js">draw();</pre> + +<p>The result looks like this:</p> +</div> + +<p>{{EmbedLiveSample("A_createPattern_example", "180", "180", "https://mdn.mozillademos.org/files/222/Canvas_createpattern.png")}}</p> + +<h2 id="Shadows">Shadows</h2> + +<p>Using shadows involves just four properties:</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.shadowOffsetX", "shadowOffsetX = float")}}</dt> + <dd>Indicates the horizontal distance the shadow should extend from the object. This value isn't affected by the transformation matrix. The default is 0.</dd> + <dt>{{domxref("CanvasRenderingContext2D.shadowOffsetY", "shadowOffsetY = float")}}</dt> + <dd>Indicates the vertical distance the shadow should extend from the object. This value isn't affected by the transformation matrix. The default is 0.</dd> + <dt>{{domxref("CanvasRenderingContext2D.shadowBlur", "shadowBlur = float")}}</dt> + <dd>Indicates the size of the blurring effect; this value doesn't correspond to a number of pixels and is not affected by the current transformation matrix. The default value is 0.</dd> + <dt>{{domxref("CanvasRenderingContext2D.shadowColor", "shadowColor = color")}}</dt> + <dd>A standard CSS color value indicating the color of the shadow effect; by default, it is fully-transparent black.</dd> +</dl> + +<p>The properties <code>shadowOffsetX</code> and <code>shadowOffsetY</code> indicate how far the shadow should extend from the object in the X and Y directions; these values aren't affected by the current transformation matrix. Use negative values to cause the shadow to extend up or to the left, and positive values to cause the shadow to extend down or to the right. These are both 0 by default.</p> + +<p>The <code>shadowBlur</code> property indicates the size of the blurring effect; this value doesn't correspond to a number of pixels and is not affected by the current transformation matrix. The default value is 0.</p> + +<p>The <code>shadowColor</code> property is a standard CSS color value indicating the color of the shadow effect; by default, it is fully-transparent black.</p> + +<div class="note"> +<p><strong>Note:</strong> Shadows are only drawn for <code>source-over</code> <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Compositing" title="Web/Guide/HTML/Canvas_tutorial/Compositing">compositing operations</a>.</p> +</div> + +<h3 id="A_shadowed_text_example">A shadowed text example</h3> + +<p>This example draws a text string with a shadowing effect.</p> + +<pre class="brush: js;highlight[4,5,6,7]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + ctx.shadowOffsetX = 2; + ctx.shadowOffsetY = 2; + ctx.shadowBlur = 2; + ctx.shadowColor = 'rgba(0, 0, 0, 0.5)'; + + ctx.font = '20px Times New Roman'; + ctx.fillStyle = 'Black'; + ctx.fillText('Sample String', 5, 30); +} +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="80"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("A_shadowed_text_example", "180", "100", "https://mdn.mozillademos.org/files/2505/shadowed-string.png")}}</p> + +<p>We will look at the <code>font</code> property and <code>fillText</code> method in the next chapter about <a href="/en-US/docs/Web/API/Canvas_API/Tutorial/Drawing_text">drawing text</a>.</p> + +<h2 id="Canvas_fill_rules">Canvas fill rules</h2> + +<p>When using <code>fill</code> (or {{domxref("CanvasRenderingContext2D.clip", "clip")}} and {{domxref("CanvasRenderingContext2D.isPointInPath", "isPointinPath")}}) you can optionally provide a fill rule algorithm by which to determine if a point is inside or outside a path and thus if it gets filled or not. This is useful when a path intersects itself or is nested.<br> + <br> + Two values are possible:</p> + +<ul> + <li><code><strong>"nonzero</strong></code>": The <a class="external external-icon" href="http://en.wikipedia.org/wiki/Nonzero-rule">non-zero winding rule</a>, which is the default rule.</li> + <li><code><strong>"evenodd"</strong></code>: The <a class="external external-icon" href="http://en.wikipedia.org/wiki/Even%E2%80%93odd_rule">even-odd winding rule</a>.</li> +</ul> + +<p>In this example we are using the <code>evenodd</code> rule.</p> + +<pre class="brush: js;highlight[6]">function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + ctx.beginPath(); + ctx.arc(50, 50, 30, 0, Math.PI * 2, true); + ctx.arc(50, 50, 15, 0, Math.PI * 2, true); + ctx.fill('evenodd'); +}</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="100" height="100"></canvas></pre> + +<pre class="brush: js">draw();</pre> +</div> + +<p>{{EmbedLiveSample("Canvas_fill_rules", "110", "110", "https://mdn.mozillademos.org/files/9855/fill-rule.png")}}</p> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Drawing_shapes", "Web/API/Canvas_API/Tutorial/Drawing_text")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/basic_animations/index.html b/files/es/web/api/canvas_api/tutorial/basic_animations/index.html new file mode 100644 index 0000000000..94c66fb05d --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/basic_animations/index.html @@ -0,0 +1,333 @@ +--- +title: Animaciones básicas +slug: Web/Guide/HTML/Canvas_tutorial/Basic_animations +tags: + - Canvas + - HTML5 + - Intermedio + - Tutorial + - graficos +translation_of: Web/API/Canvas_API/Tutorial/Basic_animations +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Compositing", "Web/API/Canvas_API/Tutorial/Advanced_animations")}}</div> + +<div class="summary"> +<p>Ya que estamos usando JavaScript para controlar elementos {{HTMLElement("canvas")}} , también es muy fácil hacer animaciones (interactivas). En este capitulo veremos como hacer algunas animaciones básicas.</p> +</div> + +<p>Probablemente la mayor limitación es que una vez que se dibuja una forma, se mantiene de esa manera. Si necesitamos moverlo tenemos que volver a dibujarlo y todo lo que se dibujó antes. Se necesita mucho tiempo para volver a dibujar estructuras complejas y el rendimiento depende en gran medida de la velocidad de la computadora en la que se ejecuta.</p> + +<h2 id="Basic_animation_steps" name="Basic_animation_steps">Pasos básicos de animación</h2> + +<p>Estos son los pasos que necesitas para dibujar un cuadro:</p> + +<ol> + <li><strong>Limpiar el canvas</strong><br> + A menos que las formas que vas a dibujar llenen el canvas completo (por ejemplo, una imagen de fondo), debes borrar cualquier forma que haya dibujado previamente. La forma más fácil de hacerlo es usar el método {{domxref("CanvasRenderingContext2D.clearRect", "clearRect()")}}.</li> + <li><strong>Guardar el estado del canvas</strong><br> + Si estás cambiando alguna configuración (como estilos, transformaciones, etc.) que afecte el estado del canvas y deseas asegurarte de que se utiliza el estado original cada vez que se dibuja una figura, debes guardar ese estado original. </li> + <li><strong>Dibujar formas animadas</strong><br> + El paso en el que realizas el renderizado del cuadro actual.</li> + <li><strong>Restaurar el estado del canvas</strong><br> + Si has guardado el estado, restáuralo antes de dibujar un nuevo cuadro.</li> +</ol> + +<h2 id="Controlling_an_animation" name="Controlling_an_animation">Controlando una animación</h2> + +<p>Las formas se dibujan en el canvas utilizando los métodos de canvas directamente o llamando a funciones personalizadas. En circunstancias normales, solo vemos que estos resultados aparecen en el canvas cuando el script termina de ejecutarse. Por ejemplo, no es posible hacer una animación desde un bucle <code>for</code>.</p> + +<p>Eso significa que necesitamos una forma de ejecutar nuestras funciones de dibujo durante un período de tiempo. Hay dos formas de controlar una animación como esta.</p> + +<h3 id="Actualizaciones_Programadas">Actualizaciones Programadas</h3> + +<p>Primero {{domxref("window.setInterval()")}}, {{domxref("window.setTimeout()")}}, y {{domxref("window.requestAnimationFrame()")}} son funciones que pueden ser usadas para llamar una función especifica en un periodo de tiempo establecido.</p> + +<dl> + <dt>{{domxref("WindowTimers.setInterval", "setInterval(function, delay)")}}</dt> + <dd>Ejecuta una función especificada por <code>function</code> cada <code>delay</code> milisegundos.</dd> + <dt>{{domxref("WindowTimers.setTimeout", "setTimeout(function, delay)")}}</dt> + <dd>Ejecuta una función especificada por <code>function</code> dentro de <code>delay</code> milisegundos.</dd> + <dt>{{domxref("Window.requestAnimationFrame()", "requestAnimationFrame(callback)")}}</dt> + <dd>Comunica al navegador que deseas iniciar una animación y requieres que el navegador llame a las funciones especificas para actualizar la misma antes de la siguiente escena.</dd> +</dl> + +<p>Si no quieres ninguna interacción del usuario puedes usar la función <code>setInterval()</code> que repite la ejecución del código suministrado. Si lo que queremos es hacer un juego, podríamos usar eventos de teclado o el mouse para controlar la animación y usar <code>setTimeout()</code>. Al establecer los {{domxref("EventListener")}}, capturamos cualquier interacción del usuario y ejecutamos nuestras funciones de animación.</p> + +<div class="note"> +<p>En los siguiente ejemplo,usaremos el método para controlar animaciones {{domxref("window.requestAnimationFrame()")}}. El método <code>requestAnimationFrame</code> provee formas amigables y mas eficientes para animar llamando cada marco de animación cuando el sistema esta listo para dibujar. La cantidad de devoluciones de llamadas suele ser 60 veces por segundo y podría ser reducido a menor periodo cuando se corre en un segundo plano. Para mas información acerca de los ciclos de animación, especialmente para juegos, Ver el Articulo <a href="/es/docs/Games/Anatomy">Anatomía de un videojuego</a> en nuestra <a href="/en-US/docs/Games">GameZona de desarrollo de Juegos</a>.</p> +</div> + +<h2 id="Un_sistema_solar_animado">Un sistema solar animado</h2> + +<p>Este ejemplo animado es un pequeño modelo de nuestro sistema solar.</p> + +<pre class="brush: js">var sun = new Image(); +var moon = new Image(); +var earth = new Image(); +function init(){ + sun.src = 'https://mdn.mozillademos.org/files/1456/Canvas_sun.png'; + moon.src = 'https://mdn.mozillademos.org/files/1443/Canvas_moon.png'; + earth.src = 'https://mdn.mozillademos.org/files/1429/Canvas_earth.png'; + window.requestAnimationFrame(draw); +} + +function draw() { + var ctx = document.getElementById('canvas').getContext('2d'); + + ctx.globalCompositeOperation = 'destination-over'; + ctx.clearRect(0,0,300,300); // limpiar canvas + + ctx.fillStyle = 'rgba(0,0,0,0.4)'; + ctx.strokeStyle = 'rgba(0,153,255,0.4)'; + ctx.save(); + ctx.translate(150,150); + + // La tierra + var time = new Date(); + ctx.rotate( ((2*Math.PI)/60)*time.getSeconds() + ((2*Math.PI)/60000)*time.getMilliseconds() ); + ctx.translate(105,0); + ctx.fillRect(0,-12,50,24); // Sombra + ctx.drawImage(earth,-12,-12); + + // La luna + ctx.save(); + ctx.rotate( ((2*Math.PI)/6)*time.getSeconds() + ((2*Math.PI)/6000)*time.getMilliseconds() ); + ctx.translate(0,28.5); + ctx.drawImage(moon,-3.5,-3.5); + ctx.restore(); + + ctx.restore(); + + ctx.beginPath(); + ctx.arc(150,150,105,0,Math.PI*2,false); // Órbita terrestre + ctx.stroke(); + + ctx.drawImage(sun,0,0,300,300); + + window.requestAnimationFrame(draw); +} + +init(); +</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="300" height="300"></canvas></pre> +</div> + +<p>{{EmbedLiveSample("Un_sistema_solar_animado", "310", "310", "https://mdn.mozillademos.org/files/202/Canvas_animation1.png")}}</p> + +<h2 id="Un_reloj_animado">Un reloj animado</h2> + +<p>Este ejemplo dibuja una reloj animado, mostrando la hora actual.</p> + +<pre class="brush: js">function clock(){ + var now = new Date(); + var ctx = document.getElementById('canvas').getContext('2d'); + ctx.save(); + ctx.clearRect(0,0,150,150); + ctx.translate(75,75); + ctx.scale(0.4,0.4); + ctx.rotate(-Math.PI/2); + ctx.strokeStyle = "black"; + ctx.fillStyle = "white"; + ctx.lineWidth = 8; + ctx.lineCap = "round"; + + // Aguja de la hora + ctx.save(); + for (var i=0;i<12;i++){ + ctx.beginPath(); + ctx.rotate(Math.PI/6); + ctx.moveTo(100,0); + ctx.lineTo(120,0); + ctx.stroke(); + } + ctx.restore(); + + // Aguja del minuto + ctx.save(); + ctx.lineWidth = 5; + for (i=0;i<60;i++){ + if (i%5!=0) { + ctx.beginPath(); + ctx.moveTo(117,0); + ctx.lineTo(120,0); + ctx.stroke(); + } + ctx.rotate(Math.PI/30); + } + ctx.restore(); + + var sec = now.getSeconds(); + var min = now.getMinutes(); + var hr = now.getHours(); + hr = hr>=12 ? hr-12 : hr; + + ctx.fillStyle = "black"; + + // Escribimos la hora + ctx.save(); + ctx.rotate( hr*(Math.PI/6) + (Math.PI/360)*min + (Math.PI/21600)*sec ) + ctx.lineWidth = 14; + ctx.beginPath(); + ctx.moveTo(-20,0); + ctx.lineTo(80,0); + ctx.stroke(); + ctx.restore(); + + // escribimos los minutos + ctx.save(); + ctx.rotate( (Math.PI/30)*min + (Math.PI/1800)*sec ) + ctx.lineWidth = 10; + ctx.beginPath(); + ctx.moveTo(-28,0); + ctx.lineTo(112,0); + ctx.stroke(); + ctx.restore(); + + // escribimos los segundos + ctx.save(); + ctx.rotate(sec * Math.PI/30); + ctx.strokeStyle = "#D40000"; + ctx.fillStyle = "#D40000"; + ctx.lineWidth = 6; + ctx.beginPath(); + ctx.moveTo(-30,0); + ctx.lineTo(83,0); + ctx.stroke(); + ctx.beginPath(); + ctx.arc(0,0,10,0,Math.PI*2,true); + ctx.fill(); + ctx.beginPath(); + ctx.arc(95,0,10,0,Math.PI*2,true); + ctx.stroke(); + ctx.fillStyle = "rgba(0,0,0,0)"; + ctx.arc(0,0,3,0,Math.PI*2,true); + ctx.fill(); + ctx.restore(); + + ctx.beginPath(); + ctx.lineWidth = 14; + ctx.strokeStyle = '#325FA2'; + ctx.arc(0,0,142,0,Math.PI*2,true); + ctx.stroke(); + + ctx.restore(); + + window.requestAnimationFrame(clock); +} + +window.requestAnimationFrame(clock);</pre> + +<div class="hidden"> +<pre class="brush: html"><canvas id="canvas" width="150" height="150"></canvas></pre> +</div> + +<p>{{EmbedLiveSample("Un_reloj_animado", "180", "180", "https://mdn.mozillademos.org/files/203/Canvas_animation2.png")}}</p> + +<h2 id="Un_panorama_en_bucle">Un panorama en bucle</h2> + +<p>En este ejemplo, una foto panorámica avanza de izquierda a derecha. Donde usaremos <a href="http://commons.wikimedia.org/wiki/File:Capitan_Meadows,_Yosemite_National_Park.jpg" title="http://commons.wikimedia.org/wiki/File:Capitan_Meadows,_Yosemite_National_Park.jpg">una imagen del Parque Nacional de Yosemite</a> que tomamos de Wikipedia, pero tu podrías usar cualquier imagen que sea mas grande que el canvas.</p> + +<pre class="brush: js">var img = new Image(); + +// Variables de usuario - personalizar estas para cambiar la imagen cuando inicie el desplazamiento +// dirección y velocidad. + +img.src = 'https://mdn.mozillademos.org/files/4553/Capitan_Meadows,_Yosemite_National_Park.jpg'; +var CanvasXSize = 800; +var CanvasYSize = 200; +var speed = 30; //más bajo es más rápido +var scale = 1.05; +var y = -4.5; //desplazamiento vertical + +// Programa principal + +var dx = 0.75; +var imgW; +var imgH; +var x = 0; +var clearX; +var clearY; +var ctx; + +img.onload = function() { + imgW = img.width * scale; + imgH = img.height * scale; + + if (imgW > CanvasXSize) { + // imagen más grande que canvas + x = CanvasXSize - imgW; + } + if (imgW > CanvasXSize) { + // ancho de imagen más grande que canvas + clearX = imgW; + } else { + clearX = CanvasXSize; + } + if (imgH > CanvasYSize) { + // altura de la imagen más grande que canvas + clearY = imgH; + } else { + clearY = CanvasYSize; + } + + // obtener contexto de canvas + ctx = document.getElementById('canvas').getContext('2d'); + + // establecer frecuencia de actualización + return setInterval(draw, speed); +} + +function draw() { + ctx.clearRect(0, 0, clearX, clearY); // clear the canvas + + // si la imagen es <= tamaño de Canvas + if (imgW <= CanvasXSize) { + // reiniciar, comenzar desde el principio + if (x > CanvasXSize) { + x = -imgW + x; + } + // dibujar image1 adicional + if (x > 0) { + ctx.drawImage(img, -imgW + x, y, imgW, imgH); + } + // dibujar image2 adicional + if (x - imgW > 0) { + ctx.drawImage(img, -imgW * 2 + x, y, imgW, imgH); + } + } + + // la imagen es > tamaño de Canvas + else { + // reiniciar, comenzar desde el principio + if (x > (CanvasXSize)) { + x = CanvasXSize - imgW; + } + // dibujar image adicional + if (x > (CanvasXSize-imgW)) { + ctx.drawImage(img, x - imgW + 1, y, imgW, imgH); + } + } + // dibujar imagen + ctx.drawImage(img, x, y,imgW, imgH); + // cantidad para moverse + x += dx; +}</pre> + +<p>Debajo esta el elemento {{HTMLElement("canvas")}} en el cual va la imagen se va ha desplazar. Nota que el ancho y el alto especificado aquí son las variables <code>CanvasXZSize</code> y <code>CanvasYSize</code>.</p> + +<pre class="brush: html"><canvas id="canvas" width="800" height="200"></canvas></pre> + +<p>{{EmbedLiveSample("Un_panorama_en_bucle", "830", "230")}}</p> + +<h2 id="Other_examples" name="Other_examples">Otros ejemplos</h2> + +<dl> + <dt><a href="/es/docs/Web/API/Canvas_API/A_basic_ray-caster" title="/en-US/docs/Web/Guide/HTML/A_basic_ray-caster">Un ray-caster básico</a></dt> + <dd>Un buen ejemplo de como hacer animaciones usando como control el teclado.</dd> + <dt><a href="/es/docs/Web/API/Canvas_API/Tutorial/Advanced_animations">Animaciones avanzadas</a></dt> + <dd>Vamos a echar un vistazo a algunas técnicas de animación avanzadas y física en el próximo capítulo.</dd> +</dl> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Compositing", "Web/API/Canvas_API/Tutorial/Advanced_animations")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/basic_usage/index.html b/files/es/web/api/canvas_api/tutorial/basic_usage/index.html new file mode 100644 index 0000000000..17136d7a7e --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/basic_usage/index.html @@ -0,0 +1,146 @@ +--- +title: Uso básico de Canvas +slug: Web/Guide/HTML/Canvas_tutorial/Basic_usage +translation_of: Web/API/Canvas_API/Tutorial/Basic_usage +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial", "Web/API/Canvas_API/Tutorial/Dibujando_formas")}}</div> + +<div class="summary"> +<p>Comenzamos este tutorial observando el elemento {{HTMLElement("canvas")}}. Al final de esta página, sabrás como configurar el entorno 2D de canvas y habrás dibujado el primer ejemplo en tu navegador.</p> +</div> + +<h2 id="El_elemento_<canvas>">El elemento <code><canvas></code></h2> + +<pre class="brush: html"><canvas id="tutorial" width="150" height="150"></canvas> +</pre> + +<p>A primera vista, un elemento {{HTMLElement("canvas")}} es parecido al elemento {{HTMLElement("img")}}, con la diferencia que este no tiene los atributos <code>src</code> y <code>alt</code>. El elemento <code><canvas></code> tiene solo dos atributos - {{htmlattrxref("width", "canvas")}} y {{htmlattrxref("height", "canvas")}}. Ambos son opcionales y pueden ser definidos usando propiedades <a href="/en-US/docs/DOM" rel="internal" title="en/DOM">DOM</a>. Cuando los atributos ancho y alto no estan especificados, el lienzo se inicializara con <strong>300 pixels</strong> ancho y <strong>150 pixels</strong> de alto. El elemento puede ser arbitrariamente redimensionado por CSS, pero durante el renderizado la imagen es escalada para ajustarse al tamaño de su layout. Si el tamaño del CSS no respeta el ratio del canvas inicial, este aparecerá distorsionado.</p> + +<div class="note"> +<p><strong>Nota:</strong> Si su renderizado se ve distorsionado, pruebe especificar los atributos width y height explícitamente en los atributos del <code><canvas></code> , y no usando CSS.</p> +</div> + +<p>El atributo <a href="/es/docs/Web/HTML/Atributos_Globales/id">id</a> no está especificado para el elemento <code><canvas></code> pero es uno de los <a href="/es/docs/Web/HTML/Atributos_Globales">atributos globales de HTML</a> el cual puede ser aplicado a cualquier elemento HTML (como <a href="en-US/docs/Web/HTML/Global_attributes/class">class</a> por ejemplo). Siempre es buena idea proporcionar un <code>id</code> porque esto hace más fácil identificarlo en un script.</p> + +<p>El elemento <code><canvas></code> puede ser estilizado como a cualquier imagen normal (margin, border, background, etc). Estas reglas, sin embargo, no afectan a lo dibujado sobre el canvas. Mas adelante veremos cómo se hace esto en un <a href="en-US/docs/Web/API/Canvas_API/Tutorial/Applying_styles_and_colors">capítulo dedicado</a> en este tutorial. Cuando no tenemos reglas de estilo aplicadas al canvas, este será completamente transparente.</p> + +<div id="section_2"> +<h3 id="Contenido_alternativo">Contenido alternativo</h3> + +<p>El elemento <canvas> se diferencia de un tag {{HTMLElement("img")}} en que, como los elementos {{HTMLElement("video")}}, {{HTMLElement("audio")}} o {{HTMLElement("picture")}}, es fácil definir contenido alternativo (fallback content) para mostrarse en navegadores viejos que no soporten el elemento <canvas>, como versiones de Internet Explorer previas a la versión 9 o navegadores de texto. Siempre debes proporcionar contenido alternativo para mostrar en estos navegadores.</p> + +<p>Proporcionar contenido alternativo es muy explicito: solo debemos insertar el contenido alterno dentro del elemento <canvas>. Los navegadores que no soporten <code><canvas></code> ignoraran el contenedor y mostrarán el contenido indicado dentro de este. Navegadores que soporten <code><canvas></code> ignorarán el contenido en su interior (de las etiquetas), y mostrarán el canvas normalmente.</p> + +<p>Por ejemplo, podremos proporcionar un texto descriptivo del contenido del canvas o proveer una imagen estática del contenido rederizado. Nos podría quedar algo así:</p> + +<pre class="brush: html"><canvas id="stockGraph" width="150" height="150"> + current stock price: $3.15 +0.15 +</canvas> + +<canvas id="clock" width="150" height="150"> + <img src="images/clock.png" width="150" height="150" alt=""/> +</canvas> +</pre> + +<h2 id="Etiqueta_<canvas>_requerida">Etiqueta <code></canvas></code> requerida</h2> + +<p>De manera distinta al elemento {{HTMLElement("img")}}, el elemento {{HTMLElement("canvas")}} requiere cerrar la etiqueta (<code></canvas></code>).</p> + +<div class="note"> +<p><strong>Note:</strong> Aunque las versiones anteriores del navegador Safari de Apple no requeria el cierre de la etiqueta, la especificacion indica que es necesaria, asi que tu deberias incluir esta para asegurarte la compatibilidad. Aquellas versiones de Safari (anteriores versiones a 2.0) renderizaran el contenido de regreso agregandolo al canvas mismo a no ser que utilice trucos de CSS para enmascararlo. Afortunadamente, los usuarios de aquellas versiones de Safari son raros hoy en dia.</p> +</div> + +<p>Si el contenido alternativo no se necesita, un simple <code><canvas id="foo" ...></canvas></code> es completamente compatible con todos los navegadores que soportan canvas.</p> + +<h2 id="El_contexto_de_renderización">El contexto de renderización</h2> + +<p>{{HTMLElement("canvas")}} crea un lienzo de dibujo fijado que expone uno o mas contextos renderizados, los cuales son usados para crear y manipular el contenido mostrado. Nos enfocaremos en renderizacion de contextos 2D. Otros contextos deberan proveer diferentes tipos de renderizaciones; por ejemplo, <a href="/en-US/docs/Web/WebGL" title="/en-US/docs/Web/WebGL">WebGL</a> usa un 3D contexto ("experimental-webgl") basado sobre <a class="external" href="http://www.khronos.org/opengles/" rel="external" title="http://en.wikipedia.org/wiki/OpenGL_ES">OpenGL ES</a>.</p> + +<p>El canvas esta inicialmente en blanco. Para mostrar alguna cosa, un script primero necesita acceder al contexto a renderizar y dibujar sobre este. El elemento {{HTMLElement("canvas")}} tiene un <a href="/en-US/docs/Web/API/HTMLCanvasElement#Methods" title="/en-US/docs/Web/API/HTMLCanvasElement#Methods">method</a> llamado <code>getContext()</code>, usado para obtener el contexto a renderizar y sus funciones de dibujo. <code>getContext()</code> toma un parametro, el tipo de contexto. Para graficos 2D, como los que cubre este tutorial, su especificacion es "2d".</p> + +<pre class="brush: js">var canvas = document.getElementById('tutorial'); +var ctx = canvas.getContext('2d'); +</pre> + +<p>La primera linea regresa el nodo DOM para el elemento {{HTMLElement("canvas")}} llamando al metodo {{domxref("document.getElementById()")}}. Una vez tu tienes el elemento nodo, tu puedes acceder al contexto de dibujo usando su metodo <code>getContext()</code>.</p> + +<div id="section_5"> +<h2 id="Comprobando_soporte">Comprobando soporte</h2> + +<p>El contenido de regreso que es mostrado en navegadores los cuales no soportan {{HTMLElement("canvas")}}. Para los Scripts puede tambien comprobarse su soporte desde la programacion por un simple test para la presencia del metodo <code>getContext()</code>. Con un trozo de codigo parecido al que viene debajo:</p> + +<pre class="brush: js">var canvas = document.getElementById('tutorial'); + +if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + // drawing code here +} else { + // canvas-unsupported code here +} +</pre> +</div> +</div> + +<h2 id="Un_esqueleto_de_plantilla">Un esqueleto de plantilla</h2> + +<p>Aqui esta una plantilla minimalista, la cual usaremos como punto de partida para posteriores ejemplos.</p> + +<pre class="brush: html"><html> + <head> + <title>Canvas tutorial</title> + <script type="text/javascript"> + function draw(){ + var canvas = document.getElementById('tutorial'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + } + } + </script> + <style type="text/css"> + canvas { border: 1px solid black; } + </style> + </head> + <body onload="draw();"> + <canvas id="tutorial" width="150" height="150"></canvas> + </body> +</html> +</pre> + +<p>El script incluye una funcion llamada draw(), la cual es ejecutada una vez finalizada la carga de la pagina; este esta hecho usando el evento load del documento. Esta funcion, o una parecida, podria tambien ser llamada usando {{domxref("window.setTimeout()")}}, {{domxref("window.setInterval()")}}, o cualquier otro manejador de evento, a lo largo de que la pagina esta siendo cargada la primera vez.</p> + +<p>Aqui esta como la plantilla se ve en acción:</p> + +<p>{{EmbedLiveSample("Un_esqueleto_de_plantilla", 160, 160)}}</p> + +<h2 id="Un_simple_ejemplo">Un simple ejemplo</h2> + +<p>Para comenzar, daremos un vistazo a un simple ejemplo que dibuja dos rectangulos que se intersectan, uno de los cuales tiene alpha transparencia. Exploraremos como esto trabaja en mas detalle en posteriores ejemplos.</p> + +<pre class="brush: html"><html> + <head> + <script type="application/javascript"> + function draw() { + var canvas = document.getElementById("canvas"); + if (canvas.getContext) { + var ctx = canvas.getContext("2d"); + + ctx.fillStyle = "rgb(200,0,0)"; + ctx.fillRect (10, 10, 55, 50); + + ctx.fillStyle = "rgba(0, 0, 200, 0.5)"; + ctx.fillRect (30, 30, 55, 50); + } + } + </script> + </head> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> + +<p>Este ejemplo quedaría así:</p> + +<p>{{EmbedLiveSample("Un_simple_ejemplo", 160, 160, "https://mdn.mozillademos.org/files/228/canvas_ex1.png")}}</p> + +<p>{{PreviousNext("Web/Guide/HTML/Canvas_tutorial", "Web/Guide/HTML/Canvas_tutorial/Dibujando_formas")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/compositing/ejemplo/index.html b/files/es/web/api/canvas_api/tutorial/compositing/example/index.html index b85b83238c..b85b83238c 100644 --- a/files/es/web/api/canvas_api/tutorial/compositing/ejemplo/index.html +++ b/files/es/web/api/canvas_api/tutorial/compositing/example/index.html diff --git a/files/es/web/api/canvas_api/tutorial/drawing_shapes/index.html b/files/es/web/api/canvas_api/tutorial/drawing_shapes/index.html new file mode 100644 index 0000000000..3467533e93 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/drawing_shapes/index.html @@ -0,0 +1,513 @@ +--- +title: Dibujando formas con canvas +slug: Web/Guide/HTML/Canvas_tutorial/Dibujando_formas +tags: + - Canvas + - HTML + - HTML Canvas + - HTML5 + - Intermedio + - Tutorial + - graficos +translation_of: Web/API/Canvas_API/Tutorial/Drawing_shapes +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Basic_usage", "Web/API/Canvas_API/Tutorial/Applying_styles_and_colors")}}</div> + +<div class="summary"> +<p>Ahora que hemos preparado nuestro <a href="https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Tutorial/Basic_usage">entorno canvas</a>, podemos entrar en detalles de como dibujar en el canvas. Al final de este artículo, habrás aprendido como dibujar rectángulos, triángulos, líneas, arcos y curvas, dándote familiaridad con algunas figuras básicas. Trabajar con rutas es esencial cuando dibujamos objetos sobre el canvas y veremos como se puede hacer eso.</p> +</div> + +<h2 id="La_cuadrícula">La cuadrícula</h2> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/224/Canvas_default_grid.png" style="float: right; height: 220px; width: 220px;">Antes de que podamos empezar a dibujar, necesitamos hablar sobre la cuadrícula del canvas o el <strong>espacio de coordenadas</strong>. La plantilla HTML de la página anterior tenía un elemento canvas con un 'height' y un 'width' de 150 píxeles. A la derecha, puedes ver este canvas con la cuadrícula por defecto superpuesta. Normalmente una unidad en la cuadrícula corresponde a un píxel en el elemento canvas. El origen de esta cuadrícula está posicionado en la esquina superior izquierda (coordenada (0,0)). Todos los elementos estan posicionados de manera relativa a este punto, así que la posición de la esquina superior izquierda del cuadrado azul es de 'x' pixeles desde la izquierda y 'y' pixeles desde arriba (coordenada (x,y)). Mas tarde en este tutorial veremos como trasladar el punto de origen a una posicion diferente, girar la cuadrícula e incluso darle una escala diferente. Por ahora nos dedicaremos a lo mas común.</p> + +<h2 id="Dibujando_rectángulos">Dibujando rectángulos</h2> + +<p>A diferencia de <a href="/en-US/docs/SVG" rel="internal" title="en/SVG">SVG</a>, {{HTMLElement("canvas")}} solo soporta una forma primitiva: rectangulos. Todas las otras formas deben ser creadas por la combinación de uno o más trazos, listas de puntos conectados por líneas. Afortunadamente, tenemos una variedad de funciones para dibujar trazos que hacen posible componer formas muy complejas.</p> + +<div id="section_3"> +<p>Primero veamos el rectángulo. Aquí hay tres funciones que podemos usar en el canvas para dibujarlos:</p> + +<dl> + <dt><code>fillRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt> + <dd>Dibuja un rectángulo relleno.</dd> + <dt><code>strokeRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt> + <dd>Dibuja el contorno de un rectángulo.</dd> + <dt><code>clearRect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt> + <dd>Borra un área rectangular especificada, dejándola totalmente transparente.</dd> +</dl> + +<p>Cada una de estas tres funciones toma los mismos parámetros. X e Y especifican la posición del canvas (en relación con el origen) desde la esquina superior izquierda del rectángulo. Tambien especifica los parámetros de anchura y altura que proporcionan el tamaño del rectángulo.</p> + +<p>A continuación se muestra la función draw() de la página anterior, pero ahora haciendo uso de estas tres funciones.</p> + +<h3 id="Ejemplo_de_forma_rectangular">Ejemplo de forma rectangular</h3> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext) { + var ctx = canvas.getContext('2d'); + + ctx.fillRect(25,25,100,100); + ctx.clearRect(45,45,60,60); + ctx.strokeRect(50,50,50,50); + } +}</pre> + +<p>El resultado de este ejemplo se muestra a continuación.</p> + +<p>{{EmbedLiveSample("Rectangular_shape_example", 160, 160, "https://mdn.mozillademos.org/files/245/Canvas_rect.png")}}</p> + +<p>La función fillRect() dibuja un cuadrado grande negro de 100 píxeles en cada lado. La función clearRect() luego borra un cuadrado de 60x60 píxeles del centro, y luego strokeRect() es llamado para crear un contorno rectangular de 50x50 píxeles dentro del cuadrado borrado.</p> + +<p>En las próximas páginas veremos dos métodos alternativos para clearRect(), y también veremos cómo cambiar el color y el trazo de diferentes formas.</p> + +<p>A diferencia de las funciones de trazo que veremos en la próxima sección, las tres funciones del rectángulo dibujan inmediatamente en el canvas.</p> + +<h2 id="Dibujando_trazos">Dibujando trazos</h2> + +<p>Crear formas mediante trazos requiere algunos pasos adicionales.</p> + +<ol> + <li>Primero, se crea el trazo.</li> + <li>A continuación, se usan <a href="/es/docs/Web/API/CanvasRenderingContext2D#Paths">comandos de dibujo</a> para dibujar dentro del trazo.</li> + <li>Después, se cierra el trazo.</li> + <li>Una vez el trazo ha sido creado, se le puede dar contorno o relleno para renderizarlo.</li> +</ol> + +<p>Estas son las funciones que se usan para llevar a cabo estos pasos:</p> + +<dl> + <dt><code>beginPath()</code></dt> + <dd>Crea un nuevo trazo. Una vez creado, los comandos de dibujo futuros son aplicados dentro del trazo y usados para construir el nuevo trazo hacia arriba.</dd> + <dt><code>closePath()</code></dt> + <dd>Cierra el trazo de tal forma que los comandos de dibujo futuros son, una vez más redireccionados al contexto.</dd> + <dt><code>stroke()</code></dt> + <dd>Dibuja el contorno de la forma.</dd> + <dt><code>fill()</code></dt> + <dd>Dibuja una forma solida rellenando el área del trazo.</dd> +</dl> + +<p>El primer paso para crear un trazo es llamar la función <code>beginPath()</code>. Internamente, los trazos son guardados como una lista de subtrazos (lineas, arcos, etc) los cuales juntos crean una forma. Todo tiempo que sea llamado este método la lista es reseteada y podemos empezar a dibujar nuevas formas.</p> + +<div class="note"><strong>Nota:</strong> Cuando el trazo actual este vacio, como aparece inmediatamente despues de llamar la función <code>beginPath()</code>, o en un canvas nuevo, el primer comando para la construcción del trazo es siempre tratada como un <code>moveTo()</code>, independientemente de cual es el trazo actual. Por esta razón casi siempre querrás específicamente setear tu posición de inicio despues de resetear un trazo.</div> + +<p>El segundo paso es llamar los métodos que específican los trazos a crear. Los veremos en seguida.</p> + +<p>El tercero, y un paso opcional, es llamar a la función <code>closePath()</code>. Este método trata de cerrar la forma dibujando una linea recta desde el punto actual al inicio. Si la forma ya ha sido cerrada o hay solamente un punto en la lista, la función hace nada.</p> + +<div class="note"><strong>Nota:</strong> Cuando llamas a la función <code>fill()</code>, cualquier forma abierta es cerrada automaticamente, de tal forma que no tendrás que llamar a la función <code>closePath()</code>. Este no es el caso cuando llamas a la función <code>stroke()</code>.</div> + +<h3 id="Dibujando_un_triangulo">Dibujando un triangulo</h3> + +<p>Por ejemplo, el código para dibujar un triangulo luciría como el siguiente:</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + ctx.beginPath(); + ctx.moveTo(75,50); + ctx.lineTo(100,75); + ctx.lineTo(100,25); + ctx.closePath(); + ctx.fill(); + } +} +</pre> + +<p>El resultado lucirá así:</p> + +<p>{{EmbedLiveSample("Drawing_a_triangle", 160, 160)}}</p> + +<h3 id="Moviendo_la_pluma">Moviendo la pluma</h3> + +<p>Una función muy útil, la cual realmente no dibuja algo pero convierte parte de la lista de trazos descrita arriba, es la función <code>moveTo()</code>. Puedes, probablemente, pensar mejor de esta como levantar el lápiz o la pluma de un punto en un pedazo de papel y ponerlo en el siguiente punto.</p> + +<dl> + <dt><code>moveTo(<em>x</em>, <em>y</em>)</code></dt> + <dd>Mueve la pluma a las coordenadas específicadas por <code>x</code> e <code>y</code>.</dd> +</dl> + +<p>Cuando el canvas es inicializado ó la función <code>beginPath()</code> es llamada, querrás usar la función <code>moveTo()</code> para colocar el punto de inicio en alguna otra parte. Podríamos usar <code>moveTo()</code> para dibujar trazos sin conectar. Toma un vistazo a la cara sonriente de abajo. He marcado los lugares donde use el método <code>moveTo()</code> (las líneas rojas).</p> + +<p>Para intentar esto por tí mismo, puedes usar el pequeño código de abajo. Solo pégalo dentro de la función <code>draw()</code> que vimos antes.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + ctx.beginPath(); + ctx.arc(75,75,50,0,Math.PI*2,true); // Círculo externo + ctx.moveTo(110,75); + ctx.arc(75,75,35,0,Math.PI,false); // Boca (contra reloj) + ctx.moveTo(65,65); + ctx.arc(60,65,5,0,Math.PI*2,true); // Ojo izquierdo + ctx.moveTo(95,65); + ctx.arc(90,65,5,0,Math.PI*2,true); // Ojo derecho + ctx.stroke(); + } +} +</pre> + +<p>El resultado luce así:</p> + +<p>{{EmbedLiveSample("Moving_the_pen", 160, 160, "https://mdn.mozillademos.org/files/252/Canvas_smiley.png")}}</p> + +<p>Si quisieras ver las líneas conectadas, puedes remover las líneas de código que llaman <code>moveTo()</code>.</p> + +<div class="note"> +<p><strong>Nota:</strong> Para aprender más sobre la función <code>arc()</code>, vea los {{anch("Arcs")}} a continuación.</p> +</div> + +<h3 id="Líneas">Líneas</h3> + +<p>Para dibujar lineas rectas usa el método <code>lineTo()</code>.</p> + +<dl> + <dt><code>lineTo(<em>x</em>, <em>y</em>)</code></dt> + <dd>Dibuja una línea desde la posición actual del dibujo a la posición específicada por <code>x</code> e <code>y</code>.</dd> +</dl> + +<p>Este método toma dos argumentos <code>x</code> e <code>y</code>, los cuales son las coordenadas del punto final de la linea. El punto de inicio es dependiente de los trazos previamente dibujados, donde el punto final del trazo anterior es el punto inicial para el siguiente, etc. El punto de inicio también puede ser cambiado usando el método <code>moveTo()</code>.</p> + +<p>El ejemplo siguiente dibuja dos triángulos, uno rellenado y el otro contorneado.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + // Triángulo rellenado + ctx.beginPath(); + ctx.moveTo(25,25); + ctx.lineTo(105,25); + ctx.lineTo(25,105); + ctx.fill(); + + // Triángulo contorneado + ctx.beginPath(); + ctx.moveTo(125,125); + ctx.lineTo(125,45); + ctx.lineTo(45,125); + ctx.closePath(); + ctx.stroke(); + } +} +</pre> + +<p>Esto comienza llamando a <code>beginPath()</code> para empezar una nueva forma. Entonces usamos el método <code>moveTo()</code> para mover el punto de inicio a la posición deseada. Debajo de esto dos líneas son dibujadas lo cual pinta dos lados del triángulo.</p> + +<p>{{EmbedLiveSample("Lines", 160, 160, "https://mdn.mozillademos.org/files/238/Canvas_lineTo.png")}}</p> + +<p>Te darás cuenta de la diferencia entre el triángulo rellenado y el contorneado. Esto es, como se menciona arriba, porque las formas son automáticamente cerradas cuando un trazo es rellenado, pero no cuando esta contorneado. Si sacamos el <code>closePath()</code> para el triángulo contorneado, solamente dos líneas serian dibujadas, no un triángulo completo.</p> + +<h3 id="Arcos">Arcos</h3> + +<p>Para dibujar arcos o circulos usamos el método <code>arc()</code>. También puedes usar <code>arcTo()</code>, pero su implementación es un poco menos confiable, así que no lo cubriremos aquí.</p> + +<dl> + <dt><code>arc(<em>x</em>, <em>y</em>, <em>radius</em>, <em>startAngle</em>, <em>endAngle</em>, <em>anticlockwise</em>)</code></dt> + <dd>Dibuja un arco.</dd> +</dl> + +<p>Este método toma cinco parámetros: <code>x</code> e <code>y</code> son las coordenadas del centro del círculo en el cual el arco debería ser dibujado. <code>radius</code> se explica por sí solo. Los parámetros <code>startAngle</code> y <code>endAngle</code> definen el punto de inicio y punto final del arco en radianes a lo largo de la curva del círculo. Estos son medidos desde el eje x. El parámetro <code>anticlockwise</code> es un valor Booleano el cual cuando es verdadero (<code>true</code>) dibuja el arco al contrario de las manecillas del reloj, de lo contrario el arco es dibujado al sentido de las manecillas del reloj.</p> + +<div class="note"> +<p><strong>Nota</strong>: Los ángulos en la función del arco (<code>arc</code>) son medidos en radianes, no en grados. Para convertir grados a radianes puedes usar la siguiente expresión en Javascript: <code>radians = (Math.PI/180)*degrees</code>.</p> +</div> + +<p>El siguiente ejemplo es un poco más complejo que otros que hemos visto arriba. Esto dibuja 12 diferentes arcos, todos con diferentes ángulos y rellenos.</p> + +<p>Las dos sentencias <code>for</code> son para iterar a través de las filas y columnas de los arcos. Para cada arco, empezamos un nuevo trazo llamando <code>beginPath()</code>. En el código, cada uno de los parámetros para el arco estan en una variable para su entendimiento, pero no es necesario esto en la vida real.</p> + +<p>Las coordenadas <code>x</code> e <code>y</code> deberían ser suficientemente claras. <code>radius</code> y <code>startAngle</code> estan arreglados. El <code>endAngle</code> inicia en 180 grados (la mitad de un círculo) en la primera columna y es incrementado por pasos de 90 grados, culminando en un círculo completo en la última columna.</p> + +<p>El parámetro <code>clockwise</code> resulta, en la primera y tercera fila siendo dibujado como un arco al sentido de las manecillas de reloj y la segunda y cuarta fila como arcos al contrario de las manecillas de reloj. Finalmente, la estructura <code>if</code> hace los arcos contorneados a la mitad desde arriba y los arcos hacia abajorellenados a la mitad.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="200"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + for(var i=0;i<4;i++){ + for(var j=0;j<3;j++){ + ctx.beginPath(); + var x = 25+j*50; // Coordenada x + var y = 25+i*50; // Coordenada y + var radius = 20; // Radio del arco + var startAngle = 0; // Punto inicial del círculo + var endAngle = Math.PI+(Math.PI*j)/2; // Punto final del círculo + var anticlockwise = i%2==0 ? false : true; // Sentido de las manecillas del reloj y contrario a ellas + + ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise); + + if (i>1){ + ctx.fill(); + } else { + ctx.stroke(); + } + } + } + } +} +</pre> +{{EmbedLiveSample("Arcs", 160, 210, "https://mdn.mozillademos.org/files/204/Canvas_arc.png")}} + +<h3 id="Curvas_Bezier_curvas_cuadráticas">Curvas Bezier curvas cuadráticas</h3> + +<p>El siguiente tipo de trazos disponibles son las <a class="external" href="http://en.wikipedia.org/wiki/B%C3%A9zier_curve" rel="external" title="http://en.wikipedia.org/wiki/B%C3%A9zier_curve">curvas Bézier</a>, en sus dos variantes, cúbicas y cuadráticas. Son usadas generalmente para dibujar complejas formas orgánicas.</p> + +<dl> + <dt><code>quadraticCurveTo(cp1x, cp1y, x, y)</code></dt> + <dd><span id="result_box" lang="es"><span>Dibuja una curva cuadrática de Bézier desde la posición actual de la pluma hasta el punto final especificado por <code>x</code> e <code>y</code>, utilizando el punto de control especificado por <code>cp1x</code> y <code>cp1y</code>.</span></span></dd> + <dt><code>bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y)</code></dt> + <dd>Dibuja una curva cúbica de Bézier desde la posición actual de la pluma hasta el punto final especificado por <code>x</code> e <code>y</code>, utilizando los puntos de control especificados por (<code>cp1x</code>, <code>cp1y</code>) y (<code>cp2x</code>, <code>cp2y</code>).</dd> +</dl> + +<p><img alt="" class="internal" src="https://mdn.mozillademos.org/files/223/Canvas_curves.png" style="float: right; height: 190px; width: 190px;">La diferencia entre estos puede describirse mejor utilizando la imagen de la derecha. Una curva cuadrática de Bézier tiene un punto inicial y un punto final (puntos azules) y un solo <strong>punto de control</strong> (indicado por el punto rojo), mientras que una curva cúbica de Bézier utiliza dos puntos de control.</p> + +<p>Los parámetros <code>x</code> e <code>y</code> de ambos métodos son las coordenadas del punto final. <code>cp1x</code> y <code>cp1y</code> son las coordenadas del primer punto de control, y <code>cp2x</code> y <code>cp2y</code> son las coordenadas del segundo punto de control.</p> + +<p>El uso de curvas cuadráticas y cúbicas Bézier puede ser bastante difícil, ya que a diferencia del software de dibujo vectorial como Adobe Illustrator, no tenemos respuesta visual directa en cuanto a lo que estamos haciendo. Esto hace bastante difícil dibujar formas complejas. En el siguiente ejemplo, vamos a dibujar algunas formas orgánicas simples, pero si tienes el tiempo y, sobre todo, la paciencia, se pueden crear formas mucho más complejas.</p> + +<p>No hay nada muy difícil en estos ejemplos. En ambos casos vemos una sucesión de curvas que se dibujan que finalmente dan lugar a una forma completa.</p> + +<h4 id="Curvas_de_Bezier_cuadraticas">Curvas de Bezier cuadraticas</h4> + +<p>Este ejemplo usa multiples curvas cuadraticas de Bézier para renderizar un globo de voz.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext) { + var ctx = canvas.getContext('2d'); + + // Quadratric curves example + ctx.beginPath(); + ctx.moveTo(75,25); + ctx.quadraticCurveTo(25,25,25,62.5); + ctx.quadraticCurveTo(25,100,50,100); + ctx.quadraticCurveTo(50,120,30,125); + ctx.quadraticCurveTo(60,120,65,100); + ctx.quadraticCurveTo(125,100,125,62.5); + ctx.quadraticCurveTo(125,25,75,25); + ctx.stroke(); + } +} +</pre> + +<p>{{EmbedLiveSample("Quadratic_Bezier_curves", 160, 160, "https://mdn.mozillademos.org/files/243/Canvas_quadratic.png")}}</p> + +<h4 id="Curvas_cúbicas_Bezier">Curvas cúbicas Bezier</h4> + +<p>Este ejemplo dibuja un corazon usanco curvas cúbicas de Bézier.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + // Quadratric curves example + ctx.beginPath(); + ctx.moveTo(75,40); + ctx.bezierCurveTo(75,37,70,25,50,25); + ctx.bezierCurveTo(20,25,20,62.5,20,62.5); + ctx.bezierCurveTo(20,80,40,102,75,120); + ctx.bezierCurveTo(110,102,130,80,130,62.5); + ctx.bezierCurveTo(130,62.5,130,25,100,25); + ctx.bezierCurveTo(85,25,75,37,75,40); + ctx.fill(); + } +} +</pre> + +<p>{{EmbedLiveSample("Cubic_Bezier_curves", 160, 160, "https://mdn.mozillademos.org/files/207/Canvas_bezier.png")}}</p> + +<h3 id="Rectangles">Rectangles</h3> + +<p>In addition to the three methods we saw in {{anch("Drawing rectangles")}}, which draw rectangular shapes directly to the canvas, there's also the <code>rect()</code> method, which adds a rectangular path to a currently open path.</p> + +<dl> + <dt><code>rect(<em>x</em>, <em>y</em>, <em>width</em>, <em>height</em>)</code></dt> + <dd>Draws a rectangle whose top-left corner is specified by (<code>x</code>, <code>y</code>) with the specified <code>width</code> and <code>height</code>.</dd> +</dl> + +<p>When this method is executed, the <code>moveTo()</code> method is automatically called with the parameters (0,0). In other words, the current pen position is automatically reset to the default coordinates.</p> + +<h3 id="Making_combinations">Making combinations</h3> + +<p>So far, each example on this page has used only one type of path function per shape. However, there's no limitation to the number or types of paths you can use to create a shape. So in this final example, let's combine all of the path functions to make a set of very famous game characters.</p> + +<div class="hidden"> +<pre class="brush: html"><html> + <body onload="draw();"> + <canvas id="canvas" width="150" height="150"></canvas> + </body> +</html> +</pre> +</div> + +<pre class="brush: js">function draw() { + var canvas = document.getElementById('canvas'); + if (canvas.getContext){ + var ctx = canvas.getContext('2d'); + + roundedRect(ctx,12,12,150,150,15); + roundedRect(ctx,19,19,150,150,9); + roundedRect(ctx,53,53,49,33,10); + roundedRect(ctx,53,119,49,16,6); + roundedRect(ctx,135,53,49,33,10); + roundedRect(ctx,135,119,25,49,10); + + ctx.beginPath(); + ctx.arc(37,37,13,Math.PI/7,-Math.PI/7,false); + ctx.lineTo(31,37); + ctx.fill(); + + for(var i=0;i<8;i++){ + ctx.fillRect(51+i*16,35,4,4); + } + + for(i=0;i<6;i++){ + ctx.fillRect(115,51+i*16,4,4); + } + + for(i=0;i<8;i++){ + ctx.fillRect(51+i*16,99,4,4); + } + + ctx.beginPath(); + ctx.moveTo(83,116); + ctx.lineTo(83,102); + ctx.bezierCurveTo(83,94,89,88,97,88); + ctx.bezierCurveTo(105,88,111,94,111,102); + ctx.lineTo(111,116); + ctx.lineTo(106.333,111.333); + ctx.lineTo(101.666,116); + ctx.lineTo(97,111.333); + ctx.lineTo(92.333,116); + ctx.lineTo(87.666,111.333); + ctx.lineTo(83,116); + ctx.fill(); + + ctx.fillStyle = "white"; + ctx.beginPath(); + ctx.moveTo(91,96); + ctx.bezierCurveTo(88,96,87,99,87,101); + ctx.bezierCurveTo(87,103,88,106,91,106); + ctx.bezierCurveTo(94,106,95,103,95,101); + ctx.bezierCurveTo(95,99,94,96,91,96); + ctx.moveTo(103,96); + ctx.bezierCurveTo(100,96,99,99,99,101); + ctx.bezierCurveTo(99,103,100,106,103,106); + ctx.bezierCurveTo(106,106,107,103,107,101); + ctx.bezierCurveTo(107,99,106,96,103,96); + ctx.fill(); + + ctx.fillStyle = "black"; + ctx.beginPath(); + ctx.arc(101,102,2,0,Math.PI*2,true); + ctx.fill(); + + ctx.beginPath(); + ctx.arc(89,102,2,0,Math.PI*2,true); + ctx.fill(); + } +} + +// A utility function to draw a rectangle with rounded corners. + +function roundedRect(ctx,x,y,width,height,radius){ + ctx.beginPath(); + ctx.moveTo(x,y+radius); + ctx.lineTo(x,y+height-radius); + ctx.quadraticCurveTo(x,y+height,x+radius,y+height); + ctx.lineTo(x+width-radius,y+height); + ctx.quadraticCurveTo(x+width,y+height,x+width,y+height-radius); + ctx.lineTo(x+width,y+radius); + ctx.quadraticCurveTo(x+width,y,x+width-radius,y); + ctx.lineTo(x+radius,y); + ctx.quadraticCurveTo(x,y,x,y+radius); + ctx.stroke(); +} +</pre> + +<div id="section_18"> +<p>The resulting image looks like this:</p> + +<p>{{EmbedLiveSample("Making_combinations", 160, 160)}}</p> + +<p>We won't go over this in detail, since it's actually surprisingly simple. The most important things to note are the use of the <code>fillStyle</code> property on the drawing context, and the use of a utility function (in this case <code>roundedRect()</code>). Using utility functions for bits of drawing you do often can be very helpful and reduce the amount of code you need, as well as its complexity.</p> + +<p>We'll take another look at <code>fillStyle</code>, in more detail, later in this tutorial. Here, all we're doing is using it to change the fill color for paths from the default color of black to white, and then back again.</p> + +<p>{{PreviousNext("Web/Guide/HTML/Canvas_tutorial/Basic_usage", "Web/Guide/HTML/Canvas_tutorial/Using_images")}}</p> +</div> +</div> + +<p> </p> diff --git a/files/es/web/api/canvas_api/tutorial/drawing_text/index.html b/files/es/web/api/canvas_api/tutorial/drawing_text/index.html new file mode 100644 index 0000000000..10a5970824 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/drawing_text/index.html @@ -0,0 +1,67 @@ +--- +title: Dibujar texto usando canvas +slug: Dibujar_texto_usando_canvas +tags: + - 'HTML:Canvas' +translation_of: Web/API/Canvas_API/Tutorial/Drawing_text +--- +<p>{{ Gecko_minversion_header(1.9) }} +{{ Fx_minversion_header(3) }} +El elemento <code><a href="es/HTML/Canvas"><canvas></a></code> permite dibujar texto en él a través de una API experimental de Mozilla. +</p> +<h3 id="API" name="API"> API </h3> +<pre class="eval">attribute DOMString mozTextStyle; +void mozDrawText(in DOMString textToDraw); +float mozMeasureText(in DOMString textToMeasure); +void mozPathText(in DOMString textToPath); +void mozTextAlongPath(in DOMString textToDraw, in boolean stroke); +</pre> +<h3 id="Notas" name="Notas"> Notas </h3> +<ul><li> El tipo de letra predeterminado es sans-serif 12pt. +</li><li> Estas extensiones de texto no están aún estandarizadas por WHATWG. +</li><li> No necesitas un contexto especial para usarlas; el contexto 2D funciona bien. +</li><li> Todos los dibujos se realizan usando la transformación actual. +</li><li> Revisa el {{ Bug(339553) }} si quieres leer más sobre las implementaciones específicas. +</li></ul> +<h3 id="Demostraciones" name="Demostraciones"> Demostraciones </h3> +<p>Mira algunos ejemplos <a class="link-https" href="https://bugzilla.mozilla.org/attachment.cgi?id=273497">aquí</a>, <a class="link-https" href="https://bugzilla.mozilla.org/attachment.cgi?id=273498">aquí</a>, y <a class="link-https" href="https://bugzilla.mozilla.org/attachment.cgi?id=273499">aquí</a>. +</p> +<h3 id="Cambiar_el_tipo_de_letra_actual" name="Cambiar_el_tipo_de_letra_actual"> Cambiar el tipo de letra actual </h3> +<p>El atributo <code>mozTextStyle</code> contiene el estilo de texto actual. Usa la misma sintaxis que el especificado para las <a href="es/CSS/font">tipografías CSS</a>. +</p><p>Ej: +</p> +<pre class="eval">ctx.mozTextStyle = "20pt Arial" +</pre> +<h3 id="Dibujar_texto" name="Dibujar_texto"> Dibujar texto </h3> +<p>Dibujar es muy sencillo. <code>mozDrawText</code> usa el estilo de texto actual, cualquiera que sea éste. Se usa el color de relleno del contexto como color del texto. +</p> +<pre class="eval">ctx.translate(10, 50); +ctx.fillStyle = "Red"; +ctx.mozDrawText("Sample String"); +</pre> +<h3 id="Medir_texto" name="Medir_texto"> Medir texto </h3> +<p>A veces es útil saber qué tan ancho es un trozo de texto en particular (para centrarlo en una ventana, por ejemplo). +</p> +<pre class="eval">var text = "Sample String"; +var width = ctx.canvas.width; +var len = ctx.mozMeasureText(text); +ctx.translate(len/2, 0); +ctx.mozDrawText(text); +</pre> +<h3 id="Interacci.C3.B3n_texto.2Ftrazo" name="Interacci.C3.B3n_texto.2Ftrazo"> Interacción texto/trazo </h3> +<p>Si quieres tachar un texto, <code>mozDrawText</code> no te lo permite. En cambio, <code>mozPathText</code> agrega el tachado de texto al trazo actual. +</p> +<pre class="eval">ctx.fillStyle = "green"; +ctx.strokeStyle = "black"; +ctx.mozPathText("Sample String"); +ctx.fill() +ctx.stroke() +</pre> +<p>Supongamos ahora que quieres agregar un texto que se acomode a un trazo que dibujaste (una línea curva o algo parecido) es donde aparece <code>mozTextAlongPath</code>. Al contrario de otras funciones de texto, <code>mozTextAlongPath</code> necesita dos argumentos: el texto y qué se quiere hacer con él. <code>mozTextAlongPath</code> aproxima el trazo actual como una serie de segmentos de línea y ubica cada carácter encima de ese trazo. Los caracteres no son cambiados de tamaño o transformados de acuerdo a la curvatura de la base; toman la orientación del trazo a la mitad del carácter. +</p><p>Una vez que <code>mozTextAlongPath</code> sabe dónde está el carácter, busca el segundo parámetro para decidir qué hacer con él. Si el segundo parámetro es <code>false</code>, entonces dibuja el carácter como lo haría <code>mozDrawText</code>. Si es <code>true</code>, agrega el carácter al trazo actual, como lo hace <code>mozPathText</code>. Esto puede usarse para crear efectos únicos. +</p><p><br> +</p><p><br> +</p> +<div class="noinclude"> +</div> +{{ languages( { "en": "en/Drawing_text_using_a_canvas", "fr": "fr/Dessin_de_texte_avec_canvas", "ja": "ja/Drawing_text_using_a_canvas", "pl": "pl/Rysowanie_tekstu_przy_u\u017cyciu_canvas" } ) }} diff --git a/files/es/web/api/canvas_api/tutorial/hit_regions_and_accessibility/index.html b/files/es/web/api/canvas_api/tutorial/hit_regions_and_accessibility/index.html new file mode 100644 index 0000000000..967710de49 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/hit_regions_and_accessibility/index.html @@ -0,0 +1,99 @@ +--- +title: Hit regions and accessibility +slug: Web/Guide/HTML/Canvas_tutorial/Hit_regions_and_accessibility +translation_of: Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility +--- +<div>{{CanvasSidebar}} {{ PreviousNext("Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas", "Web/API/Canvas_API/Tutorial/Optimizing_canvas") }}</div> + +<div class="summary">The {{HTMLElement("canvas")}} element on its own is just a bitmap and does not provide information about any drawn objects. Canvas content is not exposed to accessibility tools like semantic HTML is. In general, you should avoid using canvas in an accessible website or app. The following guidelines can help to make it more accessible.</div> + +<div class="summary">El elemento {{HTMLElement ("canvas")}} por sí solo es solo un mapa de bits y no proporciona información sobre ningún objeto dibujado. El contenido del lienzo no está expuesto a herramientas de accesibilidad como el HTML semántico. En general, debe evitar usar canvas en un sitio web o aplicación accesible. Las siguientes pautas pueden ayudar a que sea más accesible.</div> + +<h2 id="Fallback_content">Fallback content</h2> + +<p>The content inside the <code><canvas> ... </canvas></code> tags can be used as a fallback for browsers which don't support canvas rendering. It's also very useful for assistive technology users (like screen readers) which can read and interpret the sub DOM in it. A good example at <a href="http://www.html5accessibility.com/tests/canvas.html">html5accessibility.com</a> demonstrates how this can be done:</p> + +<pre class="brush: html"><canvas> + <h2>Shapes</h2> + <p>A rectangle with a black border. + In the background is a pink circle. + Partially overlaying the <a href="http://en.wikipedia.org/wiki/Circle" onfocus="drawCircle();" onblur="drawPicture();">circle</a>. + Partially overlaying the circle is a green + <a href="http://en.wikipedia.org/wiki/Square" onfocus="drawSquare();" onblur="drawPicture();">square</a> + and a purple <a href="http://en.wikipedia.org/wiki/Triangle" onfocus="drawTriangle();" onblur="drawPicture();">triangle</a>, + both of which are semi-opaque, so the full circle can be seen underneath.</p> +</canvas> </pre> + +<p>See the <a href="https://www.youtube.com/watch?v=ABeIFlqYiMQ">video how NVDA reads this example by Steve Faulkner</a>.</p> + +<h2 id="ARIA_rules">ARIA rules</h2> + +<p>Accessible Rich Internet Applications <strong>(<a href="/en-US/docs/Web/Accessibility/ARIA">ARIA</a>)</strong> defines ways to make Web content and Web applications more accessible to people with disabilities. You can use ARIA attributes to describe the behavior and purpose of the canvas element. See <a href="/en-US/docs/Web/Accessibility/ARIA">ARIA</a> and <a href="/en-US/docs/Web/Accessibility/ARIA/ARIA_Techniques">ARIA techniques</a> for more information.</p> + +<pre class="brush: html"><canvas id="button" tabindex="0" role="button" aria-pressed="false" aria-label="Start game"></canvas> +</pre> + +<h2 id="Hit_regions">Hit regions</h2> + +<p>Whether the mouse coordinates are within a particular area on the canvas, is a common problem to solve. The hit region API allows you to define an area of your canvas and provides another possibility to expose interactive content on a canvas to accessibility tools. It allows you to make hit detection easier and lets you route events to DOM elements. The API has the following three methods (which are still experimental in current web browsers; check the browser compatibility tables).</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.addHitRegion()")}} {{experimental_inline}}</dt> + <dd>Adds a hit region to the canvas.</dd> + <dt>{{domxref("CanvasRenderingContext2D.removeHitRegion()")}} {{experimental_inline}}</dt> + <dd>Removes the hit region with the specified <code>id</code> from the canvas.</dd> + <dt>{{domxref("CanvasRenderingContext2D.clearHitRegions()")}} {{experimental_inline}}</dt> + <dd>Removes all hit regions from the canvas.</dd> +</dl> + +<p>You can add a hit region to your path and check for the {{domxref("MouseEvent.region")}} property to test if your mouse is hitting your region, for example.</p> + +<pre class="brush: html"><canvas id="canvas"></canvas> +<script> +var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); + +ctx.beginPath(); +ctx.arc(70, 80, 10, 0, 2 * Math.PI, false); +ctx.fill(); +ctx.addHitRegion({id: 'circle'}); + +canvas.addEventListener('mousemove', function(event) { + if (event.region) { + alert('hit region: ' + event.region); + } +}); +</script></pre> + +<p>The <code>addHitRegion()</code> method also takes a <code>control</code> option to route events to an element (that is a descendant of the canvas):</p> + +<pre class="brush: js">ctx.addHitRegion({control: element});</pre> + +<p>This can be useful for routing to {{HTMLElement("input")}} elements, for example. See also this <a href="https://codepen.io/peterj35/pen/PEdLKx">codepen demo</a>.</p> + +<h2 id="Focus_rings">Focus rings</h2> + +<p>When working with the keyboard, focus rings are a handy indicator to help navigating on a page. To draw focus rings on a canvas drawing, the <code>drawFocusIfNeeded</code> property can be used.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.drawFocusIfNeeded()")}} {{experimental_inline}}</dt> + <dd>If a given element is focused, this method draws a focus ring around the current path.</dd> +</dl> + +<p>Additionally, the <code>scrollPathIntoView()</code> method can be used to make an element visible on the screen if focused, for example.</p> + +<dl> + <dt>{{domxref("CanvasRenderingContext2D.scrollPathIntoView()")}} {{experimental_inline}}</dt> + <dd>Scrolls the current path or a given path into the view.</dd> +</dl> + +<h2 id="See_also">See also</h2> + +<ul> + <li><a href="https://www.w3.org/WAI/PF/HTML/wiki/Canvas_Accessibility_Use_Cases">Canvas accessibility use cases</a></li> + <li><a href="https://www.w3.org/html/wg/wiki/AddedElementCanvas">Canvas element accessibility issues</a></li> + <li><a href="http://www.paciellogroup.com/blog/2012/06/html5-canvas-accessibility-in-firefox-13/">HTML5 Canvas Accessibility in Firefox 13 – by Steve Faulkner</a></li> + <li><a href="https://html.spec.whatwg.org/multipage/scripting.html#best-practices">Best practices for interactive canvas elements</a></li> +</ul> + +<div>{{ PreviousNext("Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas", "Web/API/Canvas_API/Tutorial/Optimizing_canvas") }}</div> diff --git a/files/es/web/api/canvas_api/tutorial/index.html b/files/es/web/api/canvas_api/tutorial/index.html new file mode 100644 index 0000000000..da5b0b3cc9 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/index.html @@ -0,0 +1,61 @@ +--- +title: Tutorial Canvas +slug: Web/Guide/HTML/Canvas_tutorial +tags: + - Canvas + - HTML5 + - graficos +translation_of: Web/API/Canvas_API/Tutorial +--- +<p><a href="/en-US/docs/HTML/Canvas" title="HTML/Canvas"><img alt="" src="https://mdn.mozillademos.org/files/257/Canvas_tut_examples.jpg" style="float: right; height: 450px; width: 200px;"></a></p> + +<p><a href="/en-US/docs/HTML/Canvas" title="HTML/Canvas"><strong><code><canvas></code></strong></a> es un elemento <a href="/en-US/docs/HTML" title="HTML">HTML</a> el cual puede ser usado para dibujar gráficos usando scripts (normalmente <a href="/en-US/docs/JavaScript" title="JavaScript">JavaScript</a>). Este puede, por ejemplo, ser usado para dibujar gráficos, realizar composición de fotos o simples (y <a href="/en-US/docs/HTML/Canvas/A_Basic_RayCaster" title="A_Basic_RayCaster">no tan simples</a>) animaciones. Las imágenes a la derecha muestran algunos ejemplos de implementaciones <code><canvas></code> las cuales se verán en un futuro en este tutorial.</p> + +<p><code><canvas></code> fue introducido primero por Apple para el Mac OS X Dashboard y después implementado en Safari y Google Chrome. Navegadores basados en <a href="/en-US/docs/Gecko" title="Gecko">Gecko</a> 1.8, tal como Firefox 1.5, que también soportan este elemento. El <code><canvas></code> es un elemento parte de las especificaciones de la <a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/">WhatWG Web applications 1.0</a> mejor conocida como HTML5.</p> + +<p><span class="seoSummary">En este tutorial se describe cómo usar el elemento <code><canvas></code> para dibujar gráficos en 2D, empezando con lo básico. Los ejemplos le proveerán mayor claridad a las ideas que pueda tener referentes al canvas, así como los códigos que necesita para crear su propio contenido.</span></p> + +<h2 id="Before_you_start" name="Before_you_start">Antes de Empezar</h2> + +<p>Usar el elemento <code><canvas></code> no es algo muy díficil pero necesita saber y entender los aspectos básicos del <a href="/en-US/docs/HTML" title="HTML">HTML</a> y <a href="/en-US/docs/JavaScript" title="JavaScript">JavaScript</a>. El elemento <code><canvas></code> no está soportado en navegadores viejos, pero están soportado en la mayoría de las versiones más recientes de los navegadores. El tamaño por defecto del canvas es 300px * 150px [ancho (width) * alto (height)]. Pero se puede personalizar el tamaño usando las propiedades height y width de CSS.<span id="result_box" lang="es"><span class="hps"> Con el fin de</span> <span class="hps">dibujar gráficos</span> <span class="hps">en el lienzo</span> <span class="hps"><canvas> se utiliza un</span> <span class="hps">objeto de contexto de</span> <span class="hps">JavaScript</span> <span class="hps">que crea</span> <span class="hps">gráficos</span> <span class="hps">sobre la marcha.</span></span></p> + +<h2 id="In_this_tutorial" name="In_this_tutorial">En este Tutorial</h2> + +<ul> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Basic_usage" title="Canvas_tutorial/Basic_usage">Usos Básicos</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Drawing_shapes" title="Canvas_tutorial/Drawing_shapes">Dibujando Formas</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Using_images" title="Canvas_tutorial/Using_images">Usando Imágenes</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Applying_styles_and_colors" title="Canvas_tutorial/Applying_styles_and_colors">Aplicando estilos y colores</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Transformations" title="Canvas_tutorial/Transformations">Transformaciones</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Compositing" title="Canvas_tutorial/Compositing">Composiciones</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Basic_animations" title="Canvas_tutorial/Basic_animations">Animaciones Básicas</a></li> + <li><a href="/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Optimizing_canvas" title="https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Canvas_tutorial/Optimizing_canvas">Optimización de Canvas</a></li> +</ul> + +<h2 id="See_also" name="See_also">Vea también</h2> + +<ul> + <li><a href="/en-US/docs/HTML/Canvas" title="HTML/Canvas">Canvas topic page</a></li> + <li><a href="/en-US/docs/HTML/Canvas/Drawing_Graphics_with_Canvas" title="Drawing_Graphics_with_Canvas">Drawing Graphics with Canvas</a></li> + <li><a href="/en-US/docs/tag/Canvas_examples" title="tag/Canvas_examples">Canvas examples</a></li> + <li><a href="http://www.html5andcss3.org">HTML5 Tutorial</a></li> + <li><a href="/en-US/docs/Drawing_text_using_a_canvas" title="Drawing_text_using_a_canvas">Drawing Text Using a Canvas</a></li> + <li><a class="external" href="http://developer.apple.com/library/safari/#documentation/AudioVideo/Conceptual/HTML-canvas-guide/AddingText/AddingText.html#//apple_ref/doc/uid/TP40010542-CH6-SW4" title="Adding Text to Canvas">Adding Text to Canvas</a></li> + <li><a class="external" href="http://www.canvasdemos.com/" title="Canvas Demos">Canvas Demos - Games, applications, tools and tutorials</a></li> + <li><a class="external" href="http://canvimation.github.com/" title="http://canvimation.github.com/">Canvas Drawing and Animation Application</a></li> + <li><a class="external" href="http://billmill.org/static/canvastutorial/" title="http://billmill.org/static/canvastutorial/">Interactive canvas tutorial</a></li> + <li><a class="external" href="http://blog.nihilogic.dk/2009/02/html5-canvas-cheat-sheet.html" title="http://blog.nihilogic.dk/2009/02/html5-canvas-cheat-sheet.html">Canvas Cheat Sheet with all attributes and methods</a></li> + <li><a class="external" href="http://visitmix.com/labs/ai2canvas/" title="http://visitmix.com/labs/ai2canvas/">Adobe Illustrator to Canvas plug-in</a></li> + <li><a class="external" href="http://www.html5canvastutorials.com/" title="http://www.html5canvastutorials.com/">HTML5CanvasTutorials</a></li> + <li><a class="external" href="http://html5tutorial.com/how-to-draw-n-grade-bezier-curve-with-canvas-api" title="http://html5tutorial.com/how-to-draw-n-grade-bezier-curve-with-canvas-api">How to draw N grade Bézier curves with the Canvas API</a></li> + <li><a class="external" href="http://creativejs.com/2011/08/31-days-of-canvas-tutorials/" title="http://creativejs.com/2011/08/31-days-of-canvas-tutorials/">31 days of canvas tutorials</a></li> + <li><a href="http://www.w3.org/TR/2dcontext/" title="http://www.w3.org/TR/2dcontext/">W3C Standard</a></li> + <li><a href="http://www.tutorialspark.com/html5/HTML5_canvas_Intro.php" title="http://www.tutorialspark.com/html5/HTML5_canvas_Intro.php">HTML5 Canvas tutorials and reference</a></li> + <li><a href="http://davidwalsh.name/convert-canvas-image">JavaScript Canvas Image Conversion</a></li> +</ul> + +<h2 id="Nota_a_los_contribuyentes">Nota a los contribuyentes</h2> + +<p>Debido a un desafortunado error técnico que ocurrió el 17 de junio del 2013, perdimos la historia de este tutorial, incluyendo atribuciones a todos los contribuyentes del pasado a su contenido. Pedimos disculpas por esto, y esperamos que perdone este desafortunado percance.</p> + +<div>{{ Next("Web/Guide/HTML/Canvas_tutorial/Basic_usage") }}</div> diff --git a/files/es/web/api/canvas_api/tutorial/optimizing_canvas/index.html b/files/es/web/api/canvas_api/tutorial/optimizing_canvas/index.html new file mode 100644 index 0000000000..145e2734f0 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/optimizing_canvas/index.html @@ -0,0 +1,19 @@ +--- +title: Optimizing canvas +slug: Web/Guide/HTML/Canvas_tutorial/Optimizing_canvas +translation_of: Web/API/Canvas_API/Tutorial/Optimizing_canvas +--- +<p>{{HTMLElement("canvas")}} es uno de los estándares más utilizados para la representación de gráficos 2D en la Web. Se utiliza ampliamente en los juegos y visualizaciones complejas. Sin embargo, as Web sites and apps push canvas to the limits, el rendimiento comienza a sufrir. <span class="seoSummary">This article aims to provide suggestions for optimizing your use of the canvas element, to ensure that your Web site or app performs well.</span></p> +<p>A continuación una lista de tips par mejorar el rendimiento:</p> +<ul> + <li>Repintar primitives similares o objetos repetidos dentro y fuera de la pantalla canvas.</li> + <li>Batch canvas calls together (for example, draw a poly-line instead of multiple separate lines).</li> + <li>Avoid floating-point coordinates and use integers instead.</li> + <li>Avoid unnecessary canvas state changes.</li> + <li>Render screen differences only, not the whole new state.</li> + <li>Utilice varios lienzos en capas para escenas complejas.</li> + <li>Evite la propiedad <code>shadowBlur</code> siempre que sea posible.</li> + <li>Con las animaciones, use {{domxref("window.requestAnimationFrame()")}}.</li> + <li>Probar el rendimiento con <a href="http://jsperf.com" title="http://jsperf.com">JSPerf</a>.</li> +</ul> +<p>{{PreviousNext("Web/Guide/HTML/Canvas_tutorial/Basic_animations")}}</p> diff --git a/files/es/web/api/canvas_api/tutorial/pixel_manipulation_with_canvas/index.html b/files/es/web/api/canvas_api/tutorial/pixel_manipulation_with_canvas/index.html new file mode 100644 index 0000000000..14ccc9c4a5 --- /dev/null +++ b/files/es/web/api/canvas_api/tutorial/pixel_manipulation_with_canvas/index.html @@ -0,0 +1,301 @@ +--- +title: Pixel manipulation with canvas +slug: Web/Guide/HTML/Canvas_tutorial/Pixel_manipulation_with_canvas +translation_of: Web/API/Canvas_API/Tutorial/Pixel_manipulation_with_canvas +--- +<div>{{CanvasSidebar}} {{PreviousNext("Web/API/Canvas_API/Tutorial/Advanced_animations", "Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility")}}</div> + +<div class="summary"> +<p>Hasta ahora, no habíamos mirado los píxeles reales de nuestro <em>canvas</em>. Con el objeto <code>ImageData</code>, puedes leer y escribir directamente un <em>array</em> de datos para manipular píxeles.</p> + +<p>También veremos cómo se puede controlar el suavizado de la imagen (antialiasing) y cómo guardar imágenes de tu <em>canvas</em>.</p> +</div> + +<h2 id="El_objeto_ImageData">El objeto <code>ImageData</code></h2> + +<p>El objeto {{domxref("ImageData")}} representa los datos pixelados subyacentes de un área de un objeto lienzo. Contiene los siguientes atributos de sólo lectura:</p> + +<dl> + <dt><code>width</code></dt> + <dd>El ancho de la imagen en píxeles.</dd> + <dt><code>height</code></dt> + <dd>La altura de la imagen en píxeles.</dd> + <dt><code>data</code></dt> + <dd>Un objeto {{jsxref("Uint8ClampedArray")}} que representa un array unidimensional, contiene información en formato RGBA, con valores desde <code>0</code> hasta <code>255</code> (incluído).</dd> +</dl> + +<p>La propiedad <code>data</code> devuelve un {{jsxref("Uint8ClampedArray")}}, al que se puede acceder para ver los datos originales del pixel; cada pixel está representado por cuatro valores (rojo, verde, azul, y alfa, en ese orden; esto es, formato "RGBA"). Cada componente de color se representa con un valor entero entre 0 y 255. Dentro del array, cada componente ocupa un índice consecutivo, comenzando con 0 desde el punto superior izquierdo, continuando de izquierda a derecha y de arriba hacia abajo, a través del array.</p> + +<p>El {{jsxref("Uint8ClampedArray")}} contiene <code>alto</code> × <code>ancho</code> × 4 bytes de datos, con valores de índice en el rango entre 0 y (<code>alto</code>×<code>ancho</code>×4)-1.</p> + +<p>Por ejemplo, para leer el valor del componente azul del pixel en la columna 200, fila 50 de una imagen, deberías hacer lo siguiente:</p> + +<p>blueComponent = imageData.data[((50 * (imageData.width * 4)) + (200 * 4)) + 2];</p> + +<p>Si se le da un conjunto de coordenadas (X e Y), puede que termine haciendo algo así:</p> + +<pre class="brush: js">var xCoord = 50; +var yCoord = 100; +var canvasWidth = 1024; + +function getColorIndicesForCoord(x, y, width) { + var red = y * (width * 4) + x * 4; + return [red, red + 1, red + 2, red + 3]; +} + +var colorIndices = getColorIndicesForCoord(xCoord, yCoord, canvasWidth); + +var redIndex = colorIndices[0]; +var greenIndex = colorIndices[1]; +var blueIndex = colorIndices[2]; +var alphaIndex = colorIndices[3]; + +var redForCoord = imageData.data[redIndex]; +var greenForCoord = imageData.data[greenIndex]; +var blueForCoord = imageData.data[blueIndex]; +var alphaForCoord = imageData.data[alphaIndex]; +</pre> + +<p>O, en ES6 sería algo así:</p> + +<pre class="brush: js">const xCoord = 50; +const yCoord = 100; +const canvasWidth = 1024; + +const getColorIndicesForCoord = (x, y, width) => { + const red = y * (width * 4) + x * 4; + return [red, red + 1, red + 2, red + 3]; +}; + +const colorIndices = getColorIndicesForCoord(xCoord, yCoord, canvasWidth); + +const [redIndex, greenIndex, blueIndex, alphaIndex] = colorIndices; +</pre> + +<p>You may also access the size of the pixel array in bytes by reading the <code>Uint8ClampedArray.length</code> attribute:</p> + +<pre class="brush: js">var numBytes = imageData.data.length; +</pre> + +<h2 id="Creando_un_objeto_ImageData">Creando un objeto <code>ImageData</code></h2> + +<p>Para crear un objeto nuevo y vacío tipo <code>ImageData</code>, debes usar el método {{domxref("CanvasRenderingContext2D.createImageData", "createImageData()")}}. Hay dos versiones del método <code>createImageData()</code>:</p> + +<pre class="brush: js">var myImageData = ctx.createImageData(width, height);</pre> + +<p>Esto crea un nuevo objeto <code>ImageData</code> con las dimensiones especificadas. Todos los pixels tienen valor correspondiente a negro - transparente (0,0,0,0).</p> + +<p>También puedes crear un nuevo objeto <code>ImageData</code> con las mismas dimensiones que otro objeto, especificado por <code>anotherImageData</code>. Los píxels del nuevo objeto tienen valor negro - transparente. <strong>¡Esto no es una copia de los datos de la imagen!</strong></p> + +<pre class="brush: js">var myImageData = ctx.createImageData(anotherImageData);</pre> + +<h2 id="Getting_the_pixel_data_for_a_context">Getting the pixel data for a context</h2> + +<p>To obtain an <code>ImageData</code> object containing a copy of the pixel data for a canvas context, you can use the <code>getImageData()</code> method:</p> + +<pre class="brush: js">var myImageData = ctx.getImageData(left, top, width, height);</pre> + +<p>This method returns an <code>ImageData</code> object representing the pixel data for the area of the canvas whose corners are represented by the points (<code>left</code>,<code>top</code>), (<code>left+width</code>, <code>top</code>), (<code>left</code>, <code>top+height</code>), and (<code>left+width</code>, <code>top+height</code>). The coordinates are specified in canvas coordinate space units.</p> + +<div class="note"> +<p><strong>Note</strong>: Any pixels outside the canvas are returned as transparent black in the resulting <code>ImageData</code> object.</p> +</div> + +<p>This method is also demonstrated in the article <a href="/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas">Manipulating video using canvas</a>.</p> + +<h3 id="A_color_picker">A color picker</h3> + +<p>In this example we are using the <a href="/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData">getImageData() </a>method to display the color under the mouse cursor. For this, we need the current position of the mouse with <code>layerX</code> and <code>layerY</code>, then we look up the pixel data on that position in the pixel array that <a href="/en-US/docs/Web/API/CanvasRenderingContext2D/getImageData">getImageData()</a> provides us. Finally, we use the array data to set a background color and a text in the <code><div></code> to display the color.</p> + +<div class="hidden"> +<pre class="brush: html;"><canvas id="canvas" width="300" height="227" style="float:left"></canvas> +<div id="color" style="width:200px;height:50px;float:left"></div> +</pre> +</div> + +<pre class="brush: js;">var img = new Image(); +img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg'; +var canvas = document.getElementById('canvas'); +var ctx = canvas.getContext('2d'); +img.onload = function() { + ctx.drawImage(img, 0, 0); + img.style.display = 'none'; +}; +var color = document.getElementById('color'); +function pick(event) { + var x = event.layerX; + var y = event.layerY; + var pixel = ctx.getImageData(x, y, 1, 1); + var data = pixel.data; + var rgba = 'rgba(' + data[0] + ', ' + data[1] + + ', ' + data[2] + ', ' + (data[3] / 255) + ')'; + color.style.background = rgba; + color.textContent = rgba; +} +canvas.addEventListener('mousemove', pick); +</pre> + +<p>{{ EmbedLiveSample('A_color_picker', 610, 240) }}</p> + +<h2 id="Painting_pixel_data_into_a_context">Painting pixel data into a context</h2> + +<p>You can use the<a href="/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData"> putImageData() </a>method to paint pixel data into a context:</p> + +<pre class="brush: js">ctx.putImageData(myImageData, dx, dy); +</pre> + +<p>The <code>dx</code> and <code>dy</code> parameters indicate the device coordinates within the context at which to paint the top left corner of the pixel data you wish to draw.</p> + +<p>For example, to paint the entire image represented by <code>myImageData</code> to the top left corner of the context, you can simply do the following:</p> + +<pre class="brush: js">ctx.putImageData(myImageData, 0, 0); +</pre> + +<h3 id="Grayscaling_and_inverting_colors">Grayscaling and inverting colors</h3> + +<p>In this example we iterate over all pixels to change their values, then we put the modified pixel array back to the canvas using <a href="/en-US/docs/Web/API/CanvasRenderingContext2D/putImageData">putImageData()</a>. The invert function simply subtracts each color from the max value 255. The grayscale function simply uses the average of red, green and blue. You can also use a weighted average, given by the formula <code>x = 0.299r + 0.587g + 0.114b</code>, for example. See <a href="http://en.wikipedia.org/wiki/Grayscale">Grayscale</a> on Wikipedia for more information.</p> + +<div class="hidden"> +<pre class="brush: html;"><canvas id="canvas" width="300" height="227"></canvas> +<div> + <input id="grayscalebtn" value="Grayscale" type="button"> + <input id="invertbtn" value="Invert" type="button"> +</div> +</pre> +</div> + +<pre class="brush: js">var img = new Image(); +img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg'; +img.onload = function() { + draw(this); +}; + +function draw(img) { + var canvas = document.getElementById('canvas'); + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + img.style.display = 'none'; + var imageData = ctx.getImageData(0, 0, canvas.width, canvas.height); + var data = imageData.data; + + var invert = function() { + for (var i = 0; i < data.length; i += 4) { + data[i] = 255 - data[i]; // red + data[i + 1] = 255 - data[i + 1]; // green + data[i + 2] = 255 - data[i + 2]; // blue + } + ctx.putImageData(imageData, 0, 0); + }; + + var grayscale = function() { + for (var i = 0; i < data.length; i += 4) { + var avg = (data[i] + data[i + 1] + data[i + 2]) / 3; + data[i] = avg; // red + data[i + 1] = avg; // green + data[i + 2] = avg; // blue + } + ctx.putImageData(imageData, 0, 0); + }; + + var invertbtn = document.getElementById('invertbtn'); + invertbtn.addEventListener('click', invert); + var grayscalebtn = document.getElementById('grayscalebtn'); + grayscalebtn.addEventListener('click', grayscale); +} +</pre> + +<p>{{ EmbedLiveSample('Grayscaling_and_inverting_colors', 330, 270) }}</p> + +<h2 id="Zooming_and_anti-aliasing">Zooming and anti-aliasing</h2> + +<p>With the help of the {{domxref("CanvasRenderingContext2D.drawImage", "drawImage()")}} method, a second canvas and the {{domxref("CanvasRenderingContext2D.imageSmoothingEnabled", "imageSmoothingEnabled")}} property, we are able to zoom into our picture and see the details.</p> + +<p>We get the position of the mouse and crop an image of 5 pixels left and above to 5 pixels right and below. Then we copy that one over to another canvas and resize the image to the size we want it to. In the zoom canvas we resize a 10×10 pixel crop of the original canvas to 200×200.</p> + +<pre class="brush: js">zoomctx.drawImage(canvas, + Math.abs(x - 5), Math.abs(y - 5), + 10, 10, 0, 0, 200, 200);</pre> + +<p>Because anti-aliasing is enabled by default, we might want to disable the smoothing to see clear pixels. You can toggle the checkbox to see the effect of the <code>imageSmoothingEnabled</code> property (which needs prefixes for different browsers).</p> + +<h6 class="hidden" id="Zoom_example">Zoom example</h6> + +<div class="hidden"> +<pre class="brush: html;"><canvas id="canvas" width="300" height="227"></canvas> +<canvas id="zoom" width="300" height="227"></canvas> +<div> +<label for="smoothbtn"> + <input type="checkbox" name="smoothbtn" checked="checked" id="smoothbtn"> + Enable image smoothing +</label> +</div> +</pre> +</div> + +<pre class="brush: js">var img = new Image(); +img.src = 'https://mdn.mozillademos.org/files/5397/rhino.jpg'; +img.onload = function() { + draw(this); +}; + +function draw(img) { + var canvas = document.getElementById('canvas'); + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, 0, 0); + img.style.display = 'none'; + var zoomctx = document.getElementById('zoom').getContext('2d'); + + var smoothbtn = document.getElementById('smoothbtn'); + var toggleSmoothing = function(event) { + zoomctx.imageSmoothingEnabled = this.checked; + zoomctx.mozImageSmoothingEnabled = this.checked; + zoomctx.webkitImageSmoothingEnabled = this.checked; + zoomctx.msImageSmoothingEnabled = this.checked; + }; + smoothbtn.addEventListener('change', toggleSmoothing); + + var zoom = function(event) { + var x = event.layerX; + var y = event.layerY; + zoomctx.drawImage(canvas, + Math.abs(x - 5), + Math.abs(y - 5), + 10, 10, + 0, 0, + 200, 200); + }; + + canvas.addEventListener('mousemove', zoom); +}</pre> + +<p>{{ EmbedLiveSample('Zoom_example', 620, 490) }}</p> + +<h2 id="Guardando_las_imágenes">Guardando las imágenes</h2> + +<p>The {{domxref("HTMLCanvasElement")}} provides a <code>toDataURL()</code> method, which is useful when saving images. It returns a <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/data_URIs">data URI</a> containing a representation of the image in the format specified by the <code>type</code> parameter (defaults to <a class="external external-icon" href="https://en.wikipedia.org/wiki/Portable_Network_Graphics">PNG</a>). The returned image is in a resolution of 96 dpi.</p> + +<dl> + <dt>{{domxref("HTMLCanvasElement.toDataURL", "canvas.toDataURL('image/png')")}}</dt> + <dd>Default setting. Creates a PNG image.</dd> + <dt>{{domxref("HTMLCanvasElement.toDataURL", "canvas.toDataURL('image/jpeg', quality)")}}</dt> + <dd>Creates a JPG image. Optionally, you can provide a quality in the range from 0 to 1, with one being the best quality and with 0 almost not recognizable but small in file size.</dd> +</dl> + +<p>Once you have generated a data URI from you canvas, you are able to use it as the source of any {{HTMLElement("image")}} or put it into a hyper link with a <a href="/en-US/docs/Web/HTML/Element/a#attr-download">download attribute</a> to save it to disc, for example.</p> + +<p>You can also create a {{domxref("Blob")}} from the canvas.</p> + +<dl> + <dt>{{domxref("HTMLCanvasElement.toBlob", "canvas.toBlob(callback, type, encoderOptions)")}}</dt> + <dd>Creates a <code>Blob</code> object representing the image contained in the canvas.</dd> +</dl> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{domxref("ImageData")}}</li> + <li><a href="/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas">Manipulating video using canvas</a></li> + <li><a href="https://codepo8.github.io/canvas-images-and-pixels/">Canvas, images and pixels – by Christian Heilmann</a></li> +</ul> + +<p>{{PreviousNext("Web/API/Canvas_API/Tutorial/Advanced_animations", "Web/API/Canvas_API/Tutorial/Hit_regions_and_accessibility")}}</p> diff --git a/files/es/web/api/api_del_portapapeles/index.html b/files/es/web/api/clipboard_api/index.html index 53e43f6bd5..53e43f6bd5 100644 --- a/files/es/web/api/api_del_portapapeles/index.html +++ b/files/es/web/api/clipboard_api/index.html diff --git a/files/es/web/api/console/tabla/index.html b/files/es/web/api/console/table/index.html index 53f57f5636..53f57f5636 100644 --- a/files/es/web/api/console/tabla/index.html +++ b/files/es/web/api/console/table/index.html diff --git a/files/es/web/api/randomsource/obtenervaloresaleatorios/index.html b/files/es/web/api/crypto/getrandomvalues/index.html index b6e09439a9..b6e09439a9 100644 --- a/files/es/web/api/randomsource/obtenervaloresaleatorios/index.html +++ b/files/es/web/api/crypto/getrandomvalues/index.html diff --git a/files/es/web/api/document/cookie/index.html b/files/es/web/api/document/cookie/index.html new file mode 100644 index 0000000000..791ae788f2 --- /dev/null +++ b/files/es/web/api/document/cookie/index.html @@ -0,0 +1,119 @@ +--- +title: document.cookie +slug: DOM/document.cookie +tags: + - NeedsContent +translation_of: Web/API/Document/cookie +--- +<p>{{ApiRef("DOM")}}</p> + +<h3 id="Resumen" name="Resumen">Resumen</h3> + +<p>Con <code>document.cookie</code> se obtienen y definen las <code>cookies</code> asociadas con el documento.</p> + +<h2 id="Sintaxis_2">Sintaxis</h2> + +<h3 id="Sintaxis" name="Sintaxis">Leer todas las cookies accesibles desde una localización</h3> + +<pre class="eval"><em>todasLasCookies</em> = <em>document</em>.cookie; +</pre> + +<p>En el código anterior <em><code>todasLasCookies</code></em> es una cadena que contiene una lista de todas las cookies separadas por punto y coma (en pares <em><code>clave=valor</code></em>). Tenga en cuenta que <var>clave</var> y <var>valor</var> pueden estar rodeadas por espacios en blanco (caracteres espacio y tabulación): de hecho <a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a> especifica que debe haber un espacio en blanco después de cada punto y coma (;), pero algunos agentes de usuario no son muy estrictos con esto.</p> + +<h3 id="Escribir_una_nueva_cookie">Escribir una nueva cookie</h3> + +<pre class="eval"><em>document</em>.cookie = <em>nuevaCookie</em>;</pre> + +<p class="eval">En el código anterior, <em><code>nuevacookie</code></em> es una cadena de la forma <em><code>clave=valor</code></em>. Tenga en cuenta que solo se puede crear o actualizar una cookie de cada vez mediante este método. Considere también que:</p> + +<ul> + <li class="eval">Cualquiera de los siguientes atributos opcionales se puede escribir después del par clave-valor, especificando la cookie que se va a crear o actualizar, precedidos de un punto y coma. + <ul> + <li class="eval"><code>;path=<em>pat</em>h</code> (p. ej.: '/'. '/midir'). Si no se especifica, por defecto corresponde a la ruta del documento actual.<br> + La ruta debe ser <strong>absoluta</strong> (ver <a href="https://tools.ietf.org/html/rfc6265">RFC 6265</a>). Para más información sobre cómo utilizar rutas relativas, ir a <a href="https://developer.mozilla.org/es/docs/DOM/document.cookie$edit#Using_relative_URLs_in_the_path_parameter">este párrafo</a>.</li> + <li class="eval"><code>;domain=<em>domain</em></code> (p. ej. 'example.com', 'subdomain.example.com'). Si no se especifica, su valor por defecto es la porción de la dirección web de la ubicación actual del archivo. A diferencia de lo que ocurría en las primeras especificaciones, los puntos iniciales de los nombre de dominio se ignoran, pero los navegadores pueden impedir crear cookies que contengan dichos puntos. Si se especifica un dominio, los subdominios siempre son incluidos.</li> + <li class="eval"><code>;max-age=</code><em><code>duración-máxima-en-segundos</code></em> Por ejemplo: 60*60*24*365 para un año.</li> + <li class="eval"><code>;expires=</code><em><code>fecha-en-formato-GMTString</code> </em>Si no se especifica <code>max-age</code> ni <code>expires</code>, la cookie expirará al terminar la sesión actual.</li> + <li class="eval"><code>;secure</code> La cookie sólo será transmitida en un protocolo seguro (HTTPS, SSL). Antes de Chrmoe 52, este atributo podía aparecer con cookes de dominios http.</li> + <li class="eval"><code>;samesite</code> Este atributo impide al navegador enviar esta cookie a través de peticiones cross-site. Los valores posibles son lax o strict. El soporte de este atributo se añadió en Chrome 51. + <ul> + <li class="eval">El valor <em><code>strict</code></em> impide que la cookie sea enviada por el navegador al sitio destino en contexto de navegador cross-site, incluso cuando sigue un enlace regular.</li> + <li class="eval">El valor <em><code>lax</code></em> sólo envía cookies a las peticiones de GET de ALTO NIVEL. Es suficiente para seguir al usuario, pero evitará muchos ataques CSRF.</li> + </ul> + </li> + </ul> + </li> + <li class="eval">El valor de la cookie puede ser evaluado mediante <a href="/es/Referencia_de_JavaScript_1.5/Funciones_globales/encodeURIComponent" title="encodeURIComponent">encodeURIComponent()</a> para asegurarse de que dicha cadena no incluya comas, punto y coma, ni espacios en blanco (lo cual no está permitido en el valor de una cookie).</li> + <li class="eval">Algunas implementaciones de agente de usuario soporta los siguientes prefijos de cookie: + <ul> + <li class="eval"><code>__Secure-</code> Señales para el navegador que solo deben incluirse en las perticiones de cookie transmitidas por un canal seguro.</li> + <li class="eval"><code>__Host-</code> Señales del navegador que además de la restricción de uso de cookies que provienen de un origen serugo, el ámbito de la cookie está limitado a un atributo path que proporciona el servidor. Si el servidor omite el atributo path, el directorio de las petición URI está en uso. Tabién las señales del atributo dominio no deben estar presentes, lo cual previene que la cookie sea usada en otros dominis. Para Chrome, el atributo path debe tener el mismo origen.</li> + </ul> + </li> +</ul> + +<div class="geckoVersionNote">{{ gecko_callout_heading("6.0") }}</div> + +<div class="geckoVersionNote">Nótese que previamente a Gecko 6.0 {{ geckoRelease("6.0") }}, rutas que contenían comillas eran tratadas como si las comillas fueran parte de la cadena, en lugar de considerarse como un delimitador de la ruta actual. Esto ya ha sido arreglado.</div> + +<h2 id="Ejemplos">Ejemplos</h2> + +<h3 id="Ejemplo" name="Ejemplo">Ejemplo # 1: Uso sencillo</h3> + +<pre class="brush: js">document.cookie = "nombre=oeschger"; +document.cookie = "comida_preferida=tripa"; +function alertCookie() { + alert(document.cookie); // visualizar: nombre=oeschger;comida favorita=tripa + +}</pre> + +<pre><button onclick="alertCookie()">Mostrar cookies</button></pre> + +<p>{{EmbedLiveSample('Example_1_Simple_usage', 200, 36)}}</p> + +<h3 id="Ejemplo_2_Obtener_una_cookie_de_ejemplo_llamada_test2">Ejemplo #2: Obtener una cookie de ejemplo llamada <em>test2</em></h3> + +<pre>document.cookie = "test1=Hola"; +document.cookie = "test2=Mundo"; + +var cookieValor = document.cookie.replace(/(?:(?:^|.*;\s*)test2\s*\=\s*([^;]*).*$)|^.*$/, "$1"); + +function alertCookieValue() { + alert(cookieValor); +} +</pre> + +<pre><button onclick="alertCookieValue()">Mostrar valor de cookie</button></pre> + +<p>{{EmbedLiveSample('Example_2_Get_a_sample_cookie_named_test2', 200, 36)}}</p> + +<h3 id="Ejemplo_3_Hacer_algo_una_sola_vez">Ejemplo #3: Hacer algo una sola vez</h3> + +<p>De manera a usar el siguiente código, favor remplace todas las veces la palabra <code>hacerAlgoUnaSolaVez</code> (el nombre de la cookie) con un nombre personalizado.</p> + +<pre>function hazUnaVez() { + if (document.cookie.replace(/(?:(?:^|.*;\s*)<code>hacerAlgoUnaSolaVez</code>\s*\=\s*([^;]*).*$)|^.*$/, "$1") !== "true") { + alert("Hacer algo aquí!"); + document.cookie = "<code>hacerAlgoUnaSolaVez</code>=true; expires=Fri, 31 Dec 9999 23:59:59 GMT"; + } +}</pre> + +<pre><button onclick="dhacerUnaVez()">Solo hacer algo una vez</button></pre> + +<p>{{EmbedLiveSample('Example_3_Do_something_only_once', 200, 36)}}</p> + +<h3 id="Notas" name="Notas">Seguridad</h3> + +<p>Es importante mencionar que la restricción path no protege contra la lectura no autorizada de cookies de una ruta distinta. Puede ser fácilmente resuelto mediante DOM (por ejemplo creando un <a href="/en/HTML/Element/iframe" title="en/HTML/Element/iframe">iframe</a> oculto con la ruta de la cookie y accediendo a la propiedad contentDocument.cookie del iframe). La única manera de proteger el acceso a cookies es ocupando un dominio o subdominio diferente, debido a la <a href="/en/Same_origin_policy_for_JavaScript" title="Same origin policy for JavaScript">política de mismo origen</a>.</p> + +<h3 id="Notas" name="Notas">Notas</h3> + +<ul> + <li>Empezando con Firefox 2, está disponible un mejor mecanismo de almacenamiento en cliente - <a href="/es/DOM/Storage" title="es/DOM/Storage">WHATWG DOM Storage</a>.</li> + <li>Puedes eliminar una cookie simplemente estableciendo su fecha de expiración a cero.</li> + <li>Cabe mencionar que entre más cookies se tengan, mayor cantidad de datos serán transferidos entre el servidor y el cliente en cada solicitud. Esto reducirá el tiempo entre cada solicitud. Es altamente recomendado que se utilice <a href="/es/DOM/Storage" title="es/DOM/Storage">WHATWG DOM Storage</a> si se van a mantener los datos solamente en el cliente.</li> +</ul> + +<h3 id="Especificaci.C3.B3n" name="Especificaci.C3.B3n">Especificación</h3> + +<p><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-8747038">DOM Level 2: HTMLDocument.cookie</a></p> diff --git a/files/es/web/api/document/crearatributo/index.html b/files/es/web/api/document/createattribute/index.html index 22f769d577..22f769d577 100644 --- a/files/es/web/api/document/crearatributo/index.html +++ b/files/es/web/api/document/createattribute/index.html diff --git a/files/es/web/api/event/createevent/index.html b/files/es/web/api/document/createevent/index.html index 7b273c6e33..7b273c6e33 100644 --- a/files/es/web/api/event/createevent/index.html +++ b/files/es/web/api/document/createevent/index.html diff --git a/files/es/web/api/document/abrir/index.html b/files/es/web/api/document/open/index.html index 13b541561d..13b541561d 100644 --- a/files/es/web/api/document/abrir/index.html +++ b/files/es/web/api/document/open/index.html diff --git a/files/es/web/api/document/pointerlockchange_event/index.html b/files/es/web/api/document/pointerlockchange_event/index.html new file mode 100644 index 0000000000..2d5af4205b --- /dev/null +++ b/files/es/web/api/document/pointerlockchange_event/index.html @@ -0,0 +1,80 @@ +--- +title: pointerlockchange +slug: Web/Events/pointerlockchange +translation_of: Web/API/Document/pointerlockchange_event +--- +<p>El evento <code>pointerlockchange</code> es disparado cuando el cursor del navegador es bloqueado o desbloqueado.</p> + +<h2 id="Información_general">Información general</h2> + +<dl> + <dt style="float: left; text-align: right; width: 120px;">Specification</dt> + <dd style="margin: 0 0 0 120px;"><a class="external" href="http://www.w3.org/TR/pointerlock/#pointerlockchange-and-pointerlockerror-events">Pointer Lock</a></dd> + <dt style="float: left; text-align: right; width: 120px;">Interface</dt> + <dd style="margin: 0 0 0 120px;">Event</dd> + <dt style="float: left; text-align: right; width: 120px;">Bubbles</dt> + <dd style="margin: 0 0 0 120px;">Yes</dd> + <dt style="float: left; text-align: right; width: 120px;">Cancelable</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Target</dt> + <dd style="margin: 0 0 0 120px;">Document</dd> + <dt style="float: left; text-align: right; width: 120px;">Default Action</dt> + <dd style="margin: 0 0 0 120px;">None</dd> +</dl> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col">Type</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyInline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>The event target (the topmost target in the DOM tree).</td> + </tr> + <tr> + <td><code>type</code> {{readonlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The type of event.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Whether the event normally bubbles or not.</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Whether the event is cancellable or not.</td> + </tr> + </tbody> +</table> + +<h2 id="Ejemplo">Ejemplo</h2> + +<pre class="brush:js;">//Ten en cuenta que el nombre del evento, en este caso "pointerlockchange" puede variar según el navegador. +document.addEventListener("pointerlockchange", function( event ) { + // El objetivo, parámetro "target", del objeto "event" es siempre el objeto "document". + // para recuperar el objeto que recibe el bloqueo/desbloqueo es document.pointerlockElement. + document.pointerLockElement; + +}); +</pre> + +<h2 id="Eventos_relacionados">Eventos relacionados</h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Mozilla_event_reference/pointerlockerror"><code>pointerlockerror</code></a></li> +</ul> + +<h2 id="Véase_también">Véase también:</h2> + +<ul> + <li><a href="/en-US/docs/API/Pointer_Lock_API">Using Pointer Lock API</a></li> +</ul> diff --git a/files/es/web/api/document_object_model/events/index.html b/files/es/web/api/document_object_model/events/index.html new file mode 100644 index 0000000000..fce2530535 --- /dev/null +++ b/files/es/web/api/document_object_model/events/index.html @@ -0,0 +1,72 @@ +--- +title: Eventos y el DOM +slug: Referencia_DOM_de_Gecko/Eventos +tags: + - DOM + - Guía +translation_of: Web/API/Document_Object_Model/Events +--- +<h2 id="Introduction" name="Introduction">Introducción</h2> + +<p>Este capítulo describe el Modelo de Eventos del DOM. Se describe la interfaz <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-Event">Event</a>, así como las interfaces para el registro de eventos en los nodos del DOM, y los <a href="/en-US/docs/Web/API/EventTarget.addEventListener">oyentes de eventos</a>, y varios ejemplos más largos muestran cómo se relacionan entre sí las diversas interfaces de eventos.</p> + +<p>Hay un diagrama excelente que explica claramente las tres fases del flujo de eventos a través del DOM en el borrador <a href="http://www.w3.org/TR/DOM-Level-3-Events/#dom-event-architecture">DOM Level 3 Events</a>.</p> + +<p>Vea también el <a href="/en-US/docs/DOM/DOM_Reference/Examples#Example_5:_Event_Propagation">Ejemplo 5: Propagación de eventos</a> en el capítulo de Ejemplos para un ejemplo más detallado de cómo los eventos se mueven a través del DOM.</p> + +<h2 id="DOM_event_handler_List" name="DOM_event_handler_List">Registrando oyentes de eventos</h2> + +<p>Hay 3 formas de registrar gestores de eventos para un elemento DOM.</p> + +<h3 id="EventTarget.addEventListener" name="EventTarget.addEventListener"><a href="/en-US/docs/Web/API/EventTarget.addEventListener"><code>EventTarget.addEventListener</code></a></h3> + +<pre class="brush: js">// Se supone que myButton es un elemento de botón +myButton.addEventListener('click', function(){alert('Hello world');}, false); +</pre> + +<p>Este es el método que debe usar en las páginas web modernas. </p> + +<p>Nota: Internet Explorer 6-8 no admite este método, ofreciendo una API similar {{domxref("EventTarget.attachEvent")}} en su lugar. Para la compatibilidad entre navegadores utilice una de las muchas bibliotecas de JavaScript disponibles.</p> + +<p>Se pueden encontrar más detalles en la página de referencia {{domxref("EventTarget.addEventListener")}}.</p> + +<h3 id="HTML_attribute" name="HTML_attribute"><a href="/en-US/docs/Web/Guide/HTML/Event_attributes">Atributo HTML</a></h3> + +<pre class="brush: html"><button onclick="alert('Hello world!')"> +</pre> + +<p>El código de JavaScript en el atributo pasa el objeto Event por medio del parámetro <code>event</code>. <a href="http://dev.w3.org/html5/spec/webappapis.html#the-event-handler-processing-algorithm">El valor de retorno se trata de una manera especial, descrita en la especificación HTML</a>.</p> + +<p>Debe evitarse esta forma. Hace que el marcado sea más grande y menos legible. El comitido del contenido/estructura y del comportamiento no están bien separadas, por lo que es más difícil encontrar un error.</p> + +<h3 id="DOM_element_properties" name="DOM_element_properties">Propiedades del elemento DOM</h3> + +<pre class="brush: js">// Se supone que myButton es un elemento de botón +myButton.onclick = function(event){alert('Hello world');}; +</pre> + +<p>La función se puede defirnir para que tome un parámetro <code>event</code>. <a href="http://dev.w3.org/html5/spec/webappapis.html#the-event-handler-processing-algorithm">El valor de retorno se trata de una manera especial, descrita en la especificación HTML</a>.</p> + +<p>El problema con este método es que solo se puede establecer un gestor por elemento y por evento.</p> + +<h2 id="Accediendo_a_las_Interfaces_de_eventos">Accediendo a las Interfaces de eventos</h2> + +<p>Los controladores de eventos se pueden adjuntar a varios objetos, incluidos los elementos DOM, documentos, al <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects">objeto window</a>, etc. Cuando se produce un evento, se crea un objeto de evento y se pasa secuencialmente a los oyentes del evento.</p> + +<p>Se puede acceder a la interfaz {{domxref ("Evento")}} desde la función del gestor, a través del objeto de evento pasado como primer argumento. El siguiente ejemplo simple muestra cómo se pasa un objeto de evento a la función del controlador de eventos, y se puede usar desde dentro de una de esas funciones.</p> + +<pre class="brush: js">function foo(evt) { + // al parámetro evt se le asigna automáticamente el objeto event + alert(evt); +} +table_el.onclick = foo; +</pre> + +<h2 id="Subnav">Subnav</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/Document_Object_Model">DOM Reference</a></li> + <li><a href="/en-US/docs/Web/API/Document_Object_Model/Introduction">Introduction to the DOM</a></li> + <li><a href="/en-US/docs/Web/API/Document_Object_Model/Events">Events and the DOM</a></li> + <li><a href="/en-US/docs/Web/API/Document_Object_Model/Examples">Examples</a></li> +</ul> diff --git a/files/es/web/api/document_object_model/examples/index.html b/files/es/web/api/document_object_model/examples/index.html new file mode 100644 index 0000000000..33f0e9e2b7 --- /dev/null +++ b/files/es/web/api/document_object_model/examples/index.html @@ -0,0 +1,367 @@ +--- +title: Ejemplos +slug: Referencia_DOM_de_Gecko/Ejemplos +tags: + - DOM + - Referencia_DOM_de_Gecko + - Todas_las_Categorías + - páginas_a_traducir +translation_of: Web/API/Document_Object_Model/Examples +--- +<p>En este capítulo se brindan ejemplos relativamente extensos que ilustran el uso del DOM para el desarrollo web y XML. Siempre que sea posible, usaremos las APIs, trucos y patrones comunes en JavaScript para la manipulación del objeto <code>document</code>.</p> + +<h3 id="Ejemplo_1:_Altos_y_anchos" name="Ejemplo_1:_Altos_y_anchos">Ejemplo 1: Altos y anchos</h3> + +<p>El ejemplo siguiente muestra el uso de las propiedades de alto (<code>height</code>) y ancho (<code>width</code>) junto a imágenes de dimensiones variadas:</p> + +<pre><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" +"http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="es"> + +<head> +<title>Ejemplo de height/width</title> +<script type="text/javascript"> +function iniciar() +{ + var arrImages = new Array(3); + arrImages[0] = document.getElementById("imagen1"); + arrImages[1] = document.getElementById("imagen2"); + arrImages[2] = document.getElementById("imagen3"); + var objOutput = document.getElementById("salida"); + var strHtml = "<ul>"; + for (var i = 0; i < arrImages.length; i++) + strHtml += "<li>imagen" + (i+1) + + ": height=" + arrImages[i].height + + ", width=" + arrImages[i].width + + ", style.height=" + arrImages[i].style.height + + ", style.width=" + arrImages[i].style.width + + "<\/li>"; + strHtml += "<\/ul>"; + salida.innerHTML = strHtml; +} +</script> +</head> +<body onload="iniciar();"> + +<p>La 1ª imagen: +- alto (height): no +- ancho (width): no +- estilo (style): no + <img id="imagen1" src="http://www.mozilla.org/images/mozilla-banner.gif"> +</p> +<p>La 2ª imagen: +- height="50" +- width="500" +- style: no + <img id="imagen2" src="http://www.mozilla.org/images/mozilla-banner.gif" + height="50" width="500"> +</p> +<p>La 3ª imagen: +- height y width: no +- style="height: 50px; width: 500px;": sí + <img id="imagen3" src="http://www.mozilla.org/images/mozilla-banner.gif" + style="height: 50px; width: 500px;"> +</p> + +<div id="salida"> </div> +</body> +</html> +</pre> + +<p><code>height</code> y <code>width</code> son además propiedades de los elementos <code>OBJECT</code> y <code>APPLET</code>.</p> + +<h3 id="Ejemplo_2:_Atributos_de_una_imagen" name="Ejemplo_2:_Atributos_de_una_imagen">Ejemplo 2: Atributos de una imagen</h3> + +<pre><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" +"http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="es"> + +<head> +<title>Modificación del borde de una imagen</title> +<script type="text/javascript"> +function setBorderWidth(width) { + document.getElementById("img1").style.borderWidth = width + "px"; +} +</script> +</head> + +<body> +<p> + <img id="img1" src="image1.gif" style="border: 5px solid green;" width="100" +height="100" alt="test de borde"> +</p> + +<form name="Formulario"> + <p><input type="button" value="Definir un borde de 20px" +onclick="setBorderWidth(20);"> <input type="button" value="Definir un borde de 5px" +onclick="setBorderWidth(5);"></p> +</form> + +</body> +</html> +</pre> + +<h3 id="Ejemplo_3:_Manipulaci.C3.B3n_de_estilos" name="Ejemplo_3:_Manipulaci.C3.B3n_de_estilos">Ejemplo 3: Manipulación de estilos</h3> + +<p>En este ejemplo sencillo, algunas propiedades de estilo básicas de un elemento párrafo HTML son accedidas utilizando el objeto estilo en el elemento y aquellas propiedades de estilo CSS del objeto, pueden ser entregadas y establecidas desde el DOM. En este caso, está manipulando los estilos directamente. En el siguiente ejemplo (ver ejemplo 4), puede utilizar las hojas de estilo y sus reglas para cambiar estilos para el documento entero.</p> + +<pre><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" +"http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en"> + +<head> +<title>Changing color and font-size example</title> +<script type="text/javascript"> +function changeText() { + var p = document.getElementById("pid"); + p.style.color = "blue" + p.style.fontSize = "18pt" +} +</script> +</head> +<body> +<p id="pid" +onclick="window.location.href = 'http://www.cnn.com/';">linker</p> +<form> +<p><input value="rec" type="button" onclick="changeText();"></p> +</form> +</body> +</html> +</pre> + +<h3 id="Ejemplo_4:_Utilizaci.C3.B3n_de_las_hojas_de_estilo" name="Ejemplo_4:_Utilizaci.C3.B3n_de_las_hojas_de_estilo">Ejemplo 4: Utilización de las hojas de estilo</h3> + +<p>La propiedad de las hojas de estilo en un objeto de documento muestra una lista de las hojas de estilo que acompañan a ése documento. Usando los objetos de la hoja de estilo, del estilo y de las reglas de CSS se puede acceder individualmente a esas hojas de estilo y sus reglas, como se demuestra en este ejemplo, el cual muestra todos los selectores de reglas de estilo en la consola.</p> + +<pre>ss = document.styleSheets; +for(i=0; i<ss.length; i++) + { + for(j=0; j<ss[0].cssRules.length; j++) + { + dump( ss[i].cssRules[j].selectorText + "\n" ); + } + } +</pre> + +<p>Para un documento con una sola hoja de estilo en la cual son definidas las tres reglas siguientes:</p> + +<pre class="eval">BODY { background-color: darkblue; } +P { font-face: Arial; font-size: 10pt; margin-left: .125in; } +#lumpy { display: none; } +</pre> + +<p>El script sale así:</p> + +<pre class="eval">BODY +P +#LUMPY +</pre> + +<h3 id="Ejemplo_5:_Propagaci.C3.B3n_del_evento" name="Ejemplo_5:_Propagaci.C3.B3n_del_evento">Ejemplo 5: Propagación del evento</h3> + +<p>Este ejemplo muestra de una forma muy simple como los eventos se inician y son gestionados en el DOM. Cuando el cuerpo (<em>body</em> ) de ese documento HTML se carga,<em>un evento listener es registrado con la columna superior de la TABLA. El evento listener maneja el evento ejecutando la función stopEvent, que cambia el valor en el final de la celda de la tabla.</em></p> + +<p>Sin embargo, stopEvent también llama a un método del objeto evento, <a href="es/DOM/event.stopPropagation">event.stopPropagation</a>, que mantiene el evento del burbujeo a continuación dentro del DOM. Note que la tabla misma tiene un manejador de evento <a href="es/DOM/element.onclick">onclick</a> que muestra un mensaje cuando la tabla es seleccionada. Pero el método stopEvent ha detenido la propagación, y así despues los datos en la tabla son actualizados, la fase de evento es efectivamente finalizada, y un cuadro de alerta es mostrado para confirmar esto.</p> + +<pre><html> +<head> +<title>Propagación del evento</title> + +<style type="text/css"> + #t-daddy { border: 1px solid red } + #c1 { background-color: pink; } +</style> + +<script type="text/javascript"> + +function stopEvent(ev) { + c2 = document.getElementById("c2"); + c2.innerHTML = "hola"; + + // this ought to keep t-daddy from getting the click. + ev.stopPropagation(); + alert("La propagación del evento se ha parado."); +} + +function load() { + elem = document.getElementById("tbl1"); + elem.addEventListener("click", stopEvent, false); +} +</script> +</head> + +<body onload="load();"> + +<table id="t-daddy" onclick="alert('hi');"> + <tr id="tbl1"> + <td id="c1">uno</td> + </tr> + <tr> + <td id="c2">dos</td> + </tr> +</table> + +</body> +</html> +</pre> + +<h3 id="Ejemplo_6:_Conseguir_el_estilo_computado_.28getComputedStyle.29" name="Ejemplo_6:_Conseguir_el_estilo_computado_.28getComputedStyle.29">Ejemplo 6: Conseguir el estilo computado (getComputedStyle)</h3> + +<p>Este ejemplo demuestra como el método <a href="es/DOM/window.getComputedStyle">window.getComputedStyle</a> puedes utilizarse para obtener los estilos de un elemento que no son especificados en el atributo <code>style</code> o con JavaScript (por ejemplo, <strong><span class="highlightgreen"><code>element.style.backgroundColor="rgb(173, 216, 230)"</code></span></strong>). Estos últimos tipos de estilos se pueden recuperar con el atributo <a href="es/DOM/element.style">element.style</a>, las propiedades del cual están en la <a href="es/DOM/CSS">lista de propiedades de CSS</a> del DOM.</p> + +<p><code>getComputedStyle()</code> devuelve un objeto <code>ComputedCSSStyleDeclaration</code>, cuyas propiedades de estilo individuales pueden ser referenciadas con este método del objeto <code>getPropertyValue()</code>, el siguiente documento de ejemplo lo muestra.</p> + +<pre><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" +"http://www.w3.org/TR/html4/strict.dtd"> + +<html lang="en"> + +<head> + <title>Ejemplo de ''getComputedStyle''</title> + + <script type="text/javascript"> + function cStyles() + { + var RefDiv = document.getElementById("d1"); + + var txtHeight = document.getElementById("t1"); + var h_style = +document.defaultView.getComputedStyle(RefDiv, null).getPropertyValue("height"); + txtHeight.value = h_style; + + var txtWidth = document.getElementById("t2"); + var w_style = +document.defaultView.getComputedStyle(RefDiv, null).getPropertyValue("width"); + txtWidth.value = w_style; + + var txtBackgroundColor = document.getElementById("t3"); + var b_style = +document.defaultView.getComputedStyle(RefDiv, +null).getPropertyValue("background-color"); + txtBackgroundColor.value = b_style; + } + </script> + + <style type="text/css"> + #d1 { margin-left: 10px; background-color: rgb(173, 216, 230); +height: 20px; max-width: 20px; } + </style> + +</head> + +<body> + +<div id="d1">&nbsp;</div> + +<form action=""> +<p><button type="button" onclick="cStyles();">getComputedStyle</button> + height<input id="t1" type="text" value="1"> + max-width<input id="t2" type="text" value="2"> + bg-color<input id="t3" type="text" value="3"></p> +</form> + +</body> +</html> +</pre> + +<h3 id="Ejemplo_7:_Mostrar_las_propiedades_del_objeto_de_evento" name="Ejemplo_7:_Mostrar_las_propiedades_del_objeto_de_evento">Ejemplo 7: Mostrar las propiedades del objeto de evento</h3> + +<p>Este ejemplo utiliza métodos del DOM para mostrar todas las propiedades del <a href="es/DOM/event">evento</a> de <a href="es/DOM/window.onload">window.onload</a> y sus valores en una tabla. Muestra además una cómoda técnica del uso de un bucle<em><strong>for...in</strong></em> para iterar sobre las propiedades de un objeto y conseguir sus valores.</p> + +<p>Las propiedades de los objetos de evento difieren bastante entre los navegadores, la <a class="external" href="http://www.w3.org/TR/DOM-Level-2-Events/events.html">especificación W3C de los eventos del DOM 2</a> enumera las propiedades estándares, sin embargo algunos navegadores han extendido estas diferencias.</p> + +<p>El siguiente código colocado dentro de un nuevo archivo de texto y cargado en un surtido de navegadores, sorprenderá por las diferencias de los números y nombres de propiedades y/o al ponerle más elementos a la página y llamar esa función desde diferentes gestores de evento.</p> + +<pre><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" + "http://www.w3.org/TR/html4/strict.dtd"> + +<title>Muestra las propiedades del evento</title> + +<style type="text/css"> + table {border-collapse: collapse;} + thead {font-weight: bold;} + td {padding: 2px 10px 2px 10px;} + .odd {background-color: #efdfef;} + .even {background-color: #ffffff;} +</style> + +<script type="text/javascript"> + +function showEventProperties(e) +{ + function addCell(row, text) { + var cell = row.insertCell(-1); + cell.appendChild(document.createTextNode(text)); + } + + document.getElementById('eventType').innerHTML = e.type; + + var e = e || window.event; + var table = document.createElement('table'); + var thead = table.createTHead(); + var row = thead.insertRow(-1); + var lableList = ['#', 'Propriété', 'Valeur']; + var len = lableList.length; + + for (var i=0; i<len; i++) { + addCell(row, lableList[i]); + } + + var tbody = document.createElement('tbody'); + table.appendChild(tbody); + + for (var p in e) { + row = tbody.insertRow(-1); + row.className = (row.rowIndex % 2)? 'odd':'even'; + addCell(row, row.rowIndex); + addCell(row, p); + addCell(row, e[p]); + } + + document.body.appendChild(table); +} +window.onload = function(event){ + showEventProperties(event); +} +</script> + +<h1>Propiedades del objeto evento del DOM<span id="eventType"></span></h1> +</pre> + +<h3 id="Ejemplo_8:_Utilizaci.C3.B3n_del_interfaz_de_tabla_del_DOM" name="Ejemplo_8:_Utilizaci.C3.B3n_del_interfaz_de_tabla_del_DOM">Ejemplo 8: Utilización del interfaz de tabla del DOM</h3> + +<p>La interfaz HTMLTableElement del DOM provee algunos métodos de conveniencia para crear y manipular tablas. Dos métodos usados frecuentemente son <code><a href="es/DOM/table.insertRow">table.insertRow</a></code> y <code><a href="es/DOM/table/row.insertCell">row.insertCell</a></code>.</p> + +<p>Para agregar una columna y algunas celdas a una tabla existente:</p> + +<pre><table id="table0"> + <tr> + <td>Row 0 Cell 0</td> + <td>Row 0 Cell 1</td> + </tr> +</table> + +<script type="text/javascript"> + +var table = document.getElementById('table0'); +var row = table.insertRow(-1); +var cell, text; +for (var i=0; i<2; i++) { + cell = row.insertCell(-1); + text = 'Row ' + row.rowIndex + ' Cell ' + i; + cell.appendChild(document.createTextNode(text)); +} + +</script> +</pre> + +<h4 id="Notas" name="Notas">Notas</h4> + +<ul> + <li>Una propiedad <code><a href="es/DOM/element.innerHTML">innerHTML</a></code> de la tabla nunca debería ser utilizada para modificar una tabla, aunque puede utilizarla para escribir una tabla entera o el contenido de una celda.</li> + <li>Si los métodos Core del DOM<code><a href="es/DOM/document.createElement">document.createElement</a></code> y <code><a href="es/DOM/element.appendChild">element.appendChild</a></code> son utilizados para crear columnas y celdas, IE requiere que sean agregadas a un elemento tbody, mientras que otros navegadores permitirán agregar a un elemento de la tabla (las columnas serán agregadas al último elemento tbody).</li> + <li>Hay un número de otros métodos de conveniencia pertenecientes a la <a href="es/DOM/table#M.C3.A9todos">interfaz de tabla</a> que pueden ser utilizados para crear y modificar tablas.</li> +</ul> diff --git a/files/es/web/api/document_object_model/how_to_create_a_dom_tree/index.html b/files/es/web/api/document_object_model/how_to_create_a_dom_tree/index.html new file mode 100644 index 0000000000..25546a1704 --- /dev/null +++ b/files/es/web/api/document_object_model/how_to_create_a_dom_tree/index.html @@ -0,0 +1,130 @@ +--- +title: Cómo crear un DOM tree +slug: How_to_create_a_DOM_tree +translation_of: Web/API/Document_object_model/How_to_create_a_DOM_tree +--- +<p> </p> +<p>Esta página describe cómo usar el API <a class="external" href="http://www.w3.org/TR/DOM-Level-3-Core/core.html">DOM Core</a> en JavaScript para crear o modificar objetos DOM. Es aplicable a todas las aplicaciones basadas en Gecko (como Mozilla Firefox) cuyo código tenga privilegios (como las extensiones) y a las que no (páginas web).</p> +<h3 id="Dynamically_creating_a_DOM_tree" name="Dynamically_creating_a_DOM_tree">Creación dinámica de un DOM tree</h3> +<p>Considere el siguiente documento XML:</p> +<pre class="brush: xml"><?xml version="1.0"?> +<people> + <person first-name="eric" middle-initial="H" last-name="jung"> + <address street="321 south st" city="denver" state="co" country="usa"/> + <address street="123 main st" city="arlington" state="ma" country="usa"/> + </person> + + <person first-name="jed" last-name="brown"> + <address street="321 north st" city="atlanta" state="ga" country="usa"/> + <address street="123 west st" city="seattle" state="wa" country="usa"/> + <address street="321 south avenue" city="denver" state="co" country="usa"/> + </person> +</people> +</pre> +<p>El W3C DOM API soportado por Mozilla, puede ser usado para crear una representación en memoria del documento anterior, como se ve a continuación:</p> +<pre class="brush: js">var doc = document.implementation.createDocument("", "", null); +var peopleElem = doc.createElement("people"); + +var personElem1 = doc.createElement("person"); +personElem1.setAttribute("first-name", "eric"); +personElem1.setAttribute("middle-initial", "h"); +personElem1.setAttribute("last-name", "jung"); + +var addressElem1 = doc.createElement("address"); +addressElem1.setAttribute("street", "321 south st"); +addressElem1.setAttribute("city", "denver"); +addressElem1.setAttribute("state", "co"); +addressElem1.setAttribute("country", "usa"); +personElem1.appendChild(addressElem1); + +var addressElem2 = doc.createElement("address"); +addressElem2.setAttribute("street", "123 main st"); +addressElem2.setAttribute("city", "arlington"); +addressElem2.setAttribute("state", "ma"); +addressElem2.setAttribute("country", "usa"); +personElem1.appendChild(addressElem2); + +var personElem2 = doc.createElement("person"); +personElem2.setAttribute("first-name", "jed"); +personElem2.setAttribute("last-name", "brown"); + +var addressElem3 = doc.createElement("address"); +addressElem3.setAttribute("street", "321 north st"); +addressElem3.setAttribute("city", "atlanta"); +addressElem3.setAttribute("state", "ga"); +addressElem3.setAttribute("country", "usa"); +personElem2.appendChild(addressElem3); + +var addressElem4 = doc.createElement("address"); +addressElem4.setAttribute("street", "123 west st"); +addressElem4.setAttribute("city", "seattle"); +addressElem4.setAttribute("state", "wa"); +addressElem4.setAttribute("country", "usa"); +personElem2.appendChild(addressElem4); + +var addressElem5 = doc.createElement("address"); +addressElem5.setAttribute("street", "321 south avenue"); +addressElem5.setAttribute("city", "denver"); +addressElem5.setAttribute("state", "co"); +addressElem5.setAttribute("country", "usa"); +personElem2.appendChild(addressElem5); + +peopleElem.appendChild(personElem1); +peopleElem.appendChild(personElem2); +doc.appendChild(peopleElem); +</pre> +<p>Vea también el <a href="/en/XUL_Tutorial/Document_Object_Model" title="en/XUL_Tutorial/Document_Object_Model"> Capítulo DOM del Tutorial de XUL</a>.</p> +<p>Se puede automatizar la creación de un DOM tree usando el <a href="/en/JXON#JXON_reverse_algorithms" title="en/JXON#JXON_reverse_algorithms">JXON reverse algorithm (algoritmo inverso JXON)</a> en asociación con la siguiente representación JSON:</p> +<pre class="brush: js">{ + "people": { + "person": [{ + "address": [{ + "@street": "321 south st", + "@city": "denver", + "@state": "co", + "@country": "usa" + }, { + "@street": "123 main st", + "@city": "arlington", + "@state": "ma", + "@country": "usa" + }], + "@first-name": "eric", + "@middle-initial": "H", + "@last-name": "jung" + }, { + "address": [{ + "@street": "321 north st", + "@city": "atlanta", + "@state": "ga", + "@country": "usa" + }, { + "@street": "123 west st", + "@city": "seattle", + "@state": "wa", + "@country": "usa" + }, { + "@street": "321 south avenue", + "@city": "denver", + "@state": "co", + "@country": "usa" + }], + "@first-name": "jed", + "@last-name": "brown" + }] + } +} +</pre> +<h3 id="So_what.3F" name="So_what.3F">¿Ahora qué?</h3> +<p>Los DOM trees pueden ser <a href="/en/Using_XPath" title="en/Using_XPath">invocados usando expresiones XPath</a>, convertidos a cadenas de texto, salvados a un archivo local o remoto usando <a href="/en/Parsing_and_serializing_XML" title="en/Parsing_and_serializing_XML">XMLSerializer</a> (sin tener que convertirlo primero a una cadena de texto), Enviados mediante <a href="/en/DOM/XMLHttpRequest" title="en/XMLHttpRequest">POST a un servidor web</a> (via <code>XMLHttpRequest</code>), transformados usando <a href="/en/XSLT" title="en/XSLT">XSLT</a>, <a href="/en/XLink" title="en/XLink">XLink</a>, convertidos a un objeto JavaScript a tráves del <a href="/en/JXON" title="en/JXON">algoritmo </a><a href="/en/JXON" title="en/JXON">JXON</a>, etc.</p> +<p>Adicionalmente se puede hacer uso de los DOM trees para modelar los datos que no estén bien formados para RDF (o si sólo no prefieres usar RDF). Otra aplicación que puedes darle, se relaciona a XUL (que es XML), la UI (interfaz) de tu aplicación puede ser manipulada dinámicamente, descargada, subida, guardada, cargada, convertida, o transformada fácilmente.</p> +<h2 id="Vea_también">Vea también</h2> +<ul> + <li><a class="internal" href="/en/XML" title="en/XML">XML</a></li> + <li><a class="internal" href="/en/JXON" title="en/JXON">JXON</a></li> + <li><a class="internal" href="/en/XPath" title="en/XPath">XPath</a></li> + <li><a class="internal" href="/en/E4X" title="en/E4X">E4X (ECMAScript for XML)</a></li> + <li><a class="internal" href="/en/Parsing_and_serializing_XML" title="en/Parsing_and_serializing_XML">Parsing and serializing XML</a></li> + <li><a class="internal" href="/en/DOM/XMLHttpRequest" title="en/XMLHttpRequest">XMLHttpRequest</a></li> +</ul> +<p>{{ languages( { "fr": "fr/Comment_cr\u00e9er_un_arbre_DOM", "ja": "ja/How_to_create_a_DOM_tree", "zh-cn": "zh-cn/How_to_create_a_DOM_tree" } ) }}</p> diff --git a/files/es/web/api/document_object_model/index.html b/files/es/web/api/document_object_model/index.html new file mode 100644 index 0000000000..0f3a2a7f75 --- /dev/null +++ b/files/es/web/api/document_object_model/index.html @@ -0,0 +1,91 @@ +--- +title: Referencia DOM de Gecko +slug: Referencia_DOM_de_Gecko +tags: + - DOM + - NecesitaRevisiónTécnica + - Todas_las_Categorías +translation_of: Web/API/Document_Object_Model +--- +<p> +« <a href="es/Referencia_DOM_de_Gecko">Referencia DOM de Gecko</a> +</p><p><br> +Aquí está la tabla de contenido para la referencia <a href="es/DOM">DOM</a> de <a href="es/Gecko">Gecko</a>. +</p> +<h4 id="Prefacio"> <a href="es/Referencia_DOM_de_Gecko/Prefacio">Prefacio</a> </h4> +<ul><li> <a href="es/Referencia_DOM_de_Gecko/Prefacio#Sobre_.C3.A9sta_referencia">Sobre ésta referencia</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Prefacio#A_qui.C3.A9n_est.C3.A1_dirigida_esta_gu.C3.ADa.3F">A quién está dirigida esta guía?</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Prefacio#Qu.C3.A9_es_Gecko.3F">Qué es Gecko?</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Prefacio#Sintaxis_del_API">Sintaxis del API</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Prefacio#Utilizaci.C3.B3n_de_ejemplos">Utilización de ejemplos</a> +</li></ul> +<h4 id="Introducci.C3.B3n"> <a href="es/Referencia_DOM_de_Gecko/Introducci%c3%b3n">Introducción</a> </h4> +<ul><li> <a href="es/Referencia_DOM_de_Gecko/Introducci%c3%b3n#Qu.C3.A9_es_el_DOM.3F">Qué es el DOM?</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Introducci%c3%b3n#DOM_y_JavaScript">DOM y JavaScript</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Introducci%c3%b3n#C.C3.B3mo_se_accede_al_DOM.3F">Cómo se accede al DOM?</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Introducci%c3%b3n#Importancia_de_los_tipos_de_datos">Tipos de datos importantes</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Introducci%c3%b3n#Interfaces_del_DOM">Interfaces del DOM</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Introducci%c3%b3n#Probando_el_API_del_DOM">Probando el API del DOM</a> +</li></ul> +<h4 id="La_referencia_al_elemento_.28element.29_de_DOM"> <a href="es/DOM/element">La referencia al elemento (<code>element</code>) de DOM</a> </h4> +<ul><li> <a href="es/DOM/element#Introducci.C3.B3n">Introducción</a> +</li><li> <a href="es/DOM/element#Propiedades">Propiedades</a> +</li><li> <a href="es/DOM/element#M.C3.A9todos">Métodos</a> +</li><li> <a href="es/DOM/element#Manejo_de_los_eventos">Manejo de los eventos</a> +</li></ul> +<h4 id="La_referencia_a_la_ventana_.28window.29_de_DOM"> <a href="es/DOM/window">La referencia a la ventana (<code>window</code>) de DOM</a> </h4> +<ul><li> <a href="es/DOM/window#Introducci.C3.B3n">Introducción</a> +</li><li> <a href="es/DOM/window#Propiedades">Propiedades</a> +</li><li> <a href="es/DOM/window#M.C3.A9todos">Métodos</a> +</li><li> <a href="es/DOM/window#Manejo_de_los_eventos">Manejo de los eventos</a> +</li></ul> +<h4 id="La_referencia_al_document_de_DOM"> <a href="es/DOM/document">La referencia al <code>document</code> de DOM</a> </h4> +<ul><li> <a href="es/DOM/document#Introducci.C3.B3n">Introducción</a> +</li><li> <a href="es/DOM/document#Propiedades">Propiedades</a> +</li><li> <a href="es/DOM/document#M.C3.A9todos">Métodos</a> +</li></ul> +<h4 id="La_referencia_al_event_de_DOM"> <a href="es/DOM/event">La referencia al <code>event</code> de DOM</a> </h4> +<ul><li> <a href="es/DOM/event#Introducci.C3.B3n">Introducción</a> +</li><li> <a href="es/DOM/event#Propiedades">Propiedades</a> +</li><li> <a href="es/DOM/event#M.C3.A9todos">Métodos</a> +</li></ul> +<h4 id="La_referencia_al_estilo_.28style.29_de_DOM"> <a href="es/DOM/style">La referencia al estilo (<code>style</code>) de DOM</a> </h4> +<ul><li> <a href="es/DOM/style#Notas">Notas</a> +</li><li> <a href="es/DOM/style#Material_que_se_mover.C3.A1_a_otras_p.C3.A1ginas"> Material que se moverá a otras páginas</a> +</li></ul> +<h4 id="La_referencia_al_rango_.28range.29_de_DOM"> <a href="es/DOM/range">La referencia al rango (<code>range</code>) de DOM</a> </h4> +<ul><li> <a href="es/DOM/range#Introducci.C3.B3n">Introducción</a> +</li><li> <a href="es/DOM/range#Propiedades">Propiedades</a> +</li><li> <a href="es/DOM/range#M.C3.A9todos">Métodos</a> +</li></ul> +<h4 id="La_referencia_a_la_selecci.C3.B3n_.28selection.29_de_DOM"> <a href="es/DOM/selection">La referencia a la selección (<code>selection</code>) de DOM</a> </h4> +<ul><li> <a href="es/DOM/Selection#Introducci.C3.B3n">Introducción</a> +</li><li> <a href="es/DOM/Selection#Propiedades">Propiedades</a> +</li><li> <a href="es/DOM/Selection#M.C3.A9todos">Métodos</a> +</li></ul> +<h4 id="Interfaz_del_elemento_formulario_.28form.29_en_HTML"> <a href="es/DOM/form">Interfaz del elemento formulario (<code>form</code>) en HTML</a> </h4> +<ul><li> <a href="es/DOM/form#Interfaz_del_elemento_formulario_en_HTML">Interfaz del elemento formulario en HTML</a> +</li><li> <a href="es/DOM/form#Propiedades">Propiedades</a> +</li><li> <a href="es/DOM/form#M.C3.A9todos">Métodos</a> +</li></ul> +<h4 id="Interfaz_del_elemento_tabla_.28table.29_en_HTML"> <a href="es/DOM/table">Interfaz del elemento tabla (<code>table</code>) en HTML</a> </h4> +<ul><li> <a href="es/DOM/table#Interfaz_del_elemento_tabla_en_HTML">Interfaz del elemento tabla en HTML</a> +</li><li> <a href="es/DOM/table#Propiedades">Propiedades</a> +</li><li> <a href="es/DOM/table#M.C3.A9todos">Métodos</a> +</li></ul> +<h4 id="Ejemplos_DOM"> <a href="es/Referencia_DOM_de_Gecko/Ejemplos">Ejemplos DOM</a> </h4> +<ul><li> <a href="es/Referencia_DOM_de_Gecko/Ejemplos#Ejemplo_1:_Altos_y_anchos">Ejemplo 1: Altos y anchos</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Ejemplos#Ejemplo_2:_Atributos_de_una_imagen">Ejemplo 2: Atributos de una imagen</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Ejemplos#Ejemplo_3:_Manipulaci.C3.B3n_de_estilos">Ejemplo 3: Manipulación de estilos</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Ejemplos#Ejemplo_4:_Utilizaci.C3.B3n_de_la_hoja_de_estilo">Ejemplo 4: Utilización de la hoja de estilo</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Ejemplos#Ejemplo_5:_Propagaci.C3.B3n_del_evento">Ejemplo 5: Propagación del evento</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Ejemplos#Ejemplo_6:_Conseguir_el_estilo_computado">Ejemplo 6: Conseguir el estilo computado (<code>getComputedStyle</code>)</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Ejemplos#Ejemplo_7:_Mostrar_las_propiedades_del_objeto_de_evento">Ejemplo 7: Mostrar las propiedades del objeto de evento</a> +</li><li> <a href="es/Referencia_DOM_de_Gecko/Ejemplos#Ejemplo_8:_Utilizaci.C3.B3n_del_interfaz_de_tabla_del_DOM">Ejemplo 8: Utilización del interfaz de tabla del DOM</a> +</li></ul> +<div class="originaldocinfo"> +<h3 id="Informaci.C3.B3n_sobre_el_documento_original"> Información sobre el documento original </h3> +<ul><li> Última actualización: 22 de Octubre de 2006 +</li></ul> +</div> +{{ languages( { "en": "en/Gecko_DOM_Reference", "fr": "fr/R\u00e9f\u00e9rence_du_DOM_Gecko", "it": "it/Reference_del_DOM_di_Gecko", "ja": "ja/Gecko_DOM_Reference", "ko": "ko/Gecko_DOM_Reference", "pl": "pl/Dokumentacja_Gecko_DOM", "zh-cn": "cn/Gecko_DOM_\u53c2\u8003" } ) }} diff --git a/files/es/web/api/document_object_model/introduction/index.html b/files/es/web/api/document_object_model/introduction/index.html new file mode 100644 index 0000000000..5c604a7a6c --- /dev/null +++ b/files/es/web/api/document_object_model/introduction/index.html @@ -0,0 +1,248 @@ +--- +title: Introducción +slug: Referencia_DOM_de_Gecko/Introducción +tags: + - DOM + - Gecko + - Manuales + - Todas_las_Categorías +translation_of: Web/API/Document_Object_Model/Introduction +--- +<p> </p> + +<p>Ésta sección da una breve introducción conceptual del <a href="es/DOM">DOM</a>: qué es, cómo proporciona la estructura para los documentos <a href="es/HTML">HTML</a> y <a href="es/XML">XML</a>, cómo se accede a él, y cómo esta <a href="https://es.wikipedia.org/wiki/Interfaz_de_programaci%C3%B3n_de_aplicaciones">"API"</a> presenta la información de referencia y ejemplos.</p> + +<h2 id=".C2.BFQu.C3.A9_es_el_DOM.3F" name=".C2.BFQu.C3.A9_es_el_DOM.3F">¿Qué es el DOM?</h2> + +<p>El modelo de objeto de documento (DOM) es una interfaz de programación para los documentos HTML y XML. Facilita una representación estructurada del documento y define de qué manera los programas pueden acceder, al fin de modificar, tanto su estructura, estilo y contenido. El DOM da una representación del documento como un grupo de nodos y objetos estructurados que tienen propiedades y métodos. Esencialmente, conecta las páginas web a scripts o lenguajes de programación.</p> + +<p>Una página web es un documento. Éste documento puede exhibirse en la ventana de un navegador o también como código fuente HTML. Pero, en los dos casos, es el mismo documento. El modelo de objeto de documento (DOM) proporciona otras formas de presentar, guardar y manipular este mismo documento. El DOM es una representación completamente orientada al objeto de la página web y puede ser modificado con un lenguaje de script como JavaScript.</p> + +<p>El <a class="external" href="http://www.w3.org/DOM/">W3C DOM</a> estándar forma la base del funcionamiento del DOM en muchos navegadores modernos. Varios navegadores ofrecen extensiones más allá del estándar W3C, hay que ir con extremo cuidado al utilizarlas en la web, ya que los documentos pueden ser consultados por navegadores que tienen DOMs diferentes.</p> + +<p>Por ejemplo, el DOM de W3C especifica que el método <code>getElementsByTagName</code> en el código de abajo debe devolver una lista de todos los elementos <code><p></code> del documento:</p> + +<pre class="brush: js">paragraphs<font><font> = document.getElementsByTagName ("p");</font></font> +// paragraphs[0] es el primer elemento <p> +// paragraphs[1] es el segundo elemento <p>, etc.<font><font> +alert (</font></font>paragraphs<font><font> [0].nodeName);</font></font> +</pre> + +<p>Todas las propiedades, métodos y eventos disponibles para la manipulación y la creación de páginas web está organizado dentro de objetos. Un ejemplo: el objeto <code>document</code> representa al documento mismo, el objeto <code>table</code> hace funcionar la interfaz especial <code>HTMLTableElement</code> del DOM para acceder a tablas HTML, y así sucesivamente. Ésta documentación procura una relación objeto-por-objeto del DOM que funciona con los navegadores basados en Gecko.</p> + +<h2 id="DOM_y_JavaScript" name="DOM_y_JavaScript"><font><font><font><font>DOM y JavaScript</font></font></font></font></h2> + +<p>El ejemplo corto de abajo, como casi todos los ejemplos de esta referencia, es <a href="es/JavaScript">JavaScript</a>. Es decir, es <em>escrito</em> en JavaScript pero <em>utiliza</em> el DOM para acceder al documento y a sus elementos. El DOM no es un lenguaje de programación pero sin él, el lenguaje JavaScript no tiene ningún modelo o noción de las páginas web, de la páginas XML ni de los elementos con los cuales es usualmente relacionado. Cada elemento -"el documento íntegro, el título, las tablas dentro del documento, los títulos de las tablas, el texto dentro de las celdas de las tablas"- es parte del modelo de objeto del documento para cada documento, así se puede acceder y manipularlos utilizando el DOM y un lenguaje de escritura, como JavaScript.</p> + +<p>En el comienzo, JavaScript y el DOM estaban herméticamente enlazados, pero después se desarrollaron como entidades separadas. El contenido de la página es almacenado en DOM y el acceso y la manipulación se hace vía JavaScript, podría representarse aproximadamente así:</p> + +<p>API(web o página XML) = DOM + JS(lenguaje de script)</p> + +<p>El DOM fue diseñado para ser independiente de cualquier lenguaje de programación particular, hace que la presentación estructural del documento sea disponible desde un simple y consistente API. Aunque en este manual nos centramos exclusivamente en JavaScript, la directrices del DOM pueden construirse para cualquier lenguaje, así lo demuestra el siguiente ejemplo de Python:</p> + +<pre class="brush: python line-numbers language-python"><code class="language-python"># Ejemplo DOM de Python +import xml.dom.minidom as m +doc = m.parse("C:\\Projects\\Py\\chap1.xml"); +doc.nodeName # Propiedad DOM del objeto document; +p_list = doc.getElementsByTagName("para");</code></pre> + +<h2 id=".C2.BFC.C3.B3mo_se_accede_al_DOM.3F" name=".C2.BFC.C3.B3mo_se_accede_al_DOM.3F">¿Cómo se accede al DOM?</h2> + +<p>No se tiene que hacer nada especial para empezar a utilizar el DOM. Los diferentes navegadores tienen directrices DOM distintas, y éstas directrices tienen diversos grados de conformidad al actual estándar DOM (un tema que se intenta evitar en este manual), pero todos los navegadores web usan el modelo de objeto de documento para hacer accesibles las páginas web al script.</p> + +<p>Cuando se crea un script –esté en un elemento <code><SCRIPT></code> o incluido en una página web por la instrucción de cargar un script– inmediatamente está disponible para usarlo con el API, accediendo así a los elementos <code><a href="es/DOM/document">document</a></code> o <code><a href="es/DOM/window">window</a></code>, para manipular el documento mismo o sus diferentes partes, las cuales son los varios elementos de una página web. La programación DOM hace algo tan simple como lo siguiente, lo cual abre un mensaje de alerta usando la función <code><a href="es/DOM/window.alert">alert()</a></code> desde el objeto <code><a href="es/DOM/window">window</a></code>, o permite métodos DOM más sofisticados para crear realmente un nuevo contenido, como en el largo ejemplo de más abajo.</p> + +<pre class="brush: html"><body onload="window.alert('Bienvenido a mi página!');"> +</pre> + +<p>Aparte del elemento <code><script></code> en el cual JavaScript es definido, el ejemplo siguiente muestra la función a ejecutar cuando el documento se está cargando (y que el DOM completo es disponible para su uso). Esta función crea un nuevo elemento <code>H1</code>, le pone texto y después lo agrega al árbol del documento:</p> + +<pre class="brush: html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>html</span><span class="punctuation token">></span></span></code><code class="language-html"> + </code><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>head</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>script</span><span class="punctuation token">></span></span><span class="language-javascript script token"> + <span class="comment token">// ejecuta esta función cuando se cargue el documento</span> + window<span class="punctuation token">.</span>onload <span class="operator token">=</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + + <span class="comment token">// </span></span></code>crea dinámicamente un par de elementos HTML en una página vacia<code class="language-html"><span class="language-javascript script token"> + <span class="keyword token">var</span> heading <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">createElement</span><span class="punctuation token">(</span><span class="string token">"h1"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">var</span> heading_text <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">createTextNode</span><span class="punctuation token">(</span><span class="string token">"</span></span></code>el texto que desee<code class="language-html"><span class="language-javascript script token"><span class="string token">"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + heading<span class="punctuation token">.</span><span class="function token">appendChild</span><span class="punctuation token">(</span>heading_text<span class="punctuation token">)</span><span class="punctuation token">;</span> + document<span class="punctuation token">.</span>body<span class="punctuation token">.</span><span class="function token">appendChild</span><span class="punctuation token">(</span>heading<span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> + </span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>script</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>head</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>body</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>body</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>html</span><span class="punctuation token">></span></span></code></pre> + +<h2 id="Tipos_de_datos_importantes" name="Tipos_de_datos_importantes">Tipos de datos importantes</h2> + +<p>Esta parte intenta describir, de la manera más simple posible, los diferentes objetos y tipos. Pero hay que conocer una cantidad de tipos de datos diferentes que son utilizados por el API. Para simplificarlo, los ejemplos de sintaxis en esta API se refieren a nodos como <code>elements</code>, a una lista de nodos como <code>nodeLists</code> (o simples <code>elementos</code>) y a nodos de <code>atributo</code> como <code>attributes</code>.</p> + +<p>La siguiente tabla describe brevemente estos tipos de datos.</p> + +<table> + <tbody> + <tr> + <td><code>document</code></td> + <td>Cuando un miembro devuelve un objeto del tipo <code>document</code> (por ejemplo, la propiedad <strong>ownerDocument</strong> de un elemento devuelve el documento "<code>document</code>" al cual pertenece), este objeto es la raíz del objeto documento en sí mismo. El capítulo <a href="es/DOM/documento">La referencia al documento (<code>document</code>) de DOM</a> lo explica con más detalles.</td> + </tr> + <tr> + <td><code>element</code></td> + <td><code>element</code> se refiere a un elemento o a un nodo de tipo de elemento "<code>element</code>" devuelto por un miembro del API de DOM. Dicho de otra manera, por ejemplo, el método <code>document.createElement()</code> devuelve un objeto referido a un <code>nodo</code>, lo que significa que este método devuelve el elemento que acaba de ser creado en el DOM. Los objetos <code>element</code> ponen en funcionamiento a la interfaz <code>Element</code> del DOM y también a la interfaz de nodo "<code>Node</code>" más básica, las cuales son incluidas en esta referencia.</td> + </tr> + <tr> + <td><code>nodeList</code></td> + <td>Una "<code>nodeList</code>" es una serie de elementos, parecido a lo que devuelve el método <code>document.getElementsByTagName()</code>. Se accede a los items de la <code>nodeList</code> de cualquiera de las siguientes dos formas: + <ul> + <li><font><font><font><font>list.item (1)</font></font></font></font></li> + <li><font><font>lista {{mediawiki.external (1)}}</font></font></li> + </ul> + + <p>Ambas maneras son equivalentes. En la primera, <strong>item()</strong> es el método del objeto <code>nodeList</code>. En la última se utiliza la típica sintaxis de acceso a listas para llegar al segundo ítem de la lista.</p> + </td> + </tr> + <tr> + <td><code>attribute</code></td> + <td>Cuando un atributo ("<code>attribute</code>") es devuelto por un miembro (por ej., por el método <strong>createAttribute()</strong>), es una referencia a un objeto que expone una interfaz particular (aunque limitada) a los atributos. Los atributos son nodos en el DOM igual que los elementos, pero no suelen usarse así.</td> + </tr> + <tr> + <td><code>NamedNodeMap</code></td> + <td>Un <code>namedNodeMap</code> es una serie, pero los ítems son accesibles tanto por el nombre o por un índice, este último caso es meramente una conveniencia para enumerar ya que no están en ningún orden en particular en la lista. Un <code>NamedNodeMap</code> es un método de ítem() por esa razón, y permite poner o quitar ítems en un <code>NamedNodeMap</code></td> + </tr> + </tbody> +</table> + +<h2 id="Interfaces_del_DOM" name="Interfaces_del_DOM">Interfaces del DOM</h2> + +<p>Uno de los propósitos de esta guía es minimizar el hablar de interfaces abstractas, heredadas y otros detalles de funcionamiento. Más bien, concentrarse sobre los objetos en el DOM y sobre las actuales <em>cosas</em> que se pueden usar para manipular la jerarquía de DOM. Desde el punto de vista del programador web, es bastante indiferente saber que la representación del objeto del elemento <code>HTML form</code> toma la propidedad <strong>name</strong> desde la interfaz <code>HTMLFormElement</code> pero que las propiedades <code><strong>className</strong> </code>se toman desde la propia interfaz <code>HTMLElement</code>. En ambos casos, la propiedad está sólo en el objeto <code>form</code>.</p> + +<p>Pero puede resultar confuso el funcionamiento de la fuerte relación entre objetos e interfaces en el DOM, por eso esta sección intentará hablar un poquito sobre las interfaces actuales en la especificación del DOM y de como se dispone de ellas.</p> + +<h2 id="Interfaces_y_objetos" name="Interfaces_y_objetos">Interfaces y objetos</h2> + +<p>En algunos casos un objeto pone en ejecución a una sola interfaz. Pero a menudo un objeto toma prestada una tabla HTML (<code>table</code>) desde muchas interfaces diversas. El objeto table, por ejemplo, pone en funcionamiento una <a href="es/DOM/tabla">Interfaz especial del elemento table HTML</a>, la cual incluye métodos como <code>createCaption</code> y <code>insertRow</code>. Pero como también es un elemento HTML, table pone en marcha a la interfaz del <code>Element</code> descrita en el capítulo <a href="es/Referencia_DOM_de_Gecko/elemento">La referencia al elemento del DOM</a>. Y finalmente, puesto que un elemento HTML es también, por lo que concierna al DOM, un nodo en el árbol de nodos que hace el modelo de objeto para una página web o XML, el elemento de table hace funcionar la interfaz más básica de <code>Node</code>, desde el cual deriva <code>Element</code>.</p> + +<p>La referencia a un objeto <code>table</code>, como en el ejemplo siguiente, utiliza estas interfaces intercambiables sobre el objeto.</p> + +<pre class="brush: js line-numbers language-js"><code class="language-js"><span class="keyword token">var</span> table <span class="operator token">=</span> document<span class="punctuation token">.</span><span class="function token">getElementById</span><span class="punctuation token">(</span><span class="string token">"table"</span><span class="punctuation token">)</span><span class="punctuation token">;</span> +<span class="keyword token">var</span> tableAttrs <span class="operator token">=</span> table<span class="punctuation token">.</span>attributes<span class="punctuation token">;</span> <span class="comment token">// Node/interfaz Element</span> +<span class="keyword token">for</span> <span class="punctuation token">(</span><span class="keyword token">var</span> i <span class="operator token">=</span> <span class="number token">0</span><span class="punctuation token">;</span> i <span class="operator token"><</span> tableAttrs<span class="punctuation token">.</span>length<span class="punctuation token">;</span> i<span class="operator token">++</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> + <span class="comment token">// interfaz HTMLTableElement: atributo border</span> + <span class="keyword token">if</span><span class="punctuation token">(</span>tableAttrs<span class="punctuation token">[</span>i<span class="punctuation token">]</span><span class="punctuation token">.</span>nodeName<span class="punctuation token">.</span><span class="function token">toLowerCase</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="operator token">==</span> <span class="string token">"border"</span><span class="punctuation token">)</span> + table<span class="punctuation token">.</span>border <span class="operator token">=</span> <span class="string token">"1"</span><span class="punctuation token">;</span> +<span class="punctuation token">}</span> +<span class="comment token">// interfaz HTMLTableElement: atributo summary</span> +table<span class="punctuation token">.</span>summary <span class="operator token">=</span> <span class="string token">"nota: borde aumentado"</span><span class="punctuation token">;</span></code></pre> + +<h2 id="Interfaces_esenciales_en_el_DOM" name="Interfaces_esenciales_en_el_DOM">Interfaces esenciales en el DOM</h2> + +<p>Esta sección lista las interfaces más comúnmente utilizadas en el DOM. La idea no es describir qué hacen estas APIs pero sí dar una idea de las clases de métodos y propiedades que se encuentran con el uso del DOM. Muchos ejemplos de uso común de esta API se encuentran en el capítulo <a href="es/Referencia_DOM_de_Gecko/Ejemplos">Ejemplos DOM</a> al final de este manual.</p> + +<p><code>document</code> y <code>window</code> son objetos cuya interfaces son generalmente muy usadas en la programación de DOM. En término simple, el objeto <code>window</code> representa algo como podría ser el navegador, y el objeto <code>document</code> es la raíz del documento en sí. <code>Element</code> hereda de la interfaz genérica <code>Node</code>, y juntos, estas dos interfaces proporcionan muchos métodos y propiedades utilizables sobre los elementos individuales. Éstos elementos pueden igualmente tener interfaces específicas según el tipo de datos representados, como en el ejemplo anterior del objeto <code>table</code>. Lo siguiente es una breve lista de los APIS comunes en la web y en las páginas escritas en XML utilizando el DOM.</p> + +<ul> + <li><code><a href="es/DOM/document.getElementById">document.getElementById</a>(id)</code></li> + <li><code>element.<a href="es/DOM/element.getElementsByTagName">getElementsByTagName</a>(name)</code></li> + <li><code><a href="es/DOM/document.createElement">document.createElement</a>(name)</code></li> + <li><code>parentNode.<a href="es/DOM/element.appendChild">appendChild</a>(node)</code></li> + <li><code>element.<a href="es/DOM/element.innerHTML">innerHTML</a></code></li> + <li><code>element.<a href="es/DOM/element.style">style</a>.left</code></li> + <li><code>element.<a href="es/DOM/element.setAttribute">setAttribute</a></code></li> + <li><code>element.<a href="es/DOM/element.getAttribute">element.getAttribute</a></code></li> + <li><code>element.<a href="es/DOM/element.addEventListener">addEventListener</a></code></li> + <li><code><a href="es/DOM/window.content">window.content</a></code></li> + <li><code><a href="es/DOM/window.onload">window.onload</a></code></li> + <li><code><a href="es/DOM/window.dump">window.dump</a></code></li> + <li><code><a href="es/DOM/window.scrollTo">window.scrollTo</a></code></li> +</ul> + +<h2 id="Probando_el_API_del_DOM" name="Probando_el_API_del_DOM">Probando el API del DOM</h2> + +<p>Ésta parte procura ejemplos para todas las interfaces usadas en el desarrollo web. En algunos casos, los ejemplos son páginas HTML enteras, con el acceso del DOM a un elemento de <script>, la interfaz necesaria (por ejemplo, botones) para la ejecución del script en un formulario, y también que los elementos HTML sobre los cuales opera el DOM se listen. Según el caso, los ejemplos se pueden copiar y pegar en un documento web para probarlos.</p> + +<p>No es el caso donde los ejemplos son muchos más concisos. Para la ejecución de estos ejemplos que sólo demuestran la relación básica entre la interfaz y los elementos HTML, resulta útil tener una página de prueba en la cual las interfaces serán fácilmente accesibles por los scripts. La muy simple página siguiente proporciona en las cabeceras un elemento de script en el cual se pondrán las funciones para testar la interfaz elegida, algunos elementos HTML con atributos que se puedan leer, editar y también manipular, así como la interfaz web necesaria para llamar esas funciones desde el navegador.</p> + +<p>Para probar y ver como trabajan en la plataforma del navegador las interfaces del DOM, esta página de prueba o una nueva similar son factibles. El contenido de la función <code>test()</code> se puede actualizar según la necesidad, para crear más botones o poner más elementos.</p> + +<pre class="brush: html line-numbers language-html"><code class="language-html"><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>html</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>head</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>title</span><span class="punctuation token">></span></span>Pruebas DOM<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>title</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>script</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>application/javascript<span class="punctuation token">"</span></span><span class="punctuation token">></span></span><span class="language-javascript script token"> + <span class="keyword token">function</span> <span class="function token">setBodyAttr</span><span class="punctuation token">(</span>attr<span class="punctuation token">,</span> value<span class="punctuation token">)</span><span class="punctuation token">{</span> + <span class="keyword token">if</span> <span class="punctuation token">(</span>document<span class="punctuation token">.</span>body<span class="punctuation token">)</span> <span class="function token">eval</span><span class="punctuation token">(</span><span class="string token">'document.body.'</span><span class="operator token">+</span>attr<span class="operator token">+</span><span class="string token">'="'</span><span class="operator token">+</span>value<span class="operator token">+</span><span class="string token">'"'</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="keyword token">else</span> <span class="function token">notSupported</span><span class="punctuation token">(</span><span class="punctuation token">)</span><span class="punctuation token">;</span> + <span class="punctuation token">}</span> + </span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>script</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>head</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>body</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>div</span><span class="language-css style-attr token"><span class="attr-name token"> <span class="attr-name token">style</span></span><span class="punctuation token">="</span><span class="attr-value token"><span class="property token">margin</span><span class="punctuation token">:</span> <span class="number token">.5</span>in<span class="punctuation token">;</span> <span class="property token">height</span><span class="punctuation token">:</span> <span class="number token">400</span><span class="punctuation token">;</span></span><span class="punctuation token">"</span></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><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>b</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>tt</span><span class="punctuation token">></span></span>texto<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>tt</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>b</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> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>form</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>select</span> <span class="attr-name token">onChange</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>setBodyAttr(<span class="punctuation token">'</span>text<span class="punctuation token">'</span>, + this.options[this.selectedIndex].value);<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>black<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>negro + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>darkblue<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>azul oscuro + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>select</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><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>b</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>tt</span><span class="punctuation token">></span></span>bgColor<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>tt</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>b</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> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>select</span> <span class="attr-name token">onChange</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>setBodyAttr(<span class="punctuation token">'</span>bgColor<span class="punctuation token">'</span>, + this.options[this.selectedIndex].value);<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>white<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>blanco + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>lightgrey<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>gris + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>select</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><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>b</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"><</span>tt</span><span class="punctuation token">></span></span>link<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>tt</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>b</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> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>select</span> <span class="attr-name token">onChange</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>setBodyAttr(<span class="punctuation token">'</span>link<span class="punctuation token">'</span>, + this.options[this.selectedIndex].value);<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>blue<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>azul + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>option</span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>green<span class="punctuation token">"</span></span><span class="punctuation token">></span></span>verde + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>select</span><span class="punctuation token">></span></span> <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>small</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>a</span> <span class="attr-name token">href</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>http://www.brownhen.com/dom_api_top.html<span class="punctuation token">"</span></span> <span class="attr-name token">id</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>sample<span class="punctuation token">"</span></span><span class="punctuation token">></span></span> + (sample link)<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>a</span><span class="punctuation token">></span></span><span class="tag token"><span class="tag token"><span class="punctuation token"></</span>small</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>form</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>form</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"><</span>input</span> <span class="attr-name token">type</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>button<span class="punctuation token">"</span></span> <span class="attr-name token">value</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>version<span class="punctuation token">"</span></span> <span class="attr-name token">onclick</span><span class="attr-value token"><span class="punctuation token">=</span><span class="punctuation token">"</span>ver()<span class="punctuation token">"</span></span> <span class="punctuation token">/></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>form</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>div</span><span class="punctuation token">></span></span> + <span class="tag token"><span class="tag token"><span class="punctuation token"></</span>body</span><span class="punctuation token">></span></span> +<span class="tag token"><span class="tag token"><span class="punctuation token"></</span>html</span><span class="punctuation token">></span></span></code></pre> + +<p>La creación de una página de prueba con una paleta de botones, campos de texto u otros elementos HTML, permitirá testar una gran cantidad de interfaces en un mismo documento, por ejemplo una serie de propiedades que afectan a los colores de una página web. Lo siguiente permite hacerse una idea de como pueden agruparse las interfaces para probarlas.</p> + +<p><font><font>Figura 0.1 Muestra DOM página de prueba</font></font></p> + +<p><img alt="" src="https://developer.mozilla.org/@api/deki/files/173/=DOM_Ref_Introduction_to_the_DOM.gif" style="height: 375px; width: 199px;"></p> + +<p>En este ejemplo, los menúes desplegables actualizan dinámicamente los aspectos de la página web accesibles al DOM como el color de fondo (<code>bgColor</code>), de los hiper-enlaces (<code>aLink</code>), y el del texto (<code>text</code>). El hecho de diseñar páginas, testar las interfaces que se encuentren a lo largo de la lectura son una parte importante del aprendizaje para una utilización eficaz del DOM.</p> + +<h2 id="Otros_enlaces"><strong>Otros enlaces</strong></h2> + +<ul> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model"><font><font>Referencia DOM</font></font></a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Introduction"><font><font>Introducción al DOM</font></font></a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events"><font><font>Eventos y el DOM</font></font></a></li> + <li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Examples"><font><font>Ejemplos</font></font></a></li> +</ul> + +<div class="s3gt_translate_tooltip_mini_box" id="s3gt_translate_tooltip_mini" style="background: initial !important; border: initial !important; border-radius: initial !important; border-collapse: initial !important; direction: ltr !important; font-weight: initial !important; height: initial !important; letter-spacing: initial !important; max-width: initial !important; min-height: initial !important; margin: auto !important; outline: initial !important; padding: initial !important; position: absolute; text-align: initial !important; text-shadow: initial !important; width: initial !important; display: initial !important; color: inherit !important; font-size: 13px !important; font-family: X-LocaleSpecific,sans-serif,Tahoma,Helvetica !important; line-height: 13px !important; vertical-align: top !important; white-space: inherit !important; left: 10px; top: 35px; opacity: 0.85;"> +<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> + +<div class="s3gt_translate_tooltip_mini_box" id="s3gt_translate_tooltip_mini" style="background: initial !important; border: initial !important; border-radius: initial !important; border-collapse: initial !important; direction: ltr !important; font-weight: initial !important; height: initial !important; letter-spacing: initial !important; max-width: initial !important; min-height: initial !important; margin: auto !important; outline: initial !important; padding: initial !important; position: absolute; text-align: initial !important; text-shadow: initial !important; width: initial !important; display: initial !important; color: inherit !important; font-size: 13px !important; font-family: X-LocaleSpecific,sans-serif,Tahoma,Helvetica !important; line-height: 13px !important; vertical-align: top !important; white-space: inherit !important; left: 39px; top: 1952px; opacity: 0.45;"> +<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="Escuchar"> </div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_copy" title="Copiar texto al Portapapeles"> </div> +</div> + +<div class="s3gt_translate_tooltip_mini_box" id="s3gt_translate_tooltip_mini" style="background: initial !important; border: initial !important; border-radius: initial !important; border-collapse: initial !important; direction: ltr !important; font-weight: initial !important; height: initial !important; letter-spacing: initial !important; max-width: initial !important; min-height: initial !important; margin: auto !important; outline: initial !important; padding: initial !important; position: absolute; text-align: initial !important; text-shadow: initial !important; width: initial !important; display: initial !important; color: inherit !important; font-size: 13px !important; font-family: X-LocaleSpecific,sans-serif,Tahoma,Helvetica !important; line-height: 13px !important; vertical-align: top !important; white-space: inherit !important; left: 307px; top: 1961px; opacity: 0;"> +<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="Escuchar"> </div> + +<div class="s3gt_translate_tooltip_mini" id="s3gt_translate_tooltip_mini_copy" title="Copiar texto al Portapapeles"> </div> +</div> diff --git a/files/es/web/api/document_object_model/locating_dom_elements_using_selectors/index.html b/files/es/web/api/document_object_model/locating_dom_elements_using_selectors/index.html new file mode 100644 index 0000000000..cf8a94cd4a --- /dev/null +++ b/files/es/web/api/document_object_model/locating_dom_elements_using_selectors/index.html @@ -0,0 +1,50 @@ +--- +title: Localizando elementos DOM usando selectores +slug: Referencia_DOM_de_Gecko/Localizando_elementos_DOM_usando_selectores +tags: + - DOM + - Necesita actualizacion para principiantes + - Principiante +translation_of: Web/API/Document_object_model/Locating_DOM_elements_using_selectors +--- +<p>Los selectores api proveen metodos que hacen mas facil y rapido devolver elementos del nodo {{domxref("Element")}} del DOM mediante emparejamiento de un conjunto de selectores. Esto es mucho mas rapido que las tecnicas anteriores, donde fuera necesario, por ejemplo usar un loop en un codigo JavaScript para localizar el item especifico que quisieras encontrar.</p> + +<h2 id="Interfaz_de_NodeSelector">Interfaz de NodeSelector</h2> + +<p>Esta especificación añade dos nuevos metodos a cualquier objeto implementando el {{domxref("Document")}}, {{domxref("DocumentFragment")}}, o {{domxref("Element")}} interfaces:</p> + +<dl> + <dt>{{domxref("Element.querySelector", "querySelector()")}}</dt> + <dd>Devuelve la primera coincidencia del (elemento) {{domxref("Element")}} nodo dentro de las subramas del nodo. Sino se encuentra un nodo coincidente, se devuelve <code>null</code> .</dd> + <dt>{{domxref("Element.querySelectorAll", "querySelectorAll()")}}</dt> + <dd>devuelve un listado de nodos {{domxref("NodeList")}} conteniendo todos los elementos del nodo coincidentes( <code>Element</code>) dentro de las subramas del nodo, o Devuelve un Listado de Nodos vacio <code>NodeList</code> sino se encuentran coincidencias.</dd> +</dl> + +<div class="note"><strong>Note:</strong> El {{domxref("NodeList")}} devuelto por {{domxref("Element.querySelectorAll()", "querySelectorAll()")}} no es dinamico, Es decir que cualquier cambio realizado en el DOM no se vera reflejado en la coleccion. Esto es diferente de otros metodos de querying del dom que si devuelven listados de nodos dinamicos.</div> + +<p>Encontraras ejemplos y detalles leyendo el documento de metodos {{domxref("Element.querySelector()")}} y {{domxref("Element.querySelectorAll()")}}, Tambien en el articulo <a class="internal" href="/en-US/docs/Code_snippets/QuerySelector" title="en-US/docs/Code snippets/QuerySelector">Code snippets for querySelector</a>.</p> + +<h2 id="Selectors">Selectors</h2> + +<p>El metodo de selectores acepta uno o mas selectores seperados por comas entre cada selector para determinar que elemento o elementos deben ser devueltos. por ejemplo para seleccionar todos los elementos (p) del parrafo en un documento donde la clase CSS sea tanto <code>warning</code> or <code>note</code>, podes hacer lo siguiente:</p> + +<pre class="notranslate"><code>var special = document.querySelectorAll( "p.warning, p.note" );</code></pre> + +<p>tambien por usar query para etiquetas id. Por ejemplo:</p> + +<pre class="notranslate"><code>var el = document.querySelector( "#main, #basic, #exclamation" );</code></pre> + +<p>luego de ejecutar el codigo de arriba, la variable <code>el</code> contiene el primer elemento del documento, su ID puede ser uno de los siguentes <code>main</code>, <code>basic</code>, or <code>exclamation</code>.</p> + +<p>Podes usar cualquier selector CSS con los metodos <code>querySelector()</code> y <code>querySelectorAll()</code><em>.</em></p> + +<h2 id="Ver_tambien.">Ver tambien.</h2> + +<ul> + <li><a class="external" href="http://www.w3.org/TR/selectors-api/" title="http://www.w3.org/TR/selectors-api/">Selectors API</a></li> + <li>{{domxref("Element.querySelector()")}}</li> + <li>{{domxref("Element.querySelectorAll()")}}</li> + <li>{{domxref("Document.querySelector()")}}</li> + <li>{{domxref("Document.querySelectorAll()")}}</li> + <li><a href="/en-US/docs/Code_snippets/QuerySelector" title="en-US/docs/Code_snippets/QuerySelector">Code snippets for querySelector</a></li> +</ul> diff --git a/files/es/web/api/document_object_model/traversing_an_html_table_with_javascript_and_dom_interfaces/index.html b/files/es/web/api/document_object_model/traversing_an_html_table_with_javascript_and_dom_interfaces/index.html new file mode 100644 index 0000000000..b8bc2e4cf9 --- /dev/null +++ b/files/es/web/api/document_object_model/traversing_an_html_table_with_javascript_and_dom_interfaces/index.html @@ -0,0 +1,337 @@ +--- +title: Trazado de una tabla HTML mediante JavaScript y la Interface DOM +slug: Trazado_de_una_tabla_HTML_mediante_JavaScript_y_la_Interface_DOM +translation_of: >- + Web/API/Document_Object_Model/Traversing_an_HTML_table_with_JavaScript_and_DOM_Interfaces +--- +<h2 id="Introduction" name="Introduction">Introducción</h2> + +<p>Este artículo es un resumen de algunos métodos DOM nivel 1 poderosos y fundamentales así como una descripción de cómo utilizarlos utilizando Javascript. Aprenderás a crear, accesar, controlar, y remover elementos HTML dinámicamente. Los métodos DOM presentados aquí no son específicos de HTML; también aplican para XML. Las demostraciones aquí proporcionadas funcionarán en cualquier navegador moderno, incluyendo todas las versiones de Firefox e IE 5+.</p> + +<div class="note">Los métodos DOM presentados aquí forman parte del Modelo de Documento basado en Objetos (DOM: Document Object Model por sus siglas en inglés) de especificación nivel 1. DOM nivel 1 incluye métodos tanto para acceso genérico del documento (DOM 1 Core) así como métodos específicos para documentos HTML (DOM 1 HTML).</div> + +<h2 id="Overview_of_Sample1.html" name="Overview_of_Sample1.html">Ejemplo: Crear una tabla HTML dinámicamente (<code>Ejemplo1.html</code>)</h2> + +<h3 id="Contenido_HTML">Contenido HTML</h3> + +<pre class="brush: html"><input type="button" value="Genera una tabla" onclick="genera_tabla()"> +</pre> + +<h3 id="JavaScript_Content">JavaScript Content</h3> + +<pre class="brush: js">function genera_tabla() { + // Obtener la referencia del elemento body + var body = document.getElementsByTagName("body")[0]; + + // Crea un elemento <table> y un elemento <tbody> + var tabla = document.createElement("table"); + var tblBody = document.createElement("tbody"); + + // Crea las celdas + for (var i = 0; i < 2; i++) { + // Crea las hileras de la tabla + var hilera = document.createElement("tr"); + + for (var j = 0; j < 2; j++) { + // Crea un elemento <td> y un nodo de texto, haz que el nodo de + // texto sea el contenido de <td>, ubica el elemento <td> al final + // de la hilera de la tabla + var celda = document.createElement("td"); + var textoCelda = document.createTextNode("celda en la hilera "+i+", columna "+j); + celda.appendChild(textoCelda); + hilera.appendChild(celda); + } + + // agrega la hilera al final de la tabla (al final del elemento tblbody) + tblBody.appendChild(hilera); + } + + // posiciona el <tbody> debajo del elemento <table> + tabla.appendChild(tblBody); + // appends <table> into <body> + body.appendChild(tabla); + // modifica el atributo "border" de la tabla y lo fija a "2"; + tabla.setAttribute("border", "2"); +}</pre> + +<p>{{ EmbedLiveSample('Overview_of_Sample1.html') }}</p> + +<p>Observa cuidadosamente el orden en el que se crearon los elementos en el nodo de texto:</p> + +<ol> + <li>Primero se crea el elemento <table>.</li> + <li>Posteriormente, creamos el elemento <tbody> , que es el hijo del elemento <table> .</li> + <li>Después, utilizamos ciclos para crear los elementos <tr>, que son hijos del elemento <tbody>.</li> + <li>Para cada elemento <tr>, utilizamos nuevamente ciclos para generar los elementos <td> que son hijos de los elementos <tr>.</li> + <li>Para cada elemento <td>, creamos nodos de texto con el contenido de cada celda.</li> +</ol> + +<p>Una vez creados los elementos <table>, <tbody>, <tr>, y <td> así como los nodos de texto, adicionamos a cada hijo bajo su padre en el órden opuesto:</p> + +<ol> + <li>Primero, anexamos cada nodo de texto a su elemento padre <td> : + <pre>celda.appendChild(textoCelda);</pre> + </li> + <li>Posteriormente, anexamos cada elemento <td> a su elemento padre <tr> : + <pre>hilera.appendChild(celda);</pre> + </li> + <li>Posteriomente, anexamos cada elemento <tr> a su elemento padre <tbody>: + <pre>tblBody.appendChild(hilera);</pre> + </li> + <li>Después, anexamos el elemento <tbody> a su elemento padre <table>: + <pre>tabla.appendChild(tblBody);</pre> + </li> + <li>Finalmente, anexamos el elemento <table> a su elemento padre <body>: + <pre>body.appendChild(tabla);</pre> + </li> +</ol> + +<p>Recuérda esta técnica. Te será muy útil en la programación bajo el estándar W3C DOM. Primero, creas los elementos de arriba a abajo; posteriormente adicionas los hijos a los padres de abajo a arriba.</p> + +<p>A continuación aparece el código HTML generado por el código JavaScript:</p> + +<pre>... +<table border="2"> + <tbody> + <tr><td>celda en la hilera 0, columna 0</td><td>celda en la hilera 0, columna 1</td></tr> + <tr><td>celda en la hilera 1, columna 0</td><td>celda en la hilera 1, columna 1</td></tr> + </tbody> +</table> +... +</pre> + +<p>Aquí está el árbol de objetos DOM generado por el código del elemento <TABLE> :</p> + +<p><img alt="Image:sample1-tabledom.jpg" src="/@api/deki/files/833/=Sample1-tabledom.jpg"></p> + +<p>Tú puedes construir esta tabla y sus elementos internos utilizando sólo algunos de los varios métodos del DOM. Recuerda tener en mente el modelo de la estructura que planeas crear; esto hará mucho más fácil la escritura del código necesario.</p> + +<p>En el árbol del elemento <table> de la Figura 1, el elemento <table> tiene solamente un hijo mientras que <tbody> tiene dos. A su vez, cada hijo de <tbody> tiene dos hijos. Finalmente, cada elemento <td> tiene sólo uno, el nodo de texto.</p> + +<h2 id="Setting_background_of_a_paragraph" name="Setting_background_of_a_paragraph">Ejemplo: Configuración del color de fondo de un párrafo</h2> + +<p><code>getElementsByTagName(tagNameValue)</code> es un método disponible en cualquier elemento DOM o el elemento raíz del documento. Cuando se le llama, devolverá una matriz con todos los descendientes de elementos que coincidan con el nombre de la etiqueta. El primer elemento de la lista se encuentra en la posición [0] de la matriz.</p> + +<h3 id="HTML_Content">HTML Content</h3> + +<pre class="brush: html"><body> + <input type="button" value="Set paragraph background color" onclick="set_background()"> + <p>hi</p> + <p>hello</p> +</body></pre> + +<h3 id="JavaScript_Content_2">JavaScript Content</h3> + +<pre class="brush: js">function set_background() { + // get a list of all the body elements (there will only be one), + // and then select the zeroth (or first) such element + myBody = document.getElementsByTagName("body")[0]; + + // now, get all the p elements that are descendants of the body + myBodyElements = myBody.getElementsByTagName("p"); + + // get the second item of the list of p elements + myP = myBodyElements[1]; + myP.style.background = "rgb(255,0,0)"; +}</pre> + +<p>{{ EmbedLiveSample('Setting_background_of_a_paragraph') }}</p> + +<p>En este ejemplo, establecemos la variable <code>myP</code> en el objeto DOM para el segundo elemento<code>p</code> dentro del body:</p> + +<ol> + <li>Primero, obtendremos una lista de todos los elementos body mediante + <pre>myBody = document.getElementsByTagName("body")[0]</pre> + Como en cualquier documento HTML sólo hay un elemento body válido, esta lista tendrá sólo un elemento, que recuperamos seleccionando el primer elemento de esa lista usando <code>{{mediawiki.external(0)}}</code>.</li> + <li>Luego, obtenemos todos los elementos p que son descendientes del body mediante + <pre>myBodyElements = myBody.getElementsByTagName("p");</pre> + </li> + <li>Finalmente, obtenemos el segundo item de la lista de elementos p mediante + <pre>myP = myBodyElements[1];</pre> + </li> +</ol> + +<p><img alt="Image:sample2a2.jpg" src="/@api/deki/files/834/=Sample2a2.jpg"></p> + +<p>Una vez que haya obtenido el objeto DOM para un elemento HTML, puede establecer sus propiedades. Por ejemplo, si desea establecer la propiedad estilo de color de fondo, agregue:</p> + +<pre>myP.style.background = "rgb(255,0,0)"; +// setting inline STYLE attribute +</pre> + +<h3 id="Creating_TextNodes_with_document.createTextNode.28.22...22.29" name="Creating_TextNodes_with_document.createTextNode.28.22...22.29">Creating TextNodes with <code>document.createTextNode("..")</code></h3> + +<p>Use the document object to invoke the createTextNode method and create your text node. You just need to pass the text content. The return value is an object that represents the text node.</p> + +<pre>myTextNode = document.createTextNode("world"); +</pre> + +<p>This means that you have created a node of the type TEXT_NODE (a piece of text) whose text data is "world", and myTextNode is your reference to this node object. To insert this text into your HTML page, you need to make this text node a child of some other node element.</p> + +<h3 id="Inserting_Elements_with_appendChild.28...29" name="Inserting_Elements_with_appendChild.28...29">Inserting Elements with appendChild(..)</h3> + +<p>So, by calling myP.appendChild({{mediawiki.external('node_element')}}), you are making the element a new child of the second <p> element.</p> + +<pre>myP.appendChild(myTextNode); +</pre> + +<p>After testing this sample, note that the words hello and world are together: helloworld. So visually, when you see the HTML page it seems like the two text nodes hello and world are a single node, but remember that in the document model, there are two nodes. The second node is a new node of type TEXT_NODE, and it is the second child of the second <p> tag. The following figure shows the recently created Text Node object inside the document tree.</p> + +<p><img alt="Image:sample2b2.jpg" src="/@api/deki/files/835/=Sample2b2.jpg"></p> + +<div class="note">createTextNode and appendChild is a simple way to include white space between the words hello and world. Another important note is that the appendChild method will append the child after the last child, just like the word world has been added after the word hello. So if you want to append a Text Node between hello and world you will need to use insertBefore instead of appendChild.</div> + +<h3 id="Creating_New_Elements_with_the_document_object_and_the_createElement.28...29_method" name="Creating_New_Elements_with_the_document_object_and_the_createElement.28...29_method">Creating New Elements with the document object and the <code>createElement(..)</code> method</h3> + +<p>You can create new HTML elements or any other element you want with createElement. For example, if you want to create a new <p> element as a child of the <body> element, you can use the myBody in the previous example and append a new element node. To create a node simply call <code>document.createElement("tagname")</code>. For example:</p> + +<pre>myNewPTAGnode = document.createElement("p"); +myBody.appendChild(myNewPTAGnode); +</pre> + +<p><img alt="Image:sample2c.jpg" src="/@api/deki/files/836/=Sample2c.jpg"></p> + +<h3 id="Removing_nodes_with_the_removeChild.28...29_method" name="Removing_nodes_with_the_removeChild.28...29_method">Removing nodes with the <code>removeChild(..)</code> method</h3> + +<p>Nodes can be removed. The following code removes text node <code>myTextNode</code> (containing the word "world") from the second <code><p></code> element, <code>myP</code>.</p> + +<pre>myP.removeChild(myTextNode); +</pre> + +<p>Text node <code>myTextNode</code> (containing the word "world") still exists. The following code attaches <code>myTextNode</code> to the recently created <code><p></code> element, <code>myNewPTAGnode</code>.</p> + +<pre>myNewPTAGnode.appendChild(myTextNode); +</pre> + +<p>The final state for the modified object tree looks like this:</p> + +<p><img alt="Image:sample2d.jpg" src="/@api/deki/files/837/=Sample2d.jpg"></p> + +<h2 id="Creating_a_table_dynamically_.28back_to_Sample1.html.29" name="Creating_a_table_dynamically_.28back_to_Sample1.html.29">Creating a table dynamically (back to Sample1.html)</h2> + +<p>For the rest of this article we will continue working with sample1.html. The following figure shows the table object tree structure for the table created in the sample.</p> + +<h3 id="Reviewing_the_HTML_Table_structure" name="Reviewing_the_HTML_Table_structure">Reviewing the HTML Table structure</h3> + +<p><img alt="Image:sample1-tabledom.jpg" src="/@api/deki/files/833/=Sample1-tabledom.jpg"></p> + +<h3 id="Creating_element_nodes_and_inserting_them_into_the_document_tree" name="Creating_element_nodes_and_inserting_them_into_the_document_tree">Creating element nodes and inserting them into the document tree</h3> + +<p>The basic steps to create the table in sample1.html are:</p> + +<ul> + <li>Get the body object (first item of the document object).</li> + <li>Create all the elements.</li> + <li>Finally, append each child according to the table structure (as in the above figure). The following source code is a commented version for the sample1.html.</li> +</ul> + +<div class="note">At the end of the start function there is a new line of code. The table's border property was set using another DOM method, <code>setAttribute</code>. setAttribute has two arguments: the attribute name and the attribute value. You can set any attribute of any element using the setAttribute method.</div> + +<pre class="brush:html"><head> +<title>Sample code - Traversing an HTML Table with JavaScript and DOM Interfaces</title> +<script> + function start() { + // get the reference for the body + var mybody = document.getElementsByTagName("body")[0]; + + // creates <table> and <tbody> elements + mytable = document.createElement("table"); + mytablebody = document.createElement("tbody"); + + // creating all cells + for(var j = 0; j < 2; j++) { + // creates a <tr> element + mycurrent_row = document.createElement("tr"); + + for(var i = 0; i < 2; i++) { + // creates a <td> element + mycurrent_cell = document.createElement("td"); + // creates a Text Node + currenttext = document.createTextNode("cell is row " + j + ", column " + i); + // appends the Text Node we created into the cell <td> + mycurrent_cell.appendChild(currenttext); + // appends the cell <td> into the row <tr> + mycurrent_row.appendChild(mycurrent_cell); + } + // appends the row <tr> into <tbody> + mytablebody.appendChild(mycurrent_row); + } + + // appends <tbody> into <table> + mytable.appendChild(mytablebody); + // appends <table> into <body> + mybody.appendChild(mytable); + // sets the border attribute of mytable to 2; + mytable.setAttribute("border","2"); + } +</script> +</head> +<body onload="start()"> +</body> +</html></pre> + +<h2 id="Manipulating_the_table_with_DOM_and_CSS" name="Manipulating_the_table_with_DOM_and_CSS">Manipulating the table with DOM and CSS</h2> + +<h3 id="Getting_a_text_node_from_the_table" name="Getting_a_text_node_from_the_table">Getting a text node from the table</h3> + +<p>This example introduces two new DOM attributes. First it uses the <code>childNodes</code> attribute to get the list of child nodes of mycel. The <code>childNodes</code> list includes all child nodes, regardless of what their name or type is. Like getElementsByTagName(), it returns a list of nodes. The differences are that (a) getElementsByTagName() only returns elements of the specified tag name; and (b) getElementsByTagName() returns descendants at any level, not just immediate children. Once you have the returned list, use <code>{{mediawiki.external('x')}}</code> method to retrieve the desired child item. This example stores in myceltext the text node of the second cell in the second row of the table. Then, to display the results in this example, it creates a new text node whose content is the data of myceltext and appends it as a child of the <body> element.</p> + +<div class="note">If your object is a text node, you can use the data attribute and retrieve the text content of the node.</div> + +<pre class="brush:js">mybody = document.getElementsByTagName("body")[0]; +mytable = mybody.getElementsByTagName("table")[0]; +mytablebody = mytable.getElementsByTagName("tbody")[0]; +myrow = mytablebody.getElementsByTagName("tr")[1]; +mycel = myrow.getElementsByTagName("td")[1]; + +// first item element of the childNodes list of mycel +myceltext=mycel.childNodes[0]; + +// content of currenttext is the data content of myceltext +currenttext=document.createTextNode(myceltext.data); +mybody.appendChild(currenttext); +</pre> + +<h3 id="Getting_an_attribute_value" name="Getting_an_attribute_value">Getting an attribute value</h3> + +<p>At the end of sample1 there is a call to setAttribute on the mytable object. This call was used to set the border property of the table. To retrieve the value of the attribute, use the getAttribute method:</p> + +<pre>mytable.getAttribute("border"); +</pre> + +<h3 id="Hiding_a_column_by_changing_style_properties" name="Hiding_a_column_by_changing_style_properties">Hiding a column by changing style properties</h3> + +<p>Once you have the object in your JavaScript variable, you can set style properties directly. The following code is a modified version of sample1.html in which each cell of the second column is hidden and each cell of the first column is changed to have a red background. Note that the style property was set directly.</p> + +<pre class="brush:html"><html> +<body onload="start()"> +</body> +<script> + function start() { + var mybody =document.getElementsByTagName("body")[0]; + mytable = document.createElement("table"); + mytablebody = document.createElement("tbody"); + + for(var j = 0; j < 2; j++) { + mycurrent_row=document.createElement("tr"); + for(var i = 0; i < 2; i++) { + mycurrent_cell = document.createElement("td"); + currenttext = document.createTextNode("cell is:" + i + j); + mycurrent_cell.appendChild(currenttext); + mycurrent_row.appendChild(mycurrent_cell); + // set the cell background color + // if the column is 0. If the column is 1 hide the cel + if (i == 0) { + mycurrent_cell.style.background = "rgb(255,0,0)"; + } else { + mycurrent_cell.style.display = "none"; + } + } + mytablebody.appendChild(mycurrent_row); + } + mytable.appendChild(mytablebody); + mybody.appendChild(mytable); + } +</script> +</html> +</pre> diff --git a/files/es/web/api/document_object_model/using_the_w3c_dom_level_1_core/index.html b/files/es/web/api/document_object_model/using_the_w3c_dom_level_1_core/index.html new file mode 100644 index 0000000000..6c5f14c025 --- /dev/null +++ b/files/es/web/api/document_object_model/using_the_w3c_dom_level_1_core/index.html @@ -0,0 +1,93 @@ +--- +title: Using the W3C DOM Level 1 Core +slug: Using_the_W3C_DOM_Level_1_Core +tags: + - DOM + - NeedsTranslation + - NeedsUpdate + - TopicStub +translation_of: Web/API/Document_object_model/Using_the_W3C_DOM_Level_1_Core +--- +<p>The W3C's DOM Level 1 Core is a powerful object model for changing the content tree of documents. It is supported in all major browsers including Mozilla Firefox and Microsoft Internet Explorer. It is a powerful base for scripting on the web.</p> + +<h2 id="What_is_a_content_tree.3F" name="What_is_a_content_tree.3F">What is a content tree?</h2> + +<p>Many HTML authors may think of HTML as something flat -- a bunch of text with tags in the middle. However, it is something much more than that. Any HTML document (or for that matter any SGML document or XML document) is a tree structure. For example, the following document and tree structure are similar (although not identical -- see the notes on <a href="/en-US/docs/Whitespace_in_the_DOM" title="Whitespace_in_the_DOM">whitespace in the DOM</a>):</p> + +<pre class="brush: html"><html> +<head> + <title>My Document</title> +</head> +<body> + <h1>Header</h1> + <p>Paragraph</p> +</body> +</html> +</pre> + +<p><img alt="image:Using_the_W3C_DOM_Level_1_Core-doctree.jpg" class="internal" src="/@api/deki/files/415/=Using_the_W3C_DOM_Level_1_Core-doctree.jpg"></p> + +<p>When Mozilla parses a document, it builds a content tree and then uses it to display the document.</p> + +<p>The terms used to describe trees show up often in the DOM Level 1 Core. Each of the boxes I drew in the tree above is a node in the tree. The line above a node expresses a parent-child relationship: the node on top is the parent, and the node on the bottom is the child. Two children of the same parent are therefore siblings. Similarly, one can refer to ancestors and descendants. (Cousins are too messy, though.)</p> + +<h2 id="What_does_the_DOM_Level_1_Core_let_me_do.3F" name="What_does_the_DOM_Level_1_Core_let_me_do.3F">What does the DOM Level 1 Core let me do?</h2> + +<p>The W3C DOM Level 1 allows you to change the content tree <em>any way you want</em>. It is powerful enough to build any HTML document from scratch. It allows authors to change anything in the document from script, at any time. The easiest way for web page authors to change the DOM dynamically is using JavaScript. In JavaScript, the document is accessible the same way it has been in older browsers: from the <code>document</code> property of the global object. This <code>document</code> object implements the <a class="external" href="http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html#i-Document">Document interface</a> from the W3C's DOM Level 1 spec.</p> + +<h2 id="A_simple_example" name="A_simple_example">A simple example</h2> + +<p>Suppose the author wants to take the above document and change the contents of the header, and write two paragraphs instead of one. The following script would do the job:</p> + +<h3 id="HTML_Content">HTML Content</h3> + +<pre class="brush: html"><body> +<input type="button" value="Change this document." onclick="change()"> +<h2>Header</h2> +<p>Paragraph</p> +</body><span> +</span></pre> + +<h3 id="JavaScript_Content">JavaScript Content</h3> + +<pre class="brush: js"><span> function change() { + // document.getElementsByTagName("H2") returns a NodeList of the <h2> + // elements in the document, and the first is number 0: + + var header = document.getElementsByTagName("H2").item(0); + // the firstChild of the header is a Text node: + header.firstChild.data = "A dynamic document"; + // now the header is "A dynamic document". + + var para = document.getElementsByTagName("P").item(0); + para.firstChild.data = "This is the first paragraph."; + + // create a new Text node for the second paragraph + var newText = document.createTextNode("This is the second paragraph."); + // create a new Element to be the second paragraph + var newElement = document.createElement("P"); + // put the text in the paragraph + newElement.appendChild(newText); + // and put the paragraph on the end of the document by appending it to + // the BODY (which is the parent of para) + para.parentNode.appendChild(newElement); + }</span></pre> + +<p>{{ EmbedLiveSample('A_simple_example', 800, 300) }}</p> + +<p>You can see this script as <a class="internal" href="/@api/deki/files/2866/=example.html" title="/@api/deki/files/2866/=example.html">a complete example</a>.</p> + +<h2 id="How_can_I_learn_more.3F" name="How_can_I_learn_more.3F">How can I learn more?</h2> + +<p>Now that you are familiar with the basic concepts of the DOM, there is a document explaining the <a href="/en-US/docs/Traversing_an_HTML_table_with_JavaScript_and_DOM_Interfaces" title="Traversing_an_HTML_table_with_JavaScript_and_DOM_Interfaces">DOM Level 1 fundamental methods</a>. It is the follow-up to this document.</p> + +<p>See also the <a class="external" href="http://www.w3.org/TR/REC-DOM-Level-1/level-one-core.html">DOM Level 1 Core specification</a> from the W3C. It's a reasonably clear spec, although it is formal. The main thing that's useful to authors is the description of the different DOM objects and all their properties and methods. Also see our <a href="/en-US/docs/DOM" title="DOM">other DOM documentation</a>.</p> + +<div class="originaldocinfo"> +<p><strong>Original Document Information</strong></p> + +<ul> + <li>Author(s): L. David Baron <dbaron at dbaron dot org></li> + <li>Copyright Information: © 1998-2005 by individual mozilla.org contributors; content available under a <a class="external" href="http://www.mozilla.org/foundation/licensing/website-content.html">Creative Commons license</a></li> +</ul> +</div> diff --git a/files/es/web/api/document_object_model/whitespace/index.html b/files/es/web/api/document_object_model/whitespace/index.html new file mode 100644 index 0000000000..a943896180 --- /dev/null +++ b/files/es/web/api/document_object_model/whitespace/index.html @@ -0,0 +1,476 @@ +--- +title: 'Cómo manejan el espacio en blanco HTML, CSS y el DOM' +slug: Referencia_DOM_de_Gecko/Cómo_espacioenblanco +tags: + - CSS + - DOM + - HTML + - JavaScript + - espacioenblanco + - whitespace +translation_of: Web/API/Document_Object_Model/Whitespace +--- +<div>{{APIRef("DOM")}}</div> + +<p>La presencia de espacios en blanco en el <a href="/es/docs/Web/API/Document_Object_Model">DOM</a> puede causar problemas de diseño y dificultar la manipulación del árbol de contenido de formas inesperadas, dependiendo de dónde se encuentra. Este artículo explora cuándo pueden surgir dificultades y analiza qué se puede hacer para mitigar los problemas resultantes.</p> + +<h2 id="¿Qué_es_el_espacio_en_blanco">¿Qué es el espacio en blanco?</h2> + +<p>El espacio en blanco es cualquier cadena de texto compuesta solo por espacios, tabulaciones o saltos de línea (para ser precisos, secuencias CRLF, retornos de carro o avances de línea). Estos caracteres te permiten formatear tu código de una manera que lo hará fácilmente legible por ti y otras personas. De hecho, gran parte de nuestro código fuente está lleno de estos caracteres de espacio en blanco, y solo tendemos a deshacernos de ellos en un paso de compilación de producción para reducir el tamaño de descarga del código.</p> + +<h3 id="¿HTML_ignora_en_gran_medida_los_espacios_en_blanco">¿HTML ignora en gran medida los espacios en blanco?</h3> + +<p>En el caso de HTML, los espacios en blanco se ignoran en gran medida: los espacios en blanco entre palabras se tratan como un solo carácter y los espacios en blanco al principio y al final de los elementos y los elementos externos se ignoran. Tomemos el siguiente ejemplo minimalista:</p> + +<h3 class="hidden" id="HTML_largely_ignores_whitespace">HTML largely ignores whitespace?</h3> + +<pre class="brush: html notranslate"><!DOCTYPE html> + + <h1> ¡Hola mundo! </h1></pre> + +<p>{{EmbedLiveSample('HTML_largely_ignores_whitespace')}}</p> + +<p>Este código fuente contiene un par de avances de línea después del <code>DOCTYPE</code> y un montón de caracteres de espacio antes, después y dentro del elemento <code><h1></code>, pero al navegador no parece importarle en absoluto y solo muestra las palabras "¡Hola mundo!" como si estos caracteres no existieran en absoluto:</p> + +<p>Esto es para que los espacios en blanco no afecten el diseño de tu página. Crear espacio alrededor y dentro de los elementos es el trabajo de CSS.</p> + +<h3 id="¿Qué_sucede_con_los_espacios_en_blanco">¿Qué <em>sucede</em> con los espacios en blanco?</h3> + +<p>Sin embargo, no solo desaparecen.</p> + +<p>Cualquier carácter de espacio en blanco que esté fuera de los elementos HTML del documento original se representan en el DOM. Esto es necesario internamente para que el editor pueda preservar el formato de los documentos. Esto significa que:</p> + +<ul> + <li>Habrá algunos nodos de texto que contienen solo espacios en blanco, y</li> + <li>Algunos nodos de texto tendrán espacios en blanco al principio o al final.</li> +</ul> + +<p>Tomemos el siguiente documento, por ejemplo:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> +<head> + <title>Mi Documento</title> +</head> +<body> + <h1>Encabezado</h1> + <p> + Párrafo + </p> +</body> +</html> +</pre> + +<p>El árbol del DOM para esto se ve así:</p> + +<p><img alt="árbol de dom equivalente al ejemplo de HTML anterior" src="https://mdn.mozillademos.org/files/17084/dom-string.png" style="display: block; height: 288px; margin: 0 auto; width: 562px;"></p> + +<p>Conservar caracteres de espacio en blanco en el DOM es útil de muchas maneras, pero hay ciertos lugares donde esto hace que ciertos diseños sean más difíciles de implementar y causa problemas a los desarrolladores que quieren iterar a través de los nodos del DOM. Veremos estas y algunas soluciones más adelante.</p> + +<h3 id="¿CSS_cómo_procesa_los_espacios_en_blanco">¿CSS cómo procesa los espacios en blanco?</h3> + +<p>La mayoría de los espacios en blanco se ignoran, no todos. En el ejemplo anterior, uno de los espacios entre "!Hola" y "mundo!" todavía existe cuando la página se representa en un navegador. Hay reglas en el motor del navegador que deciden qué caracteres de espacio en blanco son útiles y cuáles no; estos se especifican al menos en parte en el <a href="https://www.w3.org/TR/css-text-3">Módulo de texto CSS Nivel 3</a>, y especialmente las partes sobre la <a href="https://www.w3.org/TR/css-text-3/#white-space-property">propiedad <code>white-space</code> en CSS</a> y <a href="https://www.w3.org/TR/css-text-3/#white-space-processing">detalles de procesamiento del espacio en blanco</a>, pero también ofrecemos una explicación más sencilla a continuación.</p> + +<p>Tomemos otro ejemplo realmente simple. Para hacerlo más fácil, ilustramos todos los espacios con ◦, todas las tabulaciones con ⇥ y todos los saltos de línea con ⏎:</p> + +<p>Este ejemplo:</p> + +<pre class="brush: html notranslate"><h1>◦◦◦¡Hola◦⏎ +⇥⇥⇥⇥<span>◦mundo!</span>⇥◦◦</h1></pre> + +<p>se representa en el navegador así:</p> + +<div class="hidden"> +<h4 id="Hidden_example">Hidden example</h4> + +<pre class="brush: html notranslate"><h1> ¡Hola + <span> mundo!</span> </h1></pre> +</div> + +<p>{{EmbedLiveSample('Hidden_example')}}</p> + +<p>El elemento <code><h1></code> contiene solo elementos en línea. De hecho contiene:</p> + +<ul> + <li>Un nodo de texto (que consta de algunos espacios, la palabra "¡Hola" y algunas tabulaciones).</li> + <li>Un elemento en línea (el <code><span></code>, que contiene un espacio, y la palabra "mundo!").</li> + <li>Otro nodo de texto (que consta solo de tabulaciones y espacios).</li> +</ul> + +<p>Debido a esto, establece lo que se llama un {{cssxref("Inline_formatting_context", "contexto de formato en línea")}}. Este es uno de los posibles contextos de representación de diseño con los que funcionan los motores del navegador.</p> + +<p>Dentro de este contexto, el procesamiento de caracteres de espacio en blanco se puede resumir de la siguiente manera:</p> + +<ol> + <li> + <p>Primero, todos los espacios y tabulaciones inmediatamente antes y después de un salto de línea se ignoran, por lo que, si tomamos nuestro marcado de ejemplo anterior y aplicamos esta primera regla, obtenemos:</p> + + <pre class="brush: html notranslate"><h1>◦◦◦¡Hola⏎ +<span>◦mundo!</span>⇥◦◦</h1></pre> + </li> + <li> + <p>A continuación, todos los caracteres de tabulación se tratan como caracteres de espacio, por lo que el ejemplo se convierte en:</p> + + <pre class="brush: html notranslate"><h1>◦◦◦¡Hola⏎ +<span>◦mundo!</span>◦◦◦</h1></pre> + </li> + <li> + <p>A continuación, los saltos de línea se convierten en espacios:</p> + + <pre class="brush: html notranslate"><h1>◦◦◦¡Hola◦<span>◦mundo!</span>◦◦◦</h1></pre> + </li> + <li> + <p>Después de eso, cualquier espacio inmediatamente después de otro espacio (incluso a través de dos elementos en línea separados) se ignora, por lo que terminamos con:</p> + + <pre class="brush: html notranslate"><h1>◦¡Hola◦<span>mundo!</span>◦</h1></pre> + </li> + <li> + <p>Y finalmente, las secuencias de espacios al principio y al final de una línea se eliminan, por lo que eventualmente obtenemos esto:</p> + + <pre class="brush: html notranslate"><h1>¡Hola◦<span>mundo!</span></h1></pre> + </li> +</ol> + +<p>Es por eso que las personas que visitan la página web simplemente verán la frase "¡Hola mundo!" muy bien escrita en la parte superior de la página, en lugar de un "!Hola" con una sangría extraña, seguido de un "mundo!" en la línea debajo de esa.</p> + +<div class="blockIndicator note"> +<p><strong>Nota</strong>: <a href="/es/docs/Tools">Firefox DevTools</a> ha admitido el resaltado de nodos de texto desde la versión 52, lo que facilita ver exactamente qué contenido hay dentro de los nodos de espacios en blanco. Los nodos de espacios en blanco puros están marcados con una etiqueta "<code>whitespace</code>".</p> +</div> + +<h3 id="Espacio_en_blanco_en_contextos_de_formato_de_bloque">Espacio en blanco en contextos de formato de bloque</h3> + +<p>Anteriormente, solo miramos elementos que contienen elementos en línea y contextos de formato en línea. Si un elemento contiene al menos un elemento de bloque, entonces establece lo que se llama un {{cssxref("Block_formatting_context", "contexto de formato de bloque")}}.</p> + +<p>En este contexto, los espacios en blanco se tratan de manera muy diferente. Veamos un ejemplo para explicar cómo. Hemos marcado los espacios en blanco como antes.</p> + +<pre class="brush: html notranslate"><body>⏎ +⇥<div>◦◦¡Hola◦◦</div>⏎ +⏎ +◦◦◦<div>◦◦mundo!◦◦</div>◦◦⏎ +</body></pre> + +<p>Tenemos 3 nodos de texto que contienen solo espacios en blanco, uno antes del primer <code><div></code>, uno entre los 2 <code><div></code>s y uno después del segundo <code><div></code>.</p> + +<p>Esto se renderiza así:</p> + +<div class="hidden"> +<h4 id="Hidden_example_2">Hidden example 2</h4> + +<pre class="brush: html notranslate"><body> + <div> ¡Hola </div> + + <div> mundo! </div> +</body></pre> +</div> + +<p>{{EmbedLiveSample('Hidden_example_2')}}</p> + +<p>Podemos resumir cómo se maneja el espacio en blanco aquí de la siguiente manera (puede haber algunas pequeñas diferencias en el comportamiento exacto entre los navegadores, pero básicamente, esto funciona):</p> + +<ol> + <li> + <p>Debido a que estamos dentro de un contexto de formato de bloque, todo debe ser un bloque, por lo que nuestros 3 nodos de texto también se convierten en bloques, al igual que los 2 <code><div></code>s. Los bloques ocupan todo el ancho disponible y se apilan unos encima de los otros, lo cual significa que terminamos con un diseño compuesto por esta lista de bloques:</p> + + <pre class="brush: html notranslate"><block>⏎⇥</block> +<block>◦◦¡Hola◦◦</block> +<block>⏎◦◦◦</block> +<block>◦◦mundo!◦◦</block> +<block>◦◦⏎</block></pre> + </li> + <li> + <p>Esto luego se simplifica aún más aplicando las reglas de procesamiento para espacios en blanco en contextos de formato en línea a estos bloques:</p> + + <pre class="brush: html notranslate"><block></block> +<block>¡Hola</block> +<block></block> +<block>mundo!</block> +<block></block></pre> + </li> + <li> + <p>Los 3 bloques vacíos que tenemos ahora no van a ocupar ningún espacio en el diseño final, porque no contienen nada, así que terminaremos con solo 2 bloques ocupando espacio en la página. Las personas que visitan la página web ven las palabras "!Hola" y "mundo!" en 2 líneas separadas, ya que esperarías que se distribuyeran 2 <code><div></code>s. El motor del navegador esencialmente ha ignorado todos los espacios en blanco que se agregaron en el código fuente.</p> + </li> +</ol> + +<h2 id="Espacios_entre_elementos_en_línea_y_bloques_en_línea">Espacios entre elementos en línea y bloques en línea</h2> + +<p>Ahora analicemos algunos problemas que pueden surgir debido a los espacios en blanco y qué se puede hacer al respecto. En primer lugar, veremos qué sucede con los espacios entre los elementos en línea y de bloque en línea. De hecho, ya vimos esto en nuestro primer ejemplo, cuando describimos cómo se procesan los espacios en blanco dentro de los contextos de formato en línea.</p> + +<p>Dijimos que había reglas para ignorar la mayoría de los caracteres, pero que los caracteres que separan palabras permanecen. Cuando solo se trata de elementos a nivel de bloque como <code><p></code> que solo contienen elementos en línea como <code><em></code>, <code><strong></code>, <code><span></code>, etc., normalmente no te importa esto porque el espacio en blanco adicional que llega al diseño es útil para separar las palabras en la oración.</p> + +<p>Sin embargo, se vuelve más interesante cuando comienzas a usar elementos <code>inline-block</code>. Estos elementos se comportan como elementos en línea en el exterior y como bloques en el interior, y a menudo se utilizan para mostrar piezas de la IU más complejas que solo texto, una al lado de la otra en la misma línea, por ejemplo, elementos del menú de navegación.</p> + +<p>Debido a que son bloques, muchas personas esperan que se comporten como tales, pero en realidad no es así. Si hay espacios en blanco de formato entre elementos en línea adyacentes, esto dará como resultado un espacio en el diseño, al igual que los espacios entre palabras en el texto.</p> + +<p>Considera este ejemplo (nuevamente, los espacios en blanco en el HTML están marcados para que sean visibles):</p> + +<pre class="brush: css notranslate" id="ef6f">.people-list { + list-style-type: none; + margin: 0; + padding: 0; +} + +.people-list li { + display: inline-block; + width: 2em; + height: 2em; + background: #f06; + border: 1px solid; +} +</pre> + +<pre class="brush: html notranslate" id="24bb"><ul class="people-list">⏎ + +◦◦<li></li>⏎ + +◦◦<li></li>⏎ + +◦◦<li></li>⏎ + +◦◦<li></li>⏎ + +◦◦<li></li>⏎ + +</ul></pre> + +<p>Esto se traduce de la siguiente manera:</p> + +<div class="hidden"> +<h3 id="Hidden_example_3">Hidden example 3</h3> + +<pre class="brush: css notranslate" id="ef6f">.people-list { list-style-type: none; margin: 0; padding: 0; } +.people-list li { display: inline-block; width: 2em; height: 2em; background: #f06; border: 1px solid; } +</pre> + +<pre class="brush: html notranslate" id="24bb"><ul class="people-list"> + + <li></li> + + <li></li> + + <li></li> + + <li></li> + + <li></li> + +</ul></pre> +</div> + +<p>{{EmbedLiveSample('Hidden_example_3')}}</p> + +<p>Probablemente no desees los espacios entre los bloques — dependiendo del caso de uso (¿esta es una lista de avatares o botones de navegación horizontales?), Probablemente desees que los lados del elemento estén alineados entre sí y poder controlar cualquier espacio tú mismo.</p> + +<p>El <em>Inspector HTML de Firefox DevTools</em> resaltará los nodos de texto y también te mostrará exactamente qué áreas están ocupando los elementos, lo que es útil si te preguntas qué está causando el problema y tal vez estés pensando que tienes un margen adicional allí o algo así.</p> + +<p><img alt="Espacio en blanco en Devtools" src="https://mdn.mozillademos.org/files/17085/whitespace-devtools.png" style="border-style: solid; border-width: 1px; height: 454px; width: 797px;"></p> + +<p>Hay algunas formas de solucionar este problema:</p> + +<p>Utiliza <a href="/es/docs/Learn/CSS/CSS_layout/Flexbox">Flexbox</a> para crear la lista horizontal de elementos en lugar de probar una solución de <code>inline-block</code>. Esto se encarga de todo por ti y definitivamente es la solución preferida:</p> + +<pre class="brush: css notranslate">ul { + list-style-type: none; + margin: 0; + padding: 0; + display: flex; +}</pre> + +<p>Si necesitas confiar en <code>inline-block</code>, puedes establecer el {{cssxref("font-size")}} de la lista a 0. Esto solo trabaja si tus bloques no tienen el tamaño <code>ems</code> (según el <code>font-size</code>, por lo que el tamaño del bloque también terminaría siendo 0). <code>rems</code> sería una buena opción aquí:</p> + +<pre class="brush: css notranslate">ul { + font-size: 0; + ... +} + +li { + display: inline-block; + width: 2rem; + height: 2rem; + ... +} +</pre> + +<p>O puedes establecer un margen negativo en los elementos de la lista:</p> + +<pre class="brush: css notranslate">li { + display: inline-block; + width: 2rem; + height: 2rem; + margin-right: -0.25rem; +}</pre> + +<p>También puedes resolver este problema colocando los elementos de tu lista en la misma línea en la fuente, lo cual hace que los nodos de espacios en blanco no se creen en primer lugar:</p> + +<pre class="brush: html notranslate"><li></li><li></li><li></li><li></li><li></li></pre> + +<h2 id="Recorrido_del_DOM_y_el_espacio_en_blanco">Recorrido del DOM y el espacio en blanco</h2> + +<p>Al intentar realizar una manipulación del <a href="/es/docs/Web/API/Document_Object_Model">DOM</a> en JavaScript, también puedes encontrar problemas debido a los nodos de espacios en blanco. Por ejemplo, si tienes una referencia a un nodo padre y deseas afectar su primer elemento hijo usando <a href="/es/docs/Web/API/Node/firstChild"><code>Node.firstChild</code></a>, si hay un nodo de espacio en blanco deshonesto justo después de la etiqueta de apertura principal, no obtendrás el resultado que esperabas. Se seleccionaría el nodo de texto en lugar del elemento al que deseas afectar.</p> + +<p>Veamos otro ejemplo, si tienes un determinado subconjunto de elementos en los que deseas hacer algo en función de si están vacíos (no tienen nodos secundarios) o, no puedes verificar si cada elemento está vacío usando algo como <a href="/es/docs/Web/API/Node/hasChildNodes"><code>Node.hasChildNodes()</code></a>, pero nuevamente, si algún elemento destino contiene nodos de texto, podrías terminar con resultados falsos.</p> + +<h2 id="Funciones_auxiliares_de_espacios_en_blanco">Funciones auxiliares de espacios en blanco</h2> + +<p>El siguiente código JavaScript define varias funciones que facilitan el manejo de espacios en blanco en el DOM:</p> + +<pre class="brush: js notranslate">/** + * En todo, el espacio en blanco se define como uno de los caracteres + * "\t" TAB \u0009 + * "\n" LF \u000A + * "\r" CR \u000D + * " " SPC \u0020 + * + * Esto no usa la "\s" de Javascript porque eso incluye + * espacios irrompibles (y también algunos otros caracteres). + */ + + +/** + * Determina si el contenido de texto de un nodo es completamente de espacios en blanco. + * + * @param nod Un nodo que implementa la interfaz | CharacterData | (es decir, + * un nodo |Text|, |Comment| o |CDATASection| + * @return True si todo el contenido de texto de |nod| es espacio en blanco, + * de lo contrario false. + */ +function is_all_ws( nod ) +{ + // Usa las características de String y RegExp de ECMA-262 Edición 3 + return !(/[^\t\n\r ]/.test(nod.textContent)); +} + + +/** + * Determina si un nodo debe ser ignorado por las funciones del iterador. + * + * @param nod Un objeto implementando la interfaz |Node| de DOM1. + * @return true si el nodo es: + * 1) Un nodo |Text| en que todo es espacio en blanco + * 2) Un nodo |Comment| + * y de lo contrario false. + */ + +function is_ignorable( nod ) +{ + return ( nod.nodeType == 8) || // Un nodo comment + ( (nod.nodeType == 3) && is_all_ws(nod) ); // un nodo text, todo es eeb +} + +/** + * Versión de |previousSibling| que omite los nodos que son completamente + * espacio en blanco o comentarios. (Normalmente |previousSibling| es una propiedad + * de todos los nodos DOM que devuelve el nodo hermano, el nodo que es + * un hijo del mismo padre, que ocurre inmediatamente antes del + * nodo de referencia). + * + * @param sib El nodo de referencia. + * @return O bien: + * 1) El hermano anterior más cercano a |sib| eso no es + * ignorable según |is_ignorable|, o + * 2) null si no existe tal nodo. + */ +function node_before( sib ) +{ + while ((sib = sib.previousSibling)) { + if (!is_ignorable(sib)) return sib; + } + return null; +} + +/** + * Versión de |nextSibling| que omite los nodos que son completamente + * espacio en blanco o comentarios. + * + * @param sib El nodo de referencia. + * @return O bien: + * 1) El hermano más cercano a |sib| eso no es + * ignorable según |is_ignorable|, o + * 2) null si no existe tal nodo. + */ +function node_after( sib ) +{ + while ((sib = sib.nextSibling)) { + if (!is_ignorable(sib)) return sib; + } + return null; +} + +/** + * Versión de |lastChild| que omite los nodos que son completamente + * espacio en blanco o comentarios. (Normalmente |lastChild| es una propiedad + * de todos los nodos del DOM que da el último de los nodos contenidos + * directamente en el nodo de referencia). + * + * @param sib El nodo de referencia. + * @return O bien: + * 1) El último hijo de |sib| eso no es + * ignorable según |is_ignorable|, o + * 2) null si no existe tal nodo. + */ +function last_child( par ) +{ + var res=par.lastChild; + while (res) { + if (!is_ignorable(res)) return res; + res = res.previousSibling; + } + return null; +} + +/** + * Versión de |firstChild| que omite los nodos que son completamente + * espacios en blanco y comentarios. + * + * @param sib El nodo de referencia. + * @return O bien: + * 1) El primer hijo de |sib| eso no es + * ignorable según |is_ignorable|, o + * 2) null si no existe tal nodo. + */ +function first_child( par ) +{ + var res=par.firstChild; + while (res) { + if (!is_ignorable(res)) return res; + res = res.nextSibling; + } + return null; +} + +/** + * Versión de |data| que no incluye espacios en blanco al principio + * y finaliza y normaliza todos los espacios en blanco a un solo espacio. (Normalmente + * |data| es una propiedad de los nodos de texto que proporciona el texto del nodo). + * + * @param txt El nodo de texto cuyos datos se deben devolver + * @return Una cadena que proporciona el contenido del nodo de texto con + * espacios en blanco colapsados. + */ +function data_of( txt ) +{ + var data = txt.textContent; + // Usa las características de String y RegExp de ECMA-262 Edición 3 + data = data.replace(/[\t\n\r ]+/g, " "); + if (data.charAt(0) == " ") + data = data.substring(1, data.length); + if (data.charAt(data.length - 1) == " ") + data = data.substring(0, data.length - 1); + return data; +} +</pre> + +<h3 id="Ejemplo">Ejemplo</h3> + +<p>El siguiente código demuestra el uso de las funciones anteriores. Itera sobre los hijos de un elemento (cuyos hijos son todos elementos) para encontrar aquel cuyo texto es <code>"Este es el tercer párrafo"</code>, y luego cambia el atributo de clase y el contenido de ese párrafo.</p> + +<pre class="brush: js notranslate">var cur = first_child(document.getElementById("test")); +while (cur) +{ + if (data_of(cur.firstChild) == "Este es el tercer párrafo.") + { + cur.className = "magic"; + cur.firstChild.textContent = "Este es el párrafo mágico."; + } + cur = node_after(cur); +} +</pre> diff --git a/files/es/web/api/document/getselection/index.html b/files/es/web/api/documentorshadowroot/getselection/index.html index 6c03b64dcf..6c03b64dcf 100644 --- a/files/es/web/api/document/getselection/index.html +++ b/files/es/web/api/documentorshadowroot/getselection/index.html diff --git a/files/es/web/api/document/pointerlockelement/index.html b/files/es/web/api/documentorshadowroot/pointerlockelement/index.html index cc5d490e5c..cc5d490e5c 100644 --- a/files/es/web/api/document/pointerlockelement/index.html +++ b/files/es/web/api/documentorshadowroot/pointerlockelement/index.html diff --git a/files/es/web/api/document/stylesheets/index.html b/files/es/web/api/documentorshadowroot/stylesheets/index.html index 0458cb3fc9..0458cb3fc9 100644 --- a/files/es/web/api/document/stylesheets/index.html +++ b/files/es/web/api/documentorshadowroot/stylesheets/index.html diff --git a/files/es/web/api/domstring/cadenas_binarias/index.html b/files/es/web/api/domstring/binary/index.html index a52358f62c..a52358f62c 100644 --- a/files/es/web/api/domstring/cadenas_binarias/index.html +++ b/files/es/web/api/domstring/binary/index.html diff --git a/files/es/web/api/element/blur_event/index.html b/files/es/web/api/element/blur_event/index.html new file mode 100644 index 0000000000..b54ad3e6a6 --- /dev/null +++ b/files/es/web/api/element/blur_event/index.html @@ -0,0 +1,156 @@ +--- +title: blur (evento) +slug: Web/Events/blur +tags: + - DOM +translation_of: Web/API/Element/blur_event +--- +<p>El evento <code>blur</code> es disparado cuando un elemento ha perdido su foco. La diferencia principal entre este evento y <code><a href="/en-US/docs/Mozilla_event_reference/focusout">focusout</a></code> es que sólo el último se propaga (bubbles).</p> + +<h2 id="Información_General">Información General</h2> + +<dl> + <dt style="float: left; text-align: right; width: 120px;">Especificación</dt> + <dd style="margin: 0 0 0 120px;"><a class="external" href="http://www.w3.org/TR/DOM-Level-3-Events/#event-type-blur">DOM L3</a></dd> + <dt style="float: left; text-align: right; width: 120px;">Interfaz</dt> + <dd style="margin: 0 0 0 120px;">{{domxref("FocusEvent")}}</dd> + <dt style="float: left; text-align: right; width: 120px;">Burbujas</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Cancelable</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Objetivo</dt> + <dd style="margin: 0 0 0 120px;">Element</dd> + <dt style="float: left; text-align: right; width: 120px;">Acción por defecto</dt> + <dd style="margin: 0 0 0 120px;">Ninguna.</dd> +</dl> + +<p>{{NoteStart}}El valor de {{domxref("Document.activeElement")}} varía a traves de navegadores mientras este evento está siendo manejado ({{bug(452307)}}): IE10 lo agrega al elemento al cual el foco se movera, mientras Firefox y Chrome muy seguido lo agregan al cuerpo del documento.{{NoteEnd}}</p> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Propiedad</th> + <th scope="col">Tipo</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyInline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>Objetivo del evento (elemento DOM)</td> + </tr> + <tr> + <td><code>type</code> {{readonlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>El tipo de evento.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Si el elemento normalmente se propaga o no.</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Si el evento es cancelable o no.</td> + </tr> + <tr> + <td><code>relatedTarget</code> {{readonlyInline}}</td> + <td>{{domxref("EventTarget")}} (DOM element)</td> + <td>null</td> + </tr> + </tbody> +</table> + +<h2 id="Delegación_de_eventos">Delegación de eventos</h2> + +<p>Hay dos maneras de implementar la delegación de eventos para este evento: usando el evento <code>focusout</code> en exploradores que lo soporten, o cambiando el parámetro "useCapture" de <a href="/en-US/docs/DOM/element.addEventListener"><code>addEventListener</code></a> a <code>true</code>:</p> + +<h3 id="Contenido_HTML">Contenido HTML</h3> + +<pre class="brush:html;"><form id="form"> + <input type="text" placeholder="text input"> + <input type="password" placeholder="password"> +</form></pre> + +<h3 id="Contenido_JavaScript">Contenido JavaScript</h3> + +<pre class="brush: js">var form = document.getElementById("form"); +form.addEventListener("focus", function( event ) { + event.target.style.background = "pink"; +}, true); +form.addEventListener("blur", function( event ) { + event.target.style.background = ""; +}, true);</pre> + +<p>{{EmbedLiveSample('Delegación_de_eventos')}}</p> + +<h2 id="Compatibilidad_en_navegadores">Compatibilidad en navegadores</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>5</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}<sup>[1]</sup></td> + <td>6</td> + <td>12.1</td> + <td>5.1</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Android</th> + <th>Chrome para Android</th> + <th>Edge</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>4.0</td> + <td>53</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>10.0</td> + <td>12.1</td> + <td>5.1</td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Antes de Gecko 24 {{geckoRelease(24)}} la interfaz para este evento era {{domxref("Event")}}, no {{domxref("FocusEvent")}}. Vea ({{bug(855741)}}).</p> + +<h2 id="Eventos_relacionados">Eventos relacionados</h2> + +<ul> + <li>{{event("focus")}}</li> + <li>{{event("blur")}}</li> + <li>{{event("focusin")}}</li> + <li>{{event("focusout")}}</li> +</ul> diff --git a/files/es/web/api/element/name/index.html b/files/es/web/api/element/name/index.html deleted file mode 100644 index c970ea8947..0000000000 --- a/files/es/web/api/element/name/index.html +++ /dev/null @@ -1,80 +0,0 @@ ---- -title: Element.name -slug: Web/API/Element/name -tags: - - API - - Compatibilidad de los navegadores - - DOM - - Elemento - - Propiedad - - Referencia - - Web - - actualizacion -translation_of: Web/API -translation_of_original: Web/API/Element/name ---- -<p>{{ APIRef("DOM") }}</p> - -<h2 id="Summary" name="Summary">Sumario</h2> - -<p><code><strong>name</strong></code> <span id="result_box" lang="es"><span>obtiene o establece</span> <span>la</span> <span>propiedad del nombre</span> <span>de un</span> <span>objeto DOM</span><span>;</span> <span>sólo se aplica a</span> <span>los</span> <span>siguientes elementos</span><span>:</span></span> {{ HTMLelement("a") }}, {{ HTMLelement("applet") }}, {{ HTMLelement("button") }}, {{ HTMLelement("form") }}, {{ HTMLelement("frame") }}, {{ HTMLelement("iframe") }}, {{ HTMLelement("img") }}, {{ HTMLelement("input") }}, {{ HTMLelement("map") }}, {{ HTMLelement("meta") }}, {{ HTMLelement("object") }}, {{ HTMLelement("param") }}, {{ HTMLelement("select") }}, and {{ HTMLelement("textarea") }}.</p> - -<div class="note"> -<p><strong>Nota:</strong> <code>La propiedad name no esixte para otros elementos</code>; a diferencia de <a href="/en/DOM/Element.tagName" title="en/DOM/element.tagName"><code>tagName</code></a> y <a href="/en/DOM/Node.nodeName" title="en/DOM/Node.nodeName"><code>nodeName</code></a>, no es una propiedad de los modos de comunicación (interfaces) {{domxref("Node")}}, {{domxref("Element")}} or {{domxref("HTMLElement")}}.</p> -</div> - -<p><code>name</code> puede ser utilizado en el método{{ domxref("document.getElementsByName()") }} , en una <a href="/en/DOM/HTMLFormElement" title="en/DOM/form">configuración</a> y con la colección de <a href="/en/DOM/form.elements" title="en/DOM/form.elements">elementos</a> de la configuración. cuando utilizamos una configuración o elementos de una colección, puede devolver un solo elemento o una colección.</p> - -<h2 id="Syntax" name="Syntax">Síntasix</h2> - -<pre class="eval"><em>HTMLElement</em>.name = <em>string</em>; -var elName = <em>HTMLElement</em>.name; - -var fControl = <em>HTMLFormElement</em>.<em>elementName</em>; -var controlCollection = <em>HTMLFormElement</em>.elements.<em>elementName</em>; -</pre> - -<h2 id="Example" name="Example">Ejemplo</h2> - -<pre class="eval"><form action="" name="formA"> - <input type="text" value="foo"> -</form> - -<script type="text/javascript"> - - // Get a reference to the first element in the form - var formElement = document.forms['formA'].elements[0]; - - // Give it a name - formElement.name = 'inputA'; - - // Show the value of the input - alert(document.forms['formA'].elements['inputA'].value); - -</script> -</pre> - -<h2 id="Notes" name="Notes">Notas</h2> - -<p>En Internet Explorer (IE), la propiedad <code>name</code> de los objetos DOM , creada utilizando{{ domxref("document.createElement()") }} no puede ser establecida o modificada</p> - -<h2 id="Specification" name="Specification">Especificaciones</h2> - -<p>W3C DOM 2 HTML Specification:</p> - -<ul> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-32783304">Anchor</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-39843695">Applet</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-34812697">Button</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-22051454">Form</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-91128709">Frame</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-96819659">iFrame</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-47534097">Image</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-89658498">Input</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-52696514">Map</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-31037081">Meta</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-20110362">Object</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-59871447">Param</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-41636323">Select</a></li> - <li><a class="external" href="http://www.w3.org/TR/DOM-Level-2-HTML/html.html#ID-70715578">Textarea</a></li> -</ul> diff --git a/files/es/web/api/htmlelement/style/index.html b/files/es/web/api/elementcssinlinestyle/style/index.html index 62c8903b72..62c8903b72 100644 --- a/files/es/web/api/htmlelement/style/index.html +++ b/files/es/web/api/elementcssinlinestyle/style/index.html diff --git a/files/es/web/api/fetch_api/conceptos_basicos/index.html b/files/es/web/api/fetch_api/basic_concepts/index.html index 8c02021de6..8c02021de6 100644 --- a/files/es/web/api/fetch_api/conceptos_basicos/index.html +++ b/files/es/web/api/fetch_api/basic_concepts/index.html diff --git a/files/es/web/api/fetch_api/utilizando_fetch/index.html b/files/es/web/api/fetch_api/using_fetch/index.html index 51617ad047..51617ad047 100644 --- a/files/es/web/api/fetch_api/utilizando_fetch/index.html +++ b/files/es/web/api/fetch_api/using_fetch/index.html diff --git a/files/es/web/api/xmlhttprequest/formdata/index.html b/files/es/web/api/formdata/index.html index 2ca830daf7..2ca830daf7 100644 --- a/files/es/web/api/xmlhttprequest/formdata/index.html +++ b/files/es/web/api/formdata/index.html diff --git a/files/es/web/api/formdata/using_formdata_objects/index.html b/files/es/web/api/formdata/using_formdata_objects/index.html new file mode 100644 index 0000000000..13f4c9635a --- /dev/null +++ b/files/es/web/api/formdata/using_formdata_objects/index.html @@ -0,0 +1,137 @@ +--- +title: Usando Objetos FormData +slug: Web/Guide/Usando_Objetos_FormData +translation_of: Web/API/FormData/Using_FormData_Objects +translation_of_original: Web/Guide/Using_FormData_Objects +--- +<p>Los objetos <code><a href="/es/docs/XMLHttpRequest/FormData" title="en/DOM/XMLHttpRequest/FormData">FormData</a> </code>le permiten compilar un conjunto de pares clave/valor para enviar mediante <code>XMLHttpRequest</code>. Están destinados principalmente para el envío de los datos del formulario, pero se pueden utilizar de forma independiente con el fin de transmitir los datos tecleados. Los datos transmitidos estarán en el mismo formato que usa el método <code>submit() </code>del formulario para enviar los datos si el tipo de codificación del formulario se establece en "multipart/form-data".</p> + +<h2 id="Creación_de_un_objeto_FormData_desde_cero">Creación de un objeto FormData desde cero</h2> + +<p>Usted mismo puede construir un objeto <code>FormData</code> instanciándolo y después añadiendo campos a la instancia usando su método <a href="/en/DOM/XMLHttpRequest/FormData#append()" title="en/XMLHttpRequest/FormData#append()"><code>append()</code></a> , tal y como se muestra:</p> + +<pre class="brush: js">var formData = new FormData(); + +<span style="line-height: normal;">formData</span>.append("username", "Groucho"); +<span style="line-height: normal;">formData</span>.append("accountnum", 123456); // number 123456 is immediately converted to string "123456" + +// HTML file input user's choice... +<span style="line-height: normal;">formData</span>.append("userfile", fileInputElement.files[0]); + +// JavaScript file-like object... +var content = '<a id="a"><b id="b">hey!</b></a>'; // the body of the new file... +var blob = new Blob([<span style="line-height: normal;">content</span><span style="line-height: normal;">], { type: "text/xml"});</span> + +formData.append("webmasterfile", <span style="line-height: normal;">blob</span><span style="line-height: normal;">);</span> + +var request = new XMLHttpRequest(); +<span style="line-height: normal;">request</span>.open("POST", "http://foo.com/submitform.php"); +<span style="line-height: normal;">request</span>.send(formData); +</pre> + +<div class="note"><strong>Nota:</strong> Los campos "userfile" y "webmasterfile" contienen ambos un archivo. El número asignado al campo "accountnum" es inmediatamente convertido a string por el método <a href="/en/DOM/XMLHttpRequest/FormData#append()" title="en/XMLHttpRequest/FormData#append()"><code>FormData.append()</code></a> (el valor del campo puede ser un {{ domxref("Blob") }}, {{ domxref("File") }}, o una cadena de texto; <strong>si el valor no es ni un Blob, ni un File, será convertido a un string</strong>).</div> + +<p>Este ejemplo construye una instancia de <code>FormData</code> que almacenará los valores de los campos "username", "accountnum", "userfile" y "webmasterfile", entonces usará el método <a href="/en/DOM/XMLHttpRequest#send()" title="en/XMLHttpRequest#send()"><code>send()</code></a> de <code>XMLHttpRequest</code> para enviar los datos del formulario. El campo "webmasterfile" es un <a href="/en/DOM/Blob" title="en/DOM/Blob"><code>Blob</code></a>. Un objeto <a href="/en/DOM/Blob" title="en/DOM/Blob"><code>Blob</code></a> representa un objeto de tipo similar a un fichero que es inalterable y que almacenará datos en formato raw. Los Blobs representan datos que no necesariamente tendrán un formato Javascript nativo. La interfaz {{ domxref("File") }} está basada en <a href="/en/DOM/Blob" title="en/DOM/Blob"><code>Blob</code></a>, y hereda su funcionalidad y la amplía para dar soporte a archivos que estén en el sistema del usuario. Para construir un <code><a href="/en/DOM/Blob" title="en/DOM/Blob">Blob</a></code>, puede invocar <a href="/en/DOM/Blob#Constructor" title="en/DOM/Blob#Constructor"><code>al constructor del objeto Blob</code></a>.</p> + +<h2 id="Recuperando_un_objeto_FormData_de_un_formulario_HTML">Recuperando un objeto FormData de un formulario HTML </h2> + +<p>Para construir un objeto <code>FormData</code> que contenga los datos de un {{ HTMLElement("form") }} existente, especifique ese elemento form cuando cree el objeto <code>FormData</code>:</p> + +<pre class="brush: js">var <span style="line-height: normal;">formData</span><span style="line-height: normal;"> = new FormData(someFormElement);</span> +</pre> + +<p>Por ejemplo:</p> + +<pre class="brush: js">var formElement = document.getElementById("myFormElement"); +var request = new XMLHttpRequest(); +<span style="line-height: normal;">request</span>.open("POST", "submitform.php"); +<span style="line-height: normal;">request</span>.send(new FormData(formElement)); +</pre> + +<p>También puede añadir datos adicionales al objeto <code>FormData</code> antes de enviarlo. Así:</p> + +<pre class="brush: js">var formElement = document.getElementById("myFormElement"); +formData = new FormData(formElement); +formData.append("serialnumber", serialNumber++); +<span style="line-height: normal;">request</span>.send(formData);</pre> + +<p>Esto le permite aumentar los datos del formulario antes de enviarlos para incluir información adicional que no necesariamente debiera ser editable por el usuario en el formulario.</p> + +<h2 id="Enviando_archivos_usando_objetos_FormData">Enviando archivos usando objetos FormData</h2> + +<p>También puede enviar archivos usando <code>FormData</code>. Simplemente incluye un elemento {{ HTMLElement("input") }} de tipo {{ domxref("File") }}:</p> + +<pre class="brush: html"><form enctype="multipart/form-data" method="post" name="fileinfo"> + <label>Your email address:</label> + <input type="email" autocomplete="on" autofocus name="userid" placeholder="email" required size="32" maxlength="64" /><br /> + <label>Custom file label:</label> + <input type="text" name="filelabel" size="12" maxlength="32" /><br /> + <label>File to stash:</label> + <input type="file" name="file" required /> + <input type="submit" value="Stash the file!" /> +</form> +<div id="output"></div> +</pre> + +<p>Luego puede enviarlo usando código como el siguiente:</p> + +<pre class="brush: js">var form = document.forms.namedItem("fileinfo"); +form.addEventListener('submit', function(ev) { + + var + oOutput = document.getElementById("output"), + oData = new FormData(document.forms.namedItem("fileinfo")); + + oData.append("CustomField", "This is some extra data"); + + var oReq = new XMLHttpRequest(); + oReq.open("POST", "stash.php", true); + oReq.onload = function(oEvent) { + if (oReq.status == 200) { + oOutput.innerHTML = "Uploaded!"; + } else { + oOutput.innerHTML = "Error " + oReq.status + " occurred uploading your file.<br \/>"; + } + }; + + oReq.send(oData); + ev.preventDefault(); +}, false); +</pre> + +<div class="note"> +<p><strong>Nota</strong>: el método especificado en el formulario será usado por encima del método utilizado en en la llamada a open().</p> +</div> + +<p>También puede añadir un {{ domxref("File") }} o un {{ domxref("Blob") }} directamente al objeto {{ domxref("XMLHttpRequest/FormData", "FormData") }} de la siguiente manera:</p> + +<pre class="brush: js">data.append("myfile", myBlob, "filename.txt"); +</pre> + +<p>Cuando se usa el método <code>append</code> es posible usar, de manera opcional, un tercer parámetro para pasarle un nombre de fichero dentro de la cabecera <code>Content-Disposition </code>que será enviada al servidor. Cuando no se especifica (o el parámetro no es soportado), el nombre "blob" es el que será utilizado.</p> + +<p>Además, puede usar FormData con jQuery si asigna las opciones correctas:</p> + +<pre class="brush: js">var fd = new FormData(document.getElementById("fileinfo")); +fd.append("CustomField", "This is some extra data"); +$.ajax({ + url: "stash.php", + type: "POST", + data: fd, + processData: false, // tell jQuery not to process the data + contentType: false // tell jQuery not to set contentType +}); +</pre> + +<h2 id="Envío_de_formularios_y_carga_de_archivos_vía_AJAX_sin_objetos_FormData">Envío de formularios y carga de archivos vía AJAX <em>sin</em> objetos <code style="font-size: 30px; font-weight: 700;">FormData</code></h2> + +<p>Si quiere saber cómo serializar y enviar vía <a href="/en-US/docs/AJAX" title="/en-US/docs/AJAX">AJAX</a> un formulario <em>sin </em>utilizar objetos FormData, por favor leer <a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files" title="/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files">este párrafo</a> .</p> + +<h2 id="Vea_también">Vea también</h2> + +<ul> + <li><a href="/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest" title="/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest">Usando XMLHttpRequest</a></li> + <li><a href="/en-US/docs/DOM/HTMLFormElement" title="/en-US/docs/DOM/HTMLFormElement"><code>HTMLFormElement</code></a></li> + <li><a href="/en-US/docs/DOM/Blob" title="/en-US/docs/DOM/Blob"><code>Blob</code></a></li> + <li><a href="/en-US/docs/JavaScript/Typed_arrays" title="/en-US/docs/JavaScript/Typed_arrays">Typed Arrays</a></li> +</ul> diff --git a/files/es/web/api/geolocation_api/index.html b/files/es/web/api/geolocation_api/index.html new file mode 100644 index 0000000000..6d50972f8b --- /dev/null +++ b/files/es/web/api/geolocation_api/index.html @@ -0,0 +1,232 @@ +--- +title: Uso de geolocalización +slug: WebAPI/Using_geolocation +tags: + - API + - Geolocalización + - Guía + - clearWatch + - watchPosition +translation_of: Web/API/Geolocation_API +--- +<p>{{securecontext_header}}{{APIRef("Geolocation API")}}</p> + +<p><span id="result_box" lang="es"><span class="hps">La</span> <strong><span class="hps">API de geolocalización</span></strong> <span class="hps">permite al</span> <span class="hps">usuario compartir su</span> <span class="hps">ubicación</span> <span class="hps">a las aplicaciones web</span> <span class="hps">si</span> <span class="hps">así lo desea.</span> <span class="hps">Por razones de privacidad</span><span>,</span> <span class="hps">al usuario</span> <span class="hps">se le pide que</span> <span class="hps">confirme el permiso</span> <span class="hps">para proporcionar información</span> <span class="hps">de ubicación.</span></span></p> + +<h2 id="El_objeto_geolocation">El objeto geolocation</h2> + +<p><span id="result_box" lang="es"><span class="hps">La API</span> <span class="hps">de geolocalización</span> <span class="hps">se publica</span> <span class="hps">a través del objeto </span></span>{{domxref("window.navigator.geolocation","navigator.geolocation")}}.</p> + +<p><span id="result_box" lang="es"><span class="hps">Si el objeto existe</span><span>,</span> <span class="hps">los servicios de geolocalización</span> <span class="hps">están disponibles.</span> <span class="hps">Se puede</span> <span class="hps">comprobar la presencia</span> <span class="hps">de la geolocalización</span> <span class="hps">de esta manera:</span></span></p> + +<pre class="brush: js">if ("geolocation" in navigator) { + /* la geolocalización está disponible */ +} else { + /* la geolocalización NO está disponible */ +} +</pre> + +<div class="blockIndicator note"> +<p>Nota: En Firefox 24 y versiones anteriores, <code>"geolocation" in navigator</code> siempre retornaba <code>true</code> incluso si la API se encontraba deshabilitada. Esto ha sido corregido en <a href="https://www.fxsitecompat.com/en-CA/versions/25/">Firefox 25</a> para cumplir con la especificación. ({{bug(884921)}}).</p> +</div> + +<h3 id="Obtención_de_la_ubicación_actual">Obtención de la ubicación actual</h3> + +<p><span lang="es"><span class="hps">Para</span> <span class="hps">obtener la ubicación</span> <span class="hps">actual del usuario</span><span>, puede llamar a</span><span class="atn hps">l método </span></span>{{domxref("window.navigator.geolocation.getCurrentPosition()","getCurrentPosition()")}}<span lang="es"><span class="hps">.</span></span></p> + +<p><span lang="es"><span class="hps">Esto inicia</span> <span class="hps">una solicitud asíncrona</span> <span class="hps">para detectar</span> <span class="hps">la posición del usuario</span><span>, y</span> <span class="hps">consulta el</span> <span class="hps">hardware</span> <span class="hps">de posicionamiento para</span> <span class="hps">obtener</span><span class="hps"> información actualizada.</span> </span><span id="result_box" lang="es"><span class="hps">Cuando</span> <span class="hps">se determina la posición</span><span>, se ejecuta la función</span> <span class="hps">de callback</span><span class="hps">.</span></span><span lang="es"> <span class="hps">Si lo desea,</span> <span class="hps">puede proporcionar otra función de callback</span><span class="hps"> que se</span> <span class="hps">ejecuta si</span> <span class="hps">se produce un error</span><span>.</span> <span class="hps">Un tercer</span> <span class="hps">parámetro</span> <span class="hps">opcional</span><span>, es un</span> <span class="hps">objeto de opciones</span> <span class="hps">donde se puede establecer</span> <span class="hps">la edad máxima de</span> <span class="hps">la</span> <span class="hps">posición devuelta</span><span>,</span> <span class="hps">el tiempo de espera</span> <span class="hps">para una solicitud</span> <span class="hps">y si se requiere</span> <span class="hps">una alta precisión</span> <span class="hps">para la posición.</span></span></p> + +<div class="note"> +<p><strong>Nota:</strong> Por defecto, {{domxref("window.navigator.geolocation.getCurrentPosition()","getCurrentPosition()")}} intenta responder tan rápido como sea posible con un resultado de baja precisión. Es útil cuando se necesita una respuesta rápida sin importar su exactitud. A los dispositivos con GPS, por ejemplo, les puede tomar más de un minuto obtener una posición, por lo que datos menos precisos (localización por IP o wifi) pueden ser devueltos por {{domxref("window.navigator.geolocation.getCurrentPosition()","getCurrentPosition()")}}.</p> +</div> + +<pre class="brush: js">navigator.geolocation.getCurrentPosition(function(position) { + haz_algo(position.coords.latitude, position.coords.longitude); +});</pre> + +<p>En el ejemplo anterior la función do_something() será ejecutada una vez que se obtiene la posición.</p> + +<h3 id="Rastreando_la_posición_actual">Rastreando la posición actual</h3> + +<p>Si los datos de ubicación cambian (si el dispositivo se mueve o información geográfica más precisa es recibida), puede definir una función de callback que se ejecuta al cambiar la posición. Esto se logra a través de la función {{domxref("window.navigator.geolocation.watchPosition()","watchPosition()")}}, que recibe los mismos parámetros que {{domxref("window.navigator.geolocation.getCurrentPosition()","getCurrentPosition()")}}. La función de callback es ejecutada varias veces, permitiendo al navegador actualizar la ubicación cada vez que cambia, o proporcionar una posición con mayor exactitud utilizando distintas técnicas de geolocalización. La función de callback de error, la cual es opcional como en {{domxref("window.navigator.geolocation.getCurrentPosition()","getCurrentPosition()")}}, es llamada solo una vez, cuando nunca serán devueltos resultados correctos.</p> + +<div class="note"> +<p><strong>Nota:</strong> Es posible usar la función {{domxref("window.navigator.geolocation.watchPosition()","watchPosition()")}} sin haber ejecutado antes {{domxref("window.navigator.geolocation.getCurrentPosition()","getCurrentPosition()")}}.</p> +</div> + +<pre class="brush: js">var watchID = navigator.geolocation.watchPosition(function(position) { + do_something(position.coords.latitude, position.coords.longitude); +});</pre> + +<p>El método {{domxref("window.navigator.geolocation.watchPosition()","watchPosition()")}} devuelve un número que se utiliza para identificar el rastreador de posición solicitado; este valor se utiliza junto con el método {{domxref("window.navigator.geolocation.clearWatch()","clearWatch()")}} para dejar de rastrear la posición del usuario.</p> + +<pre class="brush: js">navigator.geolocation.clearWatch(watchID); +</pre> + +<h3 id="Afinando_la_respuesta">Afinando la respuesta</h3> + +<p>Ambos métodos, {{domxref("window.navigator.geolocation.getCurrentPosition()","getCurrentPosition()")}} y {{domxref("window.navigator.geolocation.watchPosition()","watchPosition()")}} aceptan una función de callback en caso de éxito, una función callback opcional si ocurre algún error, y un objeto <code>PositionOptions</code> también opcional.</p> + +<p>{{page("/en-US/docs/DOM/window.navigator.geolocation.getCurrentPosition","PositionOptions")}}</p> + +<p>Una llamada a {{domxref("window.navigator.geolocation.watchPosition()","watchPosition")}} luce como el siguiente ejemplo:</p> + +<pre class="brush: js">function geo_success(position) { + do_something(position.coords.latitude, position.coords.longitude); +} + +function geo_error() { + alert("Sorry, no position available."); +} + +var geo_options = { + enableHighAccuracy: true, + maximumAge : 30000, + timeout : 27000 +}; + +var wpid = navigator.geolocation.watchPosition(geo_success, geo_error, geo_options);</pre> + +<p><a id="fck_paste_padding">Demo de watchPosition: </a><a class="external" href="http://www.thedotproduct.org/experiments/geo/">http://www.thedotproduct.org/experiments/geo/</a><br> + <a id="fck_paste_padding"></a></p> + +<h2 id="Describiendo_una_posición">Describiendo una posición</h2> + +<p>La ubicación del usuario es descrita con un objeto <code>Position</code> referenciando a un objeto <code>Coordinates</code>.</p> + +<p>{{page("/en-US/docs/DOM/window.navigator.geolocation.getCurrentPosition","Position")}}</p> + +<p>{{page("/en-US/docs/DOM/window.navigator.geolocation.getCurrentPosition","Coordinates")}}</p> + +<h2 id="Manejo_de_errores">Manejo de errores</h2> + +<p>La función de callback de error, si existe cuando se llama a <code>getCurrentPosition()</code> o <code>watchPosition()</code>, recibe un objeto <code>PositionError</code> como su primer parámetro.</p> + +<pre class="brush: js">function errorCallback(error) { + alert('ERROR(' + error.code + '): ' + error.message); +}; +</pre> + +<p>{{page("/en-US/docs/DOM/window.navigator.geolocation.getCurrentPosition","PositionError")}}</p> + +<h2 id="Ejemplo_de_geolocalización">Ejemplo de geolocalización</h2> + +<div class="hidden"> +<pre class="brush: css">body { + padding: 20px; + background-color:#ffffc9 +} + +p { margin : 0; } +</pre> +</div> + +<h3 id="Contenido_HTML">Contenido HTML</h3> + +<pre class="brush: html;"><p><button onclick="geoFindMe()">Show my location</button></p> +<div id="out"></div> +</pre> + +<h3 id="Contenido_JavaScript">Contenido JavaScript</h3> + +<pre class="brush: js;">function geoFindMe() { + var output = document.getElementById("out"); + + if (!navigator.geolocation){ + output.innerHTML = "<p>Geolocation is not supported by your browser</p>"; + return; + } + + function success(position) { + var latitude = position.coords.latitude; + var longitude = position.coords.longitude; + + output.innerHTML = '<p>Latitude is ' + latitude + '° <br>Longitude is ' + longitude + '°</p>'; + + var img = new Image(); + img.src = "http://maps.googleapis.com/maps/api/staticmap?center=" + latitude + "," + longitude + "&zoom=13&size=300x300&sensor=false"; + + output.appendChild(img); + }; + + function error() { + output.innerHTML = "Unable to retrieve your location"; + }; + + output.innerHTML = "<p>Locating…</p>"; + + navigator.geolocation.getCurrentPosition(success, error); +} +</pre> + +<h3 id="Resultado">Resultado</h3> + +<p>{{ EmbedLiveSample('Geolocation_Live_Example',350,410) }}</p> + +<h2 id="Compatibilidad_entre_navegadores">Compatibilidad entre navegadores</h2> + +<p>{{ CompatibilityTable() }}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>5</td> + <td>{{CompatGeckoDesktop("1.9.1")}}</td> + <td>9</td> + <td>10.60</td> + <td>5</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>{{CompatUnknown()}}</td> + <td>{{CompatUnknown()}}</td> + <td>{{CompatGeckoMobile("4")}}</td> + <td>{{CompatUnknown()}}</td> + <td>10.60</td> + <td>{{CompatUnknown()}}</td> + </tr> + </tbody> +</table> +</div> + +<h3 id="Notas_sobre_Gecko">Notas sobre Gecko</h3> + +<p>Firefox incluye soporte para localizar basándose en información de redes inalámbricas, usando Google Location Services. En la transacción entre Firefox y Google, los datos son compartidos incluyendo información del punto de acceso inalámbrico, un token de acceso (similar a una cookie con duración de dos semanas), y la dirección IP del usuario. Para más información, por favor consulte la <a href="http://www.mozilla.com/en-US/legal/privacy/" title="http://www.mozilla.com/en-US/legal/privacy/">Política de Privacidad de Mozilla</a><span class="external"> y la</span> <a href="http://www.google.com/privacy-lsf.html" title="http://www.google.com/privacy-lsf.html">Política de Privacidad de Google</a>, dichos documentos cubren como estos datos pueden ser utilizados.</p> + +<p>En Firefox 3.6 (Gecko 1.9.2) fue añadido soporte para utilizar el servicio <a href="http://catb.org/gpsd/" title="http://catb.org/gpsd/">GPSD</a> para geolocalización en sistemas Linux.</p> + +<h2 id="Consultar_también">Consultar también</h2> + +<ul> + <li>{{domxref("window.navigator.geolocation","navigator.geolocation")}}</li> + <li><a href="http://www.w3.org/TR/geolocation-API/" title="http://www.w3.org/TR/geolocation-API/">API de Geolocalización en w3.org</a></li> + <li><a href="/en-US/demos/tag/tech:geolocation" title="/en-US/demos/tag/tech:geolocation">Demos que utilizan la API de Geolocalización</a></li> +</ul> + +<p> </p> diff --git a/files/es/web/api/element/ongotpointercapture/index.html b/files/es/web/api/globaleventhandlers/ongotpointercapture/index.html index 3023c3758e..3023c3758e 100644 --- a/files/es/web/api/element/ongotpointercapture/index.html +++ b/files/es/web/api/globaleventhandlers/ongotpointercapture/index.html diff --git a/files/es/web/api/element/onlostpointercapture/index.html b/files/es/web/api/globaleventhandlers/onlostpointercapture/index.html index 9a07506d45..9a07506d45 100644 --- a/files/es/web/api/element/onlostpointercapture/index.html +++ b/files/es/web/api/globaleventhandlers/onlostpointercapture/index.html diff --git a/files/es/web/api/element/onwheel/index.html b/files/es/web/api/globaleventhandlers/onwheel/index.html index b8f829969b..b8f829969b 100644 --- a/files/es/web/api/element/onwheel/index.html +++ b/files/es/web/api/globaleventhandlers/onwheel/index.html diff --git a/files/es/web/api/history_api/example/index.html b/files/es/web/api/history_api/example/index.html new file mode 100644 index 0000000000..1971f1348f --- /dev/null +++ b/files/es/web/api/history_api/example/index.html @@ -0,0 +1,415 @@ +--- +title: Ejemplo de Navegación usando Ajax +slug: DOM/Manipulando_el_historial_del_navegador/Ejemplo +translation_of: Web/API/History_API/Example +--- +<p>This is an example of an AJAX web site composed only of three pages (<em>first_page.php</em>, <em>second_page.php</em> and <em>third_page.php</em>). To see how it works, please, create the following files (or git clone <a href="https://github.com/giabao/mdn-ajax-nav-example" title="/en-US/docs/">https://github.com/giabao/mdn-ajax-nav-example.git</a> ):</p> + +<div class="note" id="const_compatibility"><strong>Note:</strong> For fully integrating the {{HTMLElement("form")}} elements within this <em>mechanism</em>, please take a look at the paragraph <a href="/en-US/docs/Web/API/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files">Submitting forms and uploading files</a>.</div> + +<p><strong>first_page.php</strong>:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: php"><?php + $page_title = "First page"; + + $as_json = false; + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + $as_json = true; + ob_start(); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>first_page.php</strong>.</p> + +<div id="ajax-content"> +<?php } ?> + + <p>This is the content of <strong>first_page.php</strong>.</p> + +<?php + if ($as_json) { + echo json_encode(array("page" => $page_title, "content" => ob_get_clean())); + } else { +?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>first_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> + +<p><strong>second_page.php</strong>:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: php"><?php + $page_title = "Second page"; + + $as_json = false; + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + $as_json = true; + ob_start(); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>second_page.php</strong>.</p> + +<div id="ajax-content"> +<?php } ?> + + <p>This is the content of <strong>second_page.php</strong>.</p> + +<?php + if ($as_json) { + echo json_encode(array("page" => $page_title, "content" => ob_get_clean())); + } else { +?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>second_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> + +<p><strong>third_page.php</strong>:</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: php"><?php + $page_title = "Third page"; + $page_content = "<p>This is the content of <strong>third_page.php</strong>. This content is stored into a php variable.</p>"; + + if (isset($_GET["view_as"]) && $_GET["view_as"] == "json") { + echo json_encode(array("page" => $page_title, "content" => $page_content)); + } else { +?> +<!doctype html> +<html> +<head> +<?php + include "include/header.php"; + echo "<title>" . $page_title . "</title>"; +?> +</head> + +<body> + +<?php include "include/before_content.php"; ?> + +<p>This paragraph is shown only when the navigation starts from <strong>third_page.php</strong>.</p> + +<div id="ajax-content"> +<?php echo $page_content; ?> +</div> + +<p>This paragraph is shown only when the navigation starts from <strong>third_page.php</strong>.</p> + +<?php + include "include/after_content.php"; + echo "</body>\n</html>"; + } +?> +</pre> +</div> + +<p><strong>css/style.css</strong>:</p> + +<pre class="brush: css">#ajax-loader { + position: fixed; + display: table; + top: 0; + left: 0; + width: 100%; + height: 100%; +} + +#ajax-loader > div { + display: table-cell; + width: 100%; + height: 100%; + vertical-align: middle; + text-align: center; + background-color: #000000; + opacity: 0.65; +} +</pre> + +<p><strong>include/after_content.php</strong>:</p> + +<pre class="brush: php"><p>This is the footer. It is shared between all ajax pages.</p> +</pre> + +<p><strong>include/before_content.php</strong>:</p> + +<pre class="brush: php"><p> +[ <a class="ajax-nav" href="first_page.php">First example</a> +| <a class="ajax-nav" href="second_page.php">Second example</a> +| <a class="ajax-nav" href="third_page.php">Third example</a> +| <a class="ajax-nav" href="unexisting.php">Unexisting page</a> ] +</p> + +</pre> + +<p><strong>include/header.php</strong>:</p> + +<pre class="brush: php"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> +<script type="text/javascript" src="js/ajax_nav.js"></script> +<link rel="stylesheet" href="css/style.css" /> +</pre> + +<p><strong>js/ajax_nav.js</strong>:</p> + +<p>(before implementing it in a working environment, <strong>please read <a href="#const_compatibility" title="Note about *const* compatibility">the note about the const statement compatibility</a></strong>)</p> + +<div style="height: 400px; margin-bottom: 12px; overflow: auto;"> +<pre class="brush: js">"use strict"; + +const ajaxRequest = new (function () { + + function closeReq () { + oLoadingBox.parentNode && document.body.removeChild(oLoadingBox); + bIsLoading = false; + } + + function abortReq () { + if (!bIsLoading) { return; } + oReq.abort(); + closeReq(); + } + + function ajaxError () { + alert("Unknown error."); + } + + function ajaxLoad () { + var vMsg, nStatus = this.status; + switch (nStatus) { + case 200: + vMsg = JSON.parse(this.responseText); + document.title = oPageInfo.title = vMsg.page; + document.getElementById(sTargetId).innerHTML = vMsg.content; + if (bUpdateURL) { + history.pushState(oPageInfo, oPageInfo.title, oPageInfo.url); + bUpdateURL = false; + } + break; + default: + vMsg = nStatus + ": " + (oHTTPStatus[nStatus] || "Unknown"); + switch (Math.floor(nStatus / 100)) { + /* + case 1: + // Informational 1xx + console.log("Information code " + vMsg); + break; + case 2: + // Successful 2xx + console.log("Successful code " + vMsg); + break; + case 3: + // Redirection 3xx + console.log("Redirection code " + vMsg); + break; + */ + case 4: + /* Client Error 4xx */ + alert("Client Error #" + vMsg); + break; + case 5: + /* Server Error 5xx */ + alert("Server Error #" + vMsg); + break; + default: + /* Unknown status */ + ajaxError(); + } + } + closeReq(); + } + + function filterURL (sURL, sViewMode) { + return sURL.replace(rSearch, "") + ("?" + sURL.replace(rHost, "&").replace(rView, sViewMode ? "&" + sViewKey + "=" + sViewMode : "").slice(1)).replace(rEndQstMark, ""); + } + + function getPage (sPage) { + if (bIsLoading) { return; } + oReq = new XMLHttpRequest(); + bIsLoading = true; + oReq.onload = ajaxLoad; + oReq.onerror = ajaxError; + if (sPage) { oPageInfo.url = filterURL(sPage, null); } + oReq.open("get", filterURL(oPageInfo.url, "json"), true); + oReq.send(); + oLoadingBox.parentNode || document.body.appendChild(oLoadingBox); + } + + function requestPage (sURL) { + if (history.pushState) { + bUpdateURL = true; + getPage(sURL); + } else { + /* Ajax navigation is not supported */ + location.assign(sURL); + } + } + + function processLink () { + if (this.className === sAjaxClass) { + requestPage(this.href); + return false; + } + return true; + } + + function init () { + oPageInfo.title = document.title; + for (var oLink, nIdx = 0, nLen = document.links.length; nIdx < nLen; document.links[nIdx++].onclick = processLink); + } + + const + + /* customizable constants */ + sTargetId = "ajax-content", sViewKey = "view_as", sAjaxClass = "ajax-nav", + + /* not customizable constants */ + rSearch = /\?.*$/, rHost = /^[^\?]*\?*&*/, rView = new RegExp("&" + sViewKey + "\\=[^&]*|&*$", "i"), rEndQstMark = /\?$/, + oLoadingBox = document.createElement("div"), oCover = document.createElement("div"), oLoadingImg = new Image(), + oPageInfo = { + title: null, + url: location.href + }, oHTTPStatus = /* http://www.iana.org/assignments/http-status-codes/http-status-codes.xml */ { + 100: "Continue", + 101: "Switching Protocols", + 102: "Processing", + 200: "OK", + 201: "Created", + 202: "Accepted", + 203: "Non-Authoritative Information", + 204: "No Content", + 205: "Reset Content", + 206: "Partial Content", + 207: "Multi-Status", + 208: "Already Reported", + 226: "IM Used", + 300: "Multiple Choices", + 301: "Moved Permanently", + 302: "Found", + 303: "See Other", + 304: "Not Modified", + 305: "Use Proxy", + 306: "Reserved", + 307: "Temporary Redirect", + 308: "Permanent Redirect", + 400: "Bad Request", + 401: "Unauthorized", + 402: "Payment Required", + 403: "Forbidden", + 404: "Not Found", + 405: "Method Not Allowed", + 406: "Not Acceptable", + 407: "Proxy Authentication Required", + 408: "Request Timeout", + 409: "Conflict", + 410: "Gone", + 411: "Length Required", + 412: "Precondition Failed", + 413: "Request Entity Too Large", + 414: "Request-URI Too Long", + 415: "Unsupported Media Type", + 416: "Requested Range Not Satisfiable", + 417: "Expectation Failed", + 422: "Unprocessable Entity", + 423: "Locked", + 424: "Failed Dependency", + 425: "Unassigned", + 426: "Upgrade Required", + 427: "Unassigned", + 428: "Precondition Required", + 429: "Too Many Requests", + 430: "Unassigned", + 431: "Request Header Fields Too Large", + 500: "Internal Server Error", + 501: "Not Implemented", + 502: "Bad Gateway", + 503: "Service Unavailable", + 504: "Gateway Timeout", + 505: "HTTP Version Not Supported", + 506: "Variant Also Negotiates (Experimental)", + 507: "Insufficient Storage", + 508: "Loop Detected", + 509: "Unassigned", + 510: "Not Extended", + 511: "Network Authentication Required" + }; + + var + + oReq, bIsLoading = false, bUpdateURL = false; + + oLoadingBox.id = "ajax-loader"; + oCover.onclick = abortReq; + oLoadingImg.src = "data:image/gif;base64,R0lGODlhEAAQAPIAAP///wAAAMLCwkJCQgAAAGJiYoKCgpKSkiH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAADMwi63P4wyklrE2MIOggZnAdOmGYJRbExwroUmcG2LmDEwnHQLVsYOd2mBzkYDAdKa+dIAAAh+QQJCgAAACwAAAAAEAAQAAADNAi63P5OjCEgG4QMu7DmikRxQlFUYDEZIGBMRVsaqHwctXXf7WEYB4Ag1xjihkMZsiUkKhIAIfkECQoAAAAsAAAAABAAEAAAAzYIujIjK8pByJDMlFYvBoVjHA70GU7xSUJhmKtwHPAKzLO9HMaoKwJZ7Rf8AYPDDzKpZBqfvwQAIfkECQoAAAAsAAAAABAAEAAAAzMIumIlK8oyhpHsnFZfhYumCYUhDAQxRIdhHBGqRoKw0R8DYlJd8z0fMDgsGo/IpHI5TAAAIfkECQoAAAAsAAAAABAAEAAAAzIIunInK0rnZBTwGPNMgQwmdsNgXGJUlIWEuR5oWUIpz8pAEAMe6TwfwyYsGo/IpFKSAAAh+QQJCgAAACwAAAAAEAAQAAADMwi6IMKQORfjdOe82p4wGccc4CEuQradylesojEMBgsUc2G7sDX3lQGBMLAJibufbSlKAAAh+QQJCgAAACwAAAAAEAAQAAADMgi63P7wCRHZnFVdmgHu2nFwlWCI3WGc3TSWhUFGxTAUkGCbtgENBMJAEJsxgMLWzpEAACH5BAkKAAAALAAAAAAQABAAAAMyCLrc/jDKSatlQtScKdceCAjDII7HcQ4EMTCpyrCuUBjCYRgHVtqlAiB1YhiCnlsRkAAAOwAAAAAAAAAAAA=="; + oCover.appendChild(oLoadingImg); + oLoadingBox.appendChild(oCover); + + onpopstate = function (oEvent) { + bUpdateURL = false; + oPageInfo.title = oEvent.state.title; + oPageInfo.url = oEvent.state.url; + getPage(); + }; + + window.addEventListener ? addEventListener("load", init, false) : window.attachEvent ? attachEvent("onload", init) : (onload = init); + + // Public methods + + this.open = requestPage; + this.stop = abortReq; + this.rebuildLinks = init; + +})(); +</pre> +</div> + +<div class="note" id="const_compatibility"><strong>Note:</strong> The current implementation of <a href="/en/JavaScript/Reference/Statements/const" title="en/JavaScript/Reference/Statements/const"><code>const</code></a> (constant statement) <strong>is not part of ECMAScript 5</strong>. It is supported in Firefox & Chrome (V8) and partially supported in Opera 9+ and Safari. <strong>It is not supported in Internet Explorer 6-9, or in the preview of Internet Explorer 10</strong>. <a href="/en/JavaScript/Reference/Statements/const" title="en/JavaScript/Reference/Statements/const"><code>const</code></a> is going to be defined by ECMAScript 6, but with different semantics. Similar to variables declared with the <a href="/en/JavaScript/Reference/Statements/let" title="en/JavaScript/Reference/Statements/let"><code>let</code></a> statement, constants declared with <a href="/en/JavaScript/Reference/Statements/const" title="en/JavaScript/Reference/Statements/const"><code>const</code></a> will be block-scoped. <strong>We used it only for didactic purpose. If you want a full browser compatibility of this library, please replace all the <a href="/en/JavaScript/Reference/Statements/const" title="en/JavaScript/Reference/Statements/const"><code>const</code></a> statements with the <a href="/en/JavaScript/Reference/Statements/var" title="en/JavaScript/Reference/Statements/var"><code>var</code></a> statements.</strong></div> + +<p>For more information, please see: <a href="/en-US/docs/DOM/Manipulating_the_browser_history" title="/en-US/docs/DOM/Manipulating_the_browser_history">Manipulating the browser history</a>.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{ domxref("window.history") }}</li> + <li>{{ domxref("window.onpopstate") }}</li> +</ul> diff --git a/files/es/web/api/history_api/index.html b/files/es/web/api/history_api/index.html new file mode 100644 index 0000000000..eb2c0b3fdd --- /dev/null +++ b/files/es/web/api/history_api/index.html @@ -0,0 +1,228 @@ +--- +title: Manipulando el historial del navegador +slug: DOM/Manipulando_el_historial_del_navegador +tags: + - HTML5 + - historial + - para_revisar +translation_of: Web/API/History_API +--- +<p>El objeto DOM {{ domxref("window") }} proporciona acceso al historial del navegador a través del objeto {{ domxref("window.history", "history") }} . Este da acceso a métodos y propiedades útiles que permiten avanzar y retroceder a través del historial del usuario, así como --a partir de HTML5-- manipular el contenido del historial.</p> + +<h2 id="Viajando_a_través_del_historial">Viajando a través del historial</h2> + +<p>Retroceder y avanzar a través del historial del usuario utilizando los métodos <code>back()</code>, <code>forward()</code> y <code>go()</code>.</p> + +<h3 id="Moviéndose_hacia_adelante_y_hacia_atrás">Moviéndose hacia adelante y hacia atrás</h3> + +<p>Para moverte hacia atrás, solo debes hacer:</p> + +<pre>window.history.back(); +</pre> + +<p>Esto actuará exactamente como si el usuario hiciera clic en el botón "atrás" en la barra de herramientas del navegador.</p> + +<p>De manera similar, puedes moverte hacia adelante (como si el usuario hiciera clic en en el botón "adelante"), de esta forma:</p> + +<pre>window.history.forward(); +</pre> + +<h3 id="Moverse_a_un_punto_específico_del_historial">Moverse a un punto específico del historial</h3> + +<p>Puedes usar el método <code>go()</code> para cargar una página desde el historial de la sesión, identificada por su poscición relativa a la página actual (Siendo la página actual, por supuesto, relativa al índice 0).</p> + +<p>Para moverse atrás una página (equivalente a llamar <code>back()</code>):</p> + +<pre><code>window.history.go(-1);</code> +</pre> + +<p>Para moverse una página hacia adelante, como si se llamara a <code>forward()</code>:</p> + +<pre><code>window.history.go(1);</code> +</pre> + +<p>De manera similar, puedes avanzar 2 páginas pasando 2 y así sucesivamente.</p> + +<p>Otro uso para <code>go()</code> es el de actualizar la página ya sea pasando <code>0</code> como parámetro o ninguno.</p> + +<pre><code>// Cada una de las siguientes +// instrucciones actualiza la página +window.history.go(0); +window.history.go();</code></pre> + +<p>Puedes obtener el número de páginas en la pila del historial consultando el valor de la propiedad <span class="long_text" id="result_box" lang="es"><span title=""><code>length</code>:</span></span></p> + +<pre>var numeroDeEntradas = window.history.length; +</pre> + +<div class="note"><strong>Nota:</strong> Internet Explorer admite el paso de cadenas de URL como parámetro para <code>go()</code>; esto no es estándar y no está implementado en Gecko.</div> + +<h2 id="Añadiendo_y_modificando_entradas_del_historial">Añadiendo y modificando entradas del historial</h2> + +<p>{{ gecko_minversion_header("2") }}</p> + +<p>HTML5 introduce los métodos <code>history.pushState()</code> y <code>history.replaceState()</code>, los cuales te permiten añadir y modificar entradas del historial, respectivamente. Estos métodos trabajan en conjunto con el evento {{ domxref("window.onpopstate") }}.</p> + +<p>Hacer uso de <code>history.pushState()</code> cambia el referer que es utilizado en la cabecera HTTP por los objetos <a href="/es/docs/XMLHttpRequest">XMLHttpRequest</a> que hayan sido creados luego de cambiar el estado. El referer utilizará la URL del documento cuyo objeto window sea <code>this</code> al momento de la creación del objeto <a href="/es/docs/XMLHttpRequest">XMLHttpRequest</a>.</p> + +<h3 id="Ejemplo">Ejemplo</h3> + +<p>Supongamos que <span class="nowiki">http://mozilla.org/foo.html</span> ejecuta el siguiente JavaScript:</p> + +<pre>var stateObj = { foo: "bar" }; +history.pushState(stateObj, "page 2", "bar.html"); +</pre> + +<p>Esto causará que la barra de URL muestre <span class="nowiki">http://mozilla.org/bar.html</span>, pero no provocará que el navegador carge bar.html ni tampoco que verifique si bar.html existe.</p> + +<p>Supongamos ahora que el usuario navega hacia <span class="nowiki">http://google.com</span>, y despúes hace clic en Atrás. En este punto, la barra de URL mostrará <span class="nowiki">http://mozilla.org/bar.html</span>, y la página tendrá un evento <code>popstate</code> cuyo <em>state object</em> contiene una copia de <code>stateObj</code>. La página en si se verá como <code>foo.html</code>, aunque la página podria modificar su contenido durante el evento <code>popstate</code> event.</p> + +<p>Si hacemos clic en "atrás" nuevamente, la URL cambiará a <span class="nowiki">http://mozilla.org/foo.html</span>, y el documento generará otro evento <code>popstate</code> event, esta vez con un state object nulo. Aquí también, ir atrás no cambia el contenido del documento con respecto al paso anterior, aunque el documento permite actualizar su contenido manualmente después de recibir el evento <code>popstate</code>.</p> + +<h3 id="El_método_pushState()">El método pushState()</h3> + +<p><code>pushState()</code> toma tres parámetros: un objeto estado, un título (el cual es normalmente ignorado) y (opcionalmente) una URL. Vamos a examinar cada uno de estos tres parametros en más detalle:</p> + +<ul> + <li> + <p><strong>object estado</strong> — El objeto estado es un objeto JavaScript el cual esta asociado con la nueva entrada al historial creada por <code>pushState()</code>. Cada vez que el usuario navega hacia un nuevo estado, un evento <code>popstate</code> event se dispara, y la propiedad <code>state</code> del evento contiene una copia del historial de entradas del objeto estado.</p> + + <p>El objeto estado puede ser cualquier cosa que puedas pasar a <code>JSON.stringify</code>. Dado que Firefox guarda los objetos estado en el disco del usuario para que puedan ser restaurados después de que el usuario reinicie su navegador, se ha impuesto un tamaño límite de 640K caracteres en representación JSON de un objeto estado. Si pasas un objeto estado cuya representación es más larga que esto a <code>pushState()</code>, el método arrojará una excepción. Si necesitas más espacio, se recomienda usar <code>sessionStorage</code> y/o <code>localStorage</code>.</p> + </li> + <li> + <p><strong>título</strong> — Firefox actualmente ignora este parámetro, aunque podría usarse en el futuro. Pasar una cadena de caracteres vacia aquí podría asegurar estar a salvo de futuros cambios en este método. Alternativamente podrías pasar un título corto del estado hacia el cual te estás moviendo.</p> + </li> + <li> + <p><strong>URL</strong> — La URL de la nueva entrada al historial está dada por este parámetro. Recuerda que el browser no intentará cargar esta URL después de llamar a <code>pushState()</code>, <span class="long_text" id="result_box" lang="es"><span title="">pero podría intentar cargar la URL más tarde, por ejemplo, después de que el usuario reinicie su navegador</span></span>. La nueva URL no necesita ser absoluta; si es relativa, es resuelta relativamente a la actual URL. La nueva URL debe ser del mismo origen que la actual URL. Si no es así, <code>pushState()</code> arrojará una excepción. Este parámetro es opcional; <span class="long_text" id="result_box" lang="es"><span title="">si no se especifica, se tomará la URL actual del documento.</span></span></p> + </li> +</ul> + +<p>En un sentido, llamar <code>pushState()</code> es similar a asignar <code>window.location = "#foo"</code>, <span class="long_text" id="result_box" lang="es"><span title="">en tanto que también se va a crear y activar otra entrada al historial asociada con el documento actual</span></span>. Pero <code>pushState()</code> tiene las siguientes ventajas:</p> + +<ul> + <li>La nueva URL puede ser cualquier URL en el mismo origen de la actual URL. En contraste, asignar <code>window.location</code> te mantiene en el mismo {{ domxref("document") }} solamente si modificas unicamente el hash.</li> + <li>No hay por qué cambiar la URL si no se desea. Por el contrario, asignar <code>window.location = "#foo"; solamente crea una nueva entrada en el historial si el hash actual no es </code><code>#foo</code>.</li> + <li>Puedes asociar datos arbitrarios con tu nuevo historial de entrada. Con el enfoque hash-based, tu necesitas codificar todos datos relevantes dentro de una cadena de caracteres corta.</li> + <li>Si <code>title</code> es utilizado por los navegadores, estos datos pueden utilizarse (independientemente de, por ejemplo, el hash).</li> +</ul> + +<p>Hay que tener en cuenta que <code>pushState()</code> nunca dispara un evento <code>hashchange</code>, incluso si la nueva URL difiere de la antigua URL únicamente en su hash.</p> + +<p>En un documento XUL, crea el elemento XUL específico.</p> + +<p>En otros documentos, crea un elemento con un namespace de URI nulo (<code>null</code>).</p> + +<h3 id="El_método_replaceState()">El método replaceState()</h3> + +<p><code>history.replaceState()</code> trabaja exactamente igual a <code>history.pushState()</code> excepto que <code>replaceState()</code> modifica la entrada al historial actual en lugar de crear una nueva.</p> + +<p><code>replaceState()</code> es particularmente útil si deseas actualizar el objeto estado o la URL del la actual entrada al historial en respuesta a alguna acción del usuario.</p> + +<h3 id="El_evento_popstate">El evento popstate</h3> + +<p>Un evento <code>popstate</code> es dirigido a la ventana cada vez que la entrada al historial cambia. Si la entrada al historial es activada y fue creada por un llamado a <code>pushState</code> o afectada por una llamada a <code>replaceState</code>, la propiedad state del evento <code>popstate</code> contiene una copia del historial de entradas del objeto estado.</p> + +<p>Ver {{ domxref("window.onpopstate") }} para un ejemplo de uso.</p> + +<h3 id="Leyendo_el_estado_actual">Leyendo el estado actual</h3> + +<p>Cuando la página carga, debería tener un objeto de estado no nulo. Esto podría ocurrir, por ejemplo, si la página establece un object de estado (usando <code>pushState()</code> o <code>replaceState()</code>) y entonces el usuario reinicia su navegador. Cuando la página carga de nuevo, la página recibirá el evento onload, pero no el evento popstate. Sin embargo, si lees la propiedad history.state, obtendrás el objeto estado que habrías tenido si se hubiera lanzado el evento apopstate.</p> + +<p>Puedes leer el estado del historial actual sin tener que esperar un evento <code>popstate</code> usando la propiedad <code>history.state</code> de esta manera:</p> + +<pre><code>var currentState = history.state;</code></pre> + +<h2 id="Ejemplos">Ejemplos</h2> + +<p>Para un ejemplo completo de un sitio AJAX, ver: <a href="https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history/Example" title="/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history/Example">Ejemplo de navegación AJAX</a>.</p> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table> + <tbody> + <tr> + <th scope="col">Especificación</th> + <th scope="col">Estado </th> + <th scope="col">Comentario</th> + </tr> + <tr> + <td>{{SpecName('HTML WHATWG', "browsers.html#history", "History")}}</td> + <td>{{Spec2('HTML WHATWG')}}</td> + <td>No hay cambios desde {{SpecName("HTML5 W3C")}}.</td> + </tr> + <tr> + <td>{{SpecName('HTML5 W3C', "browsers.html#history", "History")}}</td> + <td>{{Spec2('HTML5 W3C')}}</td> + <td>Definición inicial</td> + </tr> + </tbody> +</table> + +<h2 id="Compatibilidad_entre_navegadores">Compatibilidad entre navegadores</h2> + +<p>{{ CompatibilityTable() }}</p> + +<table> + <tbody> + <tr> + <th>Característica</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>replaceState, pushState</td> + <td>5</td> + <td>{{ CompatGeckoDesktop("2.0") }}</td> + <td>10</td> + <td>11.50</td> + <td>5.0</td> + </tr> + <tr> + <td>history.state</td> + <td>18</td> + <td>{{ CompatGeckoDesktop("2.0") }}</td> + <td>10</td> + <td>11.50</td> + <td>6.0</td> + </tr> + </tbody> +</table> + +<table> + <tbody> + <tr> + <th>Característica</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>replaceState, pushState</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + <tr> + <td>history.state</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + </tr> + </tbody> +</table> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li>{{ domxref("window.history") }}</li> + <li>{{ domxref("window.onpopstate") }}</li> +</ul> diff --git a/files/es/web/api/html_drag_and_drop_api/file_drag_and_drop/index.html b/files/es/web/api/html_drag_and_drop_api/file_drag_and_drop/index.html new file mode 100644 index 0000000000..1225072b01 --- /dev/null +++ b/files/es/web/api/html_drag_and_drop_api/file_drag_and_drop/index.html @@ -0,0 +1,117 @@ +--- +title: Drag & Drop archivo +slug: DragDrop/Drag_and_Drop/drag_and_drop_archivo +tags: + - Guía + - arrastra y suelta + - drag and drop + - drop zone + - zona de arrastre +translation_of: Web/API/HTML_Drag_and_Drop_API/File_drag_and_drop +--- +<p>{{DefaultAPISidebar("HTML Drag and Drop API")}}</p> + +<p>Las interfaces Drag-and-Drop posibilitan arrastrar y soltar archivos en una página web. En este documento se describe cómo una aplicación puede aceptar uno, o más, archivos que son arrastrados desde el <em>explorador de archivos </em>de la plataforma y soltados en una página web.</p> + +<p>Los pasos principales para configurar Drag-and-drop son: 1) definir una "zona drop (<em>drop zone), </em>es decir, definir un elemento donde se podrá soltar el archivo; y 2) definir funciones para la gestión de los eventos {{event("drop")}} y {{event("dragover")}}. Estos pasos se describen a continuación, tambien se incluyen ejemplos snippets de código. El código fuente completo está disponible en el <a href="https://github.com/mdn/dom-examples/tree/master/drag-and-drop">repositorio drag-and-drop de MDN</a> (cualquier sugerencia o tema que revisar es bienvenido).</p> + +<p class="note">Nota: {{domxref("HTML_Drag_and_Drop_API","HTML drag and drop")}} define 2 diferentes APIs para soportar drag and drop de archivos. Una API es la interfaz {{domxref("DataTransfer")}} y la segunda API son las interfaces {{domxref("DataTransferItem")}} y {{domxref("DataTransferItemList")}}. Este ejemplo ilustra el uso de ambas APIs (y no usa ninguna interfaz específica de Gecko).</p> + +<h2 id="Define_la_zona_drop_drop_zone">Define la zona "drop" [drop <em>zone</em>]</h2> + +<p>Es necesario configurar un evento {{event("drop")}} en el objeto sobre el cual se soltará el objeto arrastrado. Este evento llamará una función global {{domxref("GlobalEventHandlers.ondrop","ondrop")}} que recibe los datos del objeto arrastrado. El siguiente código muestra cómo se hace con un elemento {{HTMLelement("div")}}:</p> + +<pre class="brush: html notranslate"><div id="drop_zone" ondrop="dropHandler(event);"> + <p>Arrastra y suelta uno o más archivos a esta zona ...</p> +</div></pre> + +<p>Normalmente, una aplicación incluirá una función de gestión de eventos {{event("dragover")}} en el elemento objetivo del arrastre y esa función desactivará el comportamiento de arrastre por defecto del browser. Para añadir esta función necesita incluir una función global {{domxref("GlobalEventHandlers.ondragover","ondragover")}}:</p> + +<pre class="brush: html notranslate"><div id="drop_zone" ondrop="dropHandler(event);" ondragover="dragOverHandler(event);"> + <p>Arrastra y suelta uno o más archivos a esta zona ...</p> +</div> +</pre> + +<p>Por último, puede que una aplicación quiera personalizar el estilo del elemento objetivo del arrastre para indicar visualmente que es una zona drag and drop. En este ejemplo, el elemento objetivo usa el siguiente estilo:</p> + +<pre class="brush: css notranslate">#drop_zone { + border: 5px solid blue; + width: 200px; + height: 100px; +} +</pre> + +<div class="note"> +<p>Fíjese que los eventos <code>dragstart</code> y <code>dragend</code> no son activados cuando se arrastra un archivo al browser desde el SO.</p> +</div> + +<h2 id="Procesar_la_acción_de_soltar_drop">Procesar la acción de soltar [drop]</h2> + +<p>El evento {{event("drop")}} se ejecuta cuando el usuario suelta el o los archivos. En el siguiente manejador, si el navegador sorporta la interfaz {{domxref("DataTransferItemList")}} , el método {{domxref("DataTransferItem.getAsFile","getAsFile()")}} se utiliza para acceder cada fichero; de lo contrario la propiedad {{domxref("DataTransfer")}} de la interfaz {{domxref("DataTransfer.files","files")}} es usada para acceder cada archivo.</p> + +<p>El ejemplo siguiente muestra como escribir el nombre de cada fichero arrastrado en la consola. En una aplicación <em>real</em>, se querrá procesar un archivo usando {{domxref("File","File API")}}.</p> + +<p>Nótese que en este ejemplo, cualquier item arrastrado que no sea un archivo es ignorado.</p> + +<pre class="brush: js notranslate">function dropHandler(ev) { + console.log('Fichero(s) arrastrados'); + + // Evitar el comportamiendo por defecto (Evitar que el fichero se abra/ejecute) + ev.preventDefault(); + + if (ev.dataTransfer.items) { + // Usar la interfaz DataTransferItemList para acceder a el/los archivos) + for (var i = 0; i < ev.dataTransfer.items.length; i++) { + // Si los elementos arrastrados no son ficheros, rechazarlos + if (ev.dataTransfer.items[i].kind === 'file') { + var file = ev.dataTransfer.items[i].getAsFile(); + console.log('... file[' + i + '].name = ' + file.name); + } + } + } else { + // Usar la interfaz DataTransfer para acceder a el/los archivos + for (var i = 0; i < ev.dataTransfer.files.length; i++) { + console.log('... file[' + i + '].name = ' + ev.dataTransfer.files[i].name); + } + } + + // Pasar el evento a removeDragData para limpiar + removeDragData(ev) +}</pre> + +<h2 id="Prevenir_el_comportamiento_default_de_arrastrado_en_el_browser">Prevenir el comportamiento default de arrastrado en el browser </h2> + +<p>El siguiente evento {{event("dragover")}} llama a {{domxref("Event.preventDefault","preventDefault()")}} para deshabilitar (turn off) la respuesta estandar drag-and-drop del browser.</p> + +<pre class="brush: js notranslate">function dragOverHandler(ev) { + console.log('File(s) in drop zone'); + + // Prevent default behavior (Prevent file from being opened) + ev.preventDefault(); +} +</pre> + +<h2 id="Limpieza_Cleanup">Limpieza (Cleanup)</h2> + +<p>Typically, an application may want to perform some cleanup by deleting the file drag data. In this example, the drop event is passed along from drop handler to a custom function called removeDragData. If the browser supports the {{domxref("DataTransferItemList")}} interface, the list's {{domxref("DataTransferItemList.clear","clear()")}} method is used to delete the file drag data; otherwise the {{domxref("DataTransfer")}} object's {{domxref("DataTransfer.clearData","clearData()")}} method is used to delete the data.</p> + +<pre class="brush: js notranslate">function removeDragData(ev) { + console.log('Removing drag data') + + if (ev.dataTransfer.items) { + // Use DataTransferItemList interface to remove the drag data + ev.dataTransfer.items.clear(); + } else { + // Use DataTransfer interface to remove the drag data + ev.dataTransfer.clearData(); + } +} +</pre> + +<h2 id="See_also" name="See_also">See also</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/HTML_Drag_and_Drop_API">HTML Drag and Drop API</a></li> + <li><a class="internal" href="/Web/Guide/HTML/Drag_operations" title="Drag Operations">Drag Operations</a></li> + <li><a href="https://html.spec.whatwg.org/multipage/interaction.html#dnd" title="Drag and Drop Standard">HTML5 Living Standard: Drag and Drop</a></li> +</ul> diff --git a/files/es/web/api/html_drag_and_drop_api/index.html b/files/es/web/api/html_drag_and_drop_api/index.html new file mode 100644 index 0000000000..82e069ed48 --- /dev/null +++ b/files/es/web/api/html_drag_and_drop_api/index.html @@ -0,0 +1,57 @@ +--- +title: Arrastrar y soltar +slug: DragDrop/Drag_and_Drop +tags: + - HTML5 + - XUL +translation_of: Web/API/HTML_Drag_and_Drop_API +--- +<p>Firefox y otras aplicaciones de Mozilla admiten una serie de características para gestionar la funcionalidad de arrastrar y soltar. Esto le permite al usuario hacer clic y mantener presionado el botón del ratón/mouse sobre un elemento, arrastrarlo a otra ubicación y soltarlo para colocar el elemento allí. Al puntero le seguirá una representación transparente de lo que se está arrastrando durante la operación. La ubicación de destino puede ser una aplicación diferente. Sitios web, extensiones y aplicaciones XUL pueden hacer uso de esta funcionalidad para personalizar los elementos que pueden ser arrastrados, evaluar la operación, así como especificar el lugar donde los elementos se pueden soltar.</p> +<div class="note"> Esta sección trata sobre la funcionalidad de arrastrar y soltar en Firefox 3.5 (Gecko 1.9.1) y versiones posteriores. Consulta la <a href="/en-US/docs/Drag_and_Drop" title="/en-US/docs/Drag_and_Drop">documentación de la API anterior</a> para Firefox 3.0 y versiones anteriores.</div> + + +<h2 id="Elementos_básicos_de_arrastrar_y_soltar">Elementos básicos de arrastrar y soltar</h2> +<p>Cuando comienza una operación de arrastre, se puede proporcionar una serie de datos:</p> +<ul> + <li>los datos que se van a arrastrar, que pueden ser de varios formatos diferentes. Por ejemplo, datos de texto que contienen una cadena de texto que se va a arrastrar. Para obtener más información al respecto, consulta <a href="/en-US/docs/DragDrop/Drag_Operations#dragdata" title="/en-US/docs/DragDrop/Drag_Operations#dragdata">Datos de la operación de arrastre</a> .</li> + <li>la imagen de confirmación sobre la operación de arrastre que aparece junto al puntero durante la operación. Esta imagen puede personalizarse, sin embargo, la mayoría de las veces, no se especifica y se genera una imagen por defecto basándose en el elemento donde se ha pulsado el ratón/mouse. Para obtener más información acerca de estas imágenes, consulta <a href="/en-US/docs/DragDrop/Drag_Operations#dragfeedback" title="/en-US/docs/DragDrop/Drag_Operations#dragfeedback">Configurar la imagen de confirmación sobre la operación de descarga</a> .</li> + <li>efectos de arrastre que se permiten. Son posibles tres efectos: <code>copy</code> para indicar que los datos que se arrastran se copiarán desde su ubicación actual a la ubicación de destino, <code>move</code> para indicar que los datos que se arrastran serán movidos y <code>link</code> para indicar que se creará algún tipo de relación o conexión entre la ubicación actual y la ubicación de destino. Durante la operación, se pueden modificar los efectos de arrastre y especificar cuáles en concreto se permiten en determinadas ubicaciones. Si se permite, se puede realizar una operación de colocación en esa ubicación. Consulta <a href="/en-US/docs/DragDrop/Drag_Operations#drageffects" title="/en-US/docs/DragDrop/Drag_Operations#drageffects">Efectos de arrastre</a> para obtener más detalles.</li> +</ul> +<p>Mozilla y Firefox admiten una serie de características que no se encuentran en el modelo estándar de arrastrar y soltar. Estas te permiten arrastrar elementos múltiples y arrastrar datos que no son cadenas. Para obtener más información, consulta <a href="/en-US/docs/DragDrop/Dragging_and_Dropping_Multiple_Items" title="/en-US/docs/DragDrop/Dragging_and_Dropping_Multiple_Items">Arrastrar y soltar múltiples elementos</a> .</p> +<p>Para obtener una lista de tipos de datos comunes utilizados para arrastrar y soltar, consulta <a href="/en-US/docs/DragDrop/Recommended_Drag_Types" title="/en-US/docs/DragDrop/Recommended_Drag_Types">Tipos de operaciones de arrastre recomendados</a>.</p> +<p>Está disponible una referencia rápida para los procedimientos recomendados en la operación de arrastre de los siguientes tipos de elementos:</p> +<ul> + <li><a href="/en-US/docs/DragDrop/Recommended_Drag_Types#text" title="/en-US/docs/DragDrop/Recommended_Drag_Types#text">Texto</a></li> + <li><a href="/en-US/docs/DragDrop/Recommended_Drag_Types#link" title="/en-US/docs/DragDrop/Recommended_Drag_Types#link">Enlaces</a></li> + <li><a href="/en-US/docs/DragDrop/Recommended_Drag_Types#html" title="/en-US/docs/DragDrop/Recommended_Drag_Types#html">HTML y XML</a></li> + <li><a href="/en-US/docs/DragDrop/Recommended_Drag_Types#file" title="/en-US/docs/DragDrop/Recommended_Drag_Types#file">Archivos</a></li> + <li><a href="/en-US/docs/DragDrop/Recommended_Drag_Types#image" title="/en-US/docs/DragDrop/Recommended_Drag_Types#image">Imágenes</a></li> + <li><a href="/en-US/docs/DragDrop/Recommended_Drag_Types#node" title="/en-US/docs/DragDrop/Recommended_Drag_Types#node">Nodos de documento</a></li> +</ul> +<p>Consulta <a href="/en-US/docs/DragDrop/DataTransfer" title="/en-US/docs/DragDrop/DataTransfer">DataTransfer</a> para tener una referencia al objeto DataTransfer.</p> + + +<h2 id="events" name="events">Eventos de arrastre</h2> +<p>Se utilizan una serie de eventos que se ejecutan durante las diversas etapas de la operación de arrastre y colocación. Ten en cuenta que se ejecutan sólo los eventos de arrastre, los eventos del ratón/mouse como <code>mousemove</code> no se ejecutan durante una operación de arrastre.</p> +<p>La propiedad <a href="/en-US/docs/DragDrop/DataTransfer" title="/en-US/docs/DragDrop/DataTransfer">dataTransfer</a> de todos los eventos de arrastre contiene datos sobre la operación de arrastre y colocación.</p> + + +<dl> + <dt>dragstart</dt> + <dd>Se ejecuta sobre un elemento cuando se inicia una operación de arrastre. El usuario está solicitando arrastrar el elemento al que dispara el evento dragstart. Durante este evento, un proceso de escucha ajustará cierto tipo de información como los datos de la operación de arrastre y la imagen que se asocia con ella. Para obtener más información al respecto, consulta <a href="/en-US/docs/DragDrop/Drag_Operations#dragstart" title="/en-US/docs/DragDrop/Drag_Operations#dragstart">Inicio de una operación de arrastre</a> .</dd> + <dt>dragenter</dt> + <dd>Se dispara cuando el ratón/mouse se mueve primero sobre un elemento, mientras está teniendo lugar una operación de arrastre. Un proceso de escucha de este evento debe indicar si se permite una operación de arrastre sobre esta ubicación. Si no hay procesos de escucha o éstos no realizan ninguna operación, entonces no se permite, de manera predeterminada, una operación de arrastre. Este es también el evento al que escuchar si deseas proporcionar información acerca de que se permite una operación de arrastre, como, por ejemplo, mostrar un resaltado o un marcador de inserción. Para obtener más información al respecto, consulta <a href="/en-US/docs/DragDrop/Drag_Operations#droptargets" title="/en-US/docs/DragDrop/Drag_Operations#droptargets">Especificación de destinos de colocación</a> .</dd> + <dt>dragover</dt> + <dd>Este evento se activa cuando el ratón/mouse se mueve sobre un elemento cuando está teniendo lugar una operación de arrastre. Gran parte del tiempo, la operación que tiene lugar durante un proceso de escucha será la misma que el evento dragenter. Para obtener más información al respecto, consulta <a href="/en-US/docs/DragDrop/Drag_Operations#droptargets" title="/en-US/docs/DragDrop/Drag_Operations#droptargets">Especificación de destinos de colocación</a>.</dd> + <dt>dragleave</dt> + <dd>Este evento se activa cuando el ratón/mouse sale de un elemento mientras que está teniendo lugar una operación de arrastre. Los procesos de escucha deben eliminar cualquier resaltado o marcador de inserción que usan para la información sobre el proceso de arrastre.</dd> + <dt>drag</dt> + <dd>Este evento se activa en el origen del arrastre, es decir, el elemento donde dragstart fue disparado, durante la operación de arrastre.</dd> + <dt>drop</dt> + <dd>El evento se dispara sobre el elemento en el que se produjo la colocación al finalizar la operación de arrastre. Un proceso de escucha se encargará de recuperar los datos que se arrastran e insertarlos en la ubicación de la colocación. Este evento sólo se activará si se desea disponer de la funcionalidad de soltar. No se activará si el usuario cancela la operación de arrastre, por ejemplo, pulsando la tecla Escape, o si se liberó el botón del ratón/mouse mientras que éste no estaba sobre un destino de colocación válido. Para más información sobre esto, consulta <a href="/en-US/docs/DragDrop/Drag_Operations#drop" title="/en-US/docs/DragDrop/Drag_Operations#drop">Realizar una operación de colocación</a>.</dd> + <dt>dragend</dt> + <dd>El origen del arrastre recibirá un evento dragend cuando la operación se haya completado, tanto si tuvo éxito como si no. Consulta <a href="/en-US/docs/DragDrop/Drag_Operations#dragend" title="/en-US/docs/DragDrop/Drag_Operations#dragend">Finalizar una operación de arrastre</a> si deseas más información.</dd> +</dl> + + +<div>{{ HTML5ArticleTOC () }}</div> diff --git a/files/es/web/api/html_drag_and_drop_api/recommended_drag_types/index.html b/files/es/web/api/html_drag_and_drop_api/recommended_drag_types/index.html new file mode 100644 index 0000000000..daad516a44 --- /dev/null +++ b/files/es/web/api/html_drag_and_drop_api/recommended_drag_types/index.html @@ -0,0 +1,144 @@ +--- +title: Tipos de Drag recomendados +slug: DragDrop/Recommended_Drag_Types +translation_of: Web/API/HTML_Drag_and_Drop_API/Recommended_drag_types +--- +<p>A continuación se describe la mejor practica para utilizar los datos a ser arrastrado.</p> +<h2 id="text" name="text">Arrastramdo Texto</h2> +<p>Al arrastrar el texto, utilice el texto / texto normal. Los datos deben ser la cadena de arrastre. Por ejemplo:</p> +<pre>event.dataTransfer.setData("text/plain", "This is text to drag") +</pre> +<p>Arrastrar texto en cuadros de texto y las selecciones de las páginas web se realiza de forma automática, por lo que no es necesario para manejar dragging.</p> +<p><span style="line-height: 1.5;">Se recomienda que siempre se agrega datos del tipo </span><code style="font-size: 14px;">text/plain</code><span style="line-height: 1.5;"> </span><span style="line-height: 1.5;">como un mensaje para las aplicaciones o los destinos que no soportan otros tipos, a menos que no hay alternativa de texto lógico. Siempre agregue el tipo de texto sin formato pasado, ya que es el menos específico.</span></p> +<p><span style="line-height: 1.5;">En códigos más viejo, encontrara </span><span style="font-family: 'Courier New', 'Andale Mono', monospace; line-height: normal;">text/unicode o </span>el tipo<span style="font-family: 'Courier New', 'Andale Mono', monospace; line-height: normal;"> </span><span style="font-family: 'Courier New', 'Andale Mono', monospace; line-height: normal;">Text.</span><span style="line-height: 1.5;">Estos equivalen </span><span style="font-family: 'Courier New', 'Andale Mono', monospace; line-height: normal;">text/plain,</span><span style="line-height: 1.5;">que </span><span style="line-height: 1.5;">guardara y recibia los datos del texto plano en ese lugar</span><font face="Courier New, Andale Mono, monospace"><span style="line-height: normal;">.</span></font></p> +<h2 id="link" name="link">Arrastrando Enlaces</h2> +<p>Los enlaces deben incluir los datos de los dos tipos, el primero debe ser URL utilizando el tipo <span style="font-family: 'Courier New', 'Andale Mono', monospace; line-height: normal;">text/uri-list,</span><span style="line-height: 1.5;">y el segundo es URL utilizando el tipo </span><span style="font-family: 'Courier New', 'Andale Mono', monospace; line-height: normal;">text/plain. </span><span style="line-height: 1.5;">Ambos tipos deben utilizar los mismos datos, la URL del enlace. Por ejemplo:</span></p> +<pre>var dt = event.dataTransfer; +dt.setData("text/uri-list", "http://www.mozilla.org"); +dt.setData("text/plain", "http://www.mozilla.org"); +</pre> +<p>Es constumbre, establecer el tipo <span style="font-family: 'Courier New', 'Andale Mono', monospace; line-height: normal;">text/plain de ultimo, </span><span style="line-height: 1.5;">, ya que es menos específico que el tipo de URI.</span></p> +<p>Note que el tipo de URL <span style="font-family: 'Courier New', 'Andale Mono', monospace; line-height: normal;">uri-list </span><span style="line-height: 1.5;">es con una "i", no una "L"</span></p> +<p><span style="line-height: 1.5;">Note that the URL type is </span><code style="font-size: 14px;">uri-list</code><span style="line-height: 1.5;"> with an 'I', not with an 'L'.</span></p> +<p>To drag multiple links, you can also separate each link with a linebreak. A line that begins with a number sign (#) is a comment and should not be considered a valid URL. You can use a comment to indicate the purpose of a link, or to hold the title associated with a link. The <code>text/plain</code> version of the drag data should include all links but should not include the comments.</p> +<p>For example:</p> +<pre>http://www.mozilla.org +#A second link +http://www.xulplanet.com +</pre> +<p>This sample <code>text/uri-list</code> data contains two links and a comment.</p> +<p>When retrieving a dropped link, you should ensure you handle the case where multiple links may have been dragged, and any comments that appear in the data. For convenience, the special type <code>URL</code> may be used to refer to the first valid link within the data for the <code>text/uri-list</code> type. You should not add data using the <code>URL</code> type; attempting to do so will just set the value of the <code>text/uri-list</code> type instead.</p> +<pre>var url = event.dataTransfer.getData("URL"); +</pre> +<p>You may also see data using the <code>text/x-moz-url</code> type which is a Mozilla specific type. If it appears, it should be used before the <code>text/uri-list</code> type. It holds the URL of the link followed by the title of the link, separated by a linebreak. For example:</p> +<pre>http://www.mozilla.org +Mozilla +http://www.xulplanet.com +XUL Planet +</pre> +<h2 id="html" name="html">Dragging HTML and XML</h2> +<p>HTML content may use the <code>text/html</code> type. The data for this type should be the serialized HTML to drag. For instance, it would be suitable to set the data value for this type to the value of the <code>innerHTML</code> property of an element.</p> +<p>XML content may use the <code>text/xml</code> type, but you should ensure that the data value is well-formed XML.</p> +<p>You may also include a plain text representation of the HTML or XML data using the <code>text/plain</code> type. The data should be just the text and should not include any of the source tags or attributes. For instance:</p> +<pre>var dt = event.dataTransfer; +dt.setData("text/html", "Hello there, <strong>stranger</strong>"); +dt.setData("text/plain", "Hello there, stranger"); +</pre> +<h2 id="file" name="file">Dragging Files</h2> +<p>A local file is dragged using the <code>application/x-moz-file</code> type with a data value that is an <a href="/en/XPCOM_Interface_Reference/nsIFile" title="nsIFile">nsIFile</a> object. Non-privileged web pages are not able to retrieve or modify data of this type. Because a file is not a string, you must use the <a href="/En/DragDrop/DataTransfer#mozSetDataAt.28.29" title="mozSetDataAt">mozSetDataAt</a> method to assign the data. Similarly, when retrieving the data, you must use the <a href="/En/DragDrop/DataTransfer#mozGetDataAt.28.29" title="mozGetDataAt">mozGetDataAt</a> method.</p> +<pre>event.dataTransfer.mozSetDataAt("application/x-moz-file", file, 0); +</pre> +<p>If possible, you may also include the file URL of the file using both the <code>text/uri-list</code> and/or <code>text/plain</code> types. These types should be added last so that the more specific <code>application/x-moz-file</code> type has higher priority.</p> +<p>Multiple files will be received during a drop as mutliple items in the data transfer. See <a href="/En/DragDrop/Dragging_and_Dropping_Multiple_Items" title="Dragging and Dropping Multiple Items">Dragging and Dropping Multiple Items</a> for more details about this.</p> +<p>The following example shows how to create an area for receiving dropped files:</p> +<pre><listbox ondragenter="return checkDrag(event)" + ondragover="return checkDrag(event)" + ondrop="doDrop(event)"/> + +<script> +function checkDrag(event) +{ + return event.dataTransfer.types.contains("application/x-moz-file"); +} + +function doDrop(event) +{ + var file = event.dataTransfer.mozGetDataAt("application/x-moz-file", 0); + if (file instanceof Components.interfaces.nsIFile) + event.currentTarget.appendItem(file.leafName); +} +</script> +</pre> +<p>In this example, the event returns false only if the data transfer contains the <code>application/x-moz-file</code> type. During the drop event, the data associated with the file type is retrieved, and the filename of the file is added to the listbox. Note that the <code>instanceof</code> operator is used here as the <a href="/En/DragDrop/DataTransfer#mozGetDataAt.28.29" title="mozGetDataAt">mozGetDataAt</a> method will return an <code>nsISupports</code> that needs to be checked and converted into an nsIFile. This is also a good extra check in case someone made a mistake and added a non-file for this type.</p> +<h2 id="image" name="image">Dragging Images</h2> +<p>Direct image dragging is not commonly done. In fact, Mozilla does not support direct image dragging on Mac or Linux platforms. Instead, images are usually dragged only by their URLs. To do this, use the <code>text/uri-list</code> type as with other URL links. The data should be the URL of the image or a data URL if the image is not stored on a web site or disk. For more information about data URLs, see <a class="internal" href="/en/data_URIs" title="en/The data URL scheme">the data URL scheme</a>.</p> +<p>As with other links, the data for the <code>text/plain</code> type should also contain the URL. However, a data URL is not usually as useful in a text context, so you may wish to exclude the <code>text/plain</code> data in this situation.</p> +<p>In chrome or other privileged code, you may also use the <code>image/jpeg</code>, <code>image/png</code> or <code>image/gif</code> types, depending on the type of image. The data should be an object which implements the <a href="/en/XPCOM_Interface_Reference/nsIInputStream" title="nsIInputStream">nsIInputStream</a> interface. When this stream is read, it should provide the data bits for the image, as if the image was a file of that type.</p> +<p>You should also include the <code>application/x-moz-file</code> type if the image is located on disk. In fact, this a common way in which image files are dragged.</p> +<p>It is important to set the data in the right order, from most specific to least specific. The image type such as <code>image/jpeg</code> should come first, followed by the <code>application/x-moz-file</code> type. Next, you should set the <code>text/uri-list</code> data and finally the <code>text/plain</code> data. For example:</p> +<pre>var dt = event.dataTransfer; +dt.mozSetDataAt("image/png", stream, 0); +dt.mozSetDataAt("application/x-moz-file", file, 0); +dt.setData("text/uri-list", imageurl); +dt.setData("text/plain", imageurl); +</pre> +<p>Note that the <a href="/En/DragDrop/DataTransfer#mozGetDataAt.28.29" title="mozGetDataAt">mozGetDataAt</a> method is used for non-text data. As some contexts may only include some of these types, it is important to check which type is made available when receiving dropped images.</p> +<h2 id="node" name="node">Dragging Nodes</h2> +<p>Nodes and elements in a document may be dragged using the <code>application/x-moz-node</code> type. This data for the type should be a DOM node. This allows the drop target to receive the actual node where the drag was started from. Note that callers from a different domain will not be able to access the node even when it has been dropped.</p> +<p>You should always include a plain text alternative for the node.</p> +<h2 id="custom" name="custom">Dragging Custom Data</h2> +<p>You can also use other types that you make up for custom purposes. You should strive to always include a plain text alternative unless that object being dragged is specific to a particular site or application. In this case, the custom type ensures that the data cannot be dropped elsewhere.</p> +<h2 id="filestoos" name="filestoos">Dragging files to an operating system folder</h2> +<p>There are cases in which you may want to add a file to an existing drag event session, and you may also want to write the file to disk when the drop operation happens over a folder in the operating system when your code receives notification of the target folder's location. This only works in extensions (or other privileged code) and the data flavor "application/moz-file-promise" should be used. The following sample offers an overview of this advanced case:</p> +<pre class="brush: js">// currentEvent is a given existing drag operation event + +currentEvent.dataTransfer.setData("text/x-moz-url", URL); +currentEvent.dataTransfer.setData("application/x-moz-file-promise-url", URL); +currentEvent.dataTransfer.setData("application/x-moz-file-promise-filename", leafName); +currentEvent.dataTransfer.mozSetDataAt('application/x-moz-file-promise', + new dataProvider(success,error), + 0, Components.interfaces.nsISupports); + +function dataProvider(){} + +dataProvider.prototype = { + QueryInterface : function(iid) { + if (iid.equals(Components.interfaces.nsIFlavorDataProvider) + || iid.equals(Components.interfaces.nsISupports)) + return this; + throw Components.results.NS_NOINTERFACE; + }, + getFlavorData : function(aTransferable, aFlavor, aData, aDataLen) { + if (aFlavor == 'application/x-moz-file-promise') { + + var urlPrimitive = {}; + var dataSize = {}; + + aTransferable.getTransferData('application/x-moz-file-promise-url', urlPrimitive, dataSize); + var url = new String(urlPrimitive.value.QueryInterface(Components.interfaces.nsISupportsString)); + console.log("URL file orignal is = " + url); + + var namePrimitive = {}; + aTransferable.getTransferData('application/x-moz-file-promise-filename', namePrimitive, dataSize); + var name = new String(namePrimitive.value.QueryInterface(Components.interfaces.nsISupportsString)); + + console.log("target filename is = " + name); + + var dirPrimitive = {}; + aTransferable.getTransferData('application/x-moz-file-promise-dir', dirPrimitive, dataSize); + var dir = dirPrimitive.value.QueryInterface(Components.interfaces.nsILocalFile); + + console.log("target folder is = " + dir.path); + + var file = Cc['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile); + file.initWithPath(dir.path); + file.appendRelativePath(name); + + console.log("output final path is =" + file.path); + + // now you can write or copy the file yourself... + } + } +} +</pre> +<p>{{ languages( { "ja": "Ja/DragDrop/Recommended_Drag_Types" } ) }}</p> diff --git a/files/es/web/api/element/accesskey/index.html b/files/es/web/api/htmlelement/accesskey/index.html index 7d73c395fc..7d73c395fc 100644 --- a/files/es/web/api/element/accesskey/index.html +++ b/files/es/web/api/htmlelement/accesskey/index.html diff --git a/files/es/web/api/htmlelement/animationend_event/index.html b/files/es/web/api/htmlelement/animationend_event/index.html new file mode 100644 index 0000000000..8bca8b046f --- /dev/null +++ b/files/es/web/api/htmlelement/animationend_event/index.html @@ -0,0 +1,81 @@ +--- +title: animationend +slug: Web/Events/animationend +translation_of: Web/API/HTMLElement/animationend_event +--- +<p>El evento <code>animationend</code> es lanzado cuando una animación CSS se ha completado.</p> + +<h2 id="Información_General">Información General</h2> + +<dl> + <dt style="float: left; text-align: right; width: 120px;">Especificación</dt> + <dd style="margin: 0 0 0 120px;"><a class="external" href="http://www.w3.org/TR/css3-animations/#animation-events">CSS Animations</a></dd> + <dt style="float: left; text-align: right; width: 120px;">Interface</dt> + <dd style="margin: 0 0 0 120px;">AnimationEvent</dd> + <dt style="float: left; text-align: right; width: 120px;">Bubbles</dt> + <dd style="margin: 0 0 0 120px;">Si</dd> + <dt style="float: left; text-align: right; width: 120px;">Cancelable</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Target</dt> + <dd style="margin: 0 0 0 120px;">Document, Element</dd> + <dt style="float: left; text-align: right; width: 120px;">Acción por defecto</dt> + <dd style="margin: 0 0 0 120px;">None</dd> +</dl> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Propiedad</th> + <th scope="col">Tipo</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{ReadOnlyInline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>The event target (the topmost target in the DOM tree).</td> + </tr> + <tr> + <td><code>type</code> {{ReadOnlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The type of event.</td> + </tr> + <tr> + <td><code>bubbles</code> {{ReadOnlyInline}}</td> + <td><code>boolean</code></td> + <td>Does the event normally bubble?</td> + </tr> + <tr> + <td><code>cancelable</code> {{ReadOnlyInline}}</td> + <td><code>boolean</code></td> + <td>Is it possible to cancel the event?</td> + </tr> + <tr> + <td><code>animationName</code> {{ReadOnlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The name of the CSS property associated with the transition.</td> + </tr> + <tr> + <td><code>elapsedTime</code> {{ReadOnlyInline}}</td> + <td>Float</td> + <td>The amount of time the animation has been running, in seconds, when this event fired, excluding any time the animation was paused. For an "animationstart" event, the elapsedTime is zero unless there was a negative value for <code>animation-delay</code>, in which case the event will be fired with an elapsedTime of (-1 * delay).</td> + </tr> + </tbody> +</table> + +<h2 id="Eventos_relacionados">Eventos relacionados</h2> + +<ul> + <li>{{Event("animationstart")}}</li> + <li>{{Event("animationend")}}</li> + <li>{{Event("animationiteration")}}</li> +</ul> + +<h2 id="Ver_también">Ver también</h2> + +<ul> + <li><a href="/en-US/docs/CSS/Using_CSS_animations" title="/en-US/docs/CSS/Using_CSS_animations">Using CSS Animations</a></li> +</ul> diff --git a/files/es/web/api/htmlelement/transitioncancel_event/index.html b/files/es/web/api/htmlelement/transitioncancel_event/index.html new file mode 100644 index 0000000000..3f9c622bd2 --- /dev/null +++ b/files/es/web/api/htmlelement/transitioncancel_event/index.html @@ -0,0 +1,163 @@ +--- +title: transitioncancel +slug: Web/Events/transitioncancel +tags: + - DOM + - Evento + - Referencia + - eventos +translation_of: Web/API/HTMLElement/transitioncancel_event +--- +<p>{{SeeCompatTable}}</p> + +<p>El evento <code>transitioncancel</code> es lanzado cuando una <a href="/en-US/docs/CSS/Using_CSS_transitions">transición CSS</a> es cancelada.</p> + +<p>Véase {{domxref("GlobalEventHandlers.ontransitioncancel")}} para mas información y ejemplos.</p> + +<h2 id="Información_general">Información general</h2> + +<dl> + <dt>Interfaz</dt> + <dd>{{domxref("TransitionEvent")}}</dd> + <dt>Burbuja</dt> + <dd>Sí</dd> + <dt>Cancelable</dt> + <dd>No</dd> + <dt>Objetivo</dt> + <dd>{{domxref("document")}}, {{domxref("element")}}</dd> + <dt>Acción por defecto</dt> + <dd>Ninguna</dd> +</dl> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Propiedad</th> + <th scope="col">Tipo</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyinline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>El objetivo del evento (the topmost target in the DOM tree).</td> + </tr> + <tr> + <td><code>type</code> {{readonlyinline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>El tipo de evento.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyinline}}</td> + <td>{{domxref("Boolean")}}</td> + <td>Si el evento normalmente se propaga o no</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyinline}}</td> + <td>{{domxref("Boolean")}}</td> + <td>Si el evento es cancelable o no</td> + </tr> + <tr> + <td><code>propertyName</code>{{readonlyinline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>El nombre de la propiedad CSS asociada con la transición.</td> + </tr> + <tr> + <td><code>elapsedTime</code>{{readonlyinline}}</td> + <td>{{domxref("Float")}}</td> + <td> + <p>La cantidad de tiempo que ha durado la transición, en segundos, desde el momento en que el evento fué generado. Este valor no se ve afectado por el valor de <code>transition-delay</code>.</p> + </td> + </tr> + <tr> + <td><code>pseudoElement</code>{{readonlyinline}}</td> + <td>{{domxref("DOMString")}}</td> + <td> + <p>El nombre (empezando con dos "dos puntos") del pseudo-elemento CSS en el que ha ocurrido la transición (en caso de que el objetivo del evento sea dicho pseudo-elemento correspondiente al elemento), o una cadena vacía si la transición ha ocurrido en un elemento (lo que quiere decir que el objetivo del evento es dicho elemento).</p> + </td> + </tr> + </tbody> +</table> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Especificación</th> + <th scope="col">Estado</th> + <th scope="col">Comentario</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('CSS3 Transitions', '#transitioncancel', 'transitioncancel')}}</td> + <td>{{Spec2('CSS3 Transitions')}}</td> + <td>Definición inicial.</td> + </tr> + </tbody> +</table> + +<h2 id="Compatibilidad_con_navegadores">Compatibilidad con navegadores</h2> + +<p>{{CompatibilityTable}}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>{{CompatNo}}</td> + <td>{{CompatGeckoDesktop(53)}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + </tr> + </tbody> +</table> +</div> + +<p> </p> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>{{CompatNo}}</td> + <td>{{CompatGeckoMobile(53)}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="Véase_también">Véase también</h2> + +<ul> + <li>El manejador {{domxref("GlobalEventHandlers.ontransitioncancel")}}</li> + <li>La interfaz {{domxref("TransitionEvent")}}</li> + <li>{{event("transitionstart")}}, {{event("transitionend")}}</li> + <li>Propiedades CSS: {{cssxref("transition")}}, {{cssxref("transition-delay")}}, {{cssxref("transition-duration")}}, {{cssxref("transition-property")}}, {{cssxref("transition-timing-function")}}.</li> +</ul> diff --git a/files/es/web/api/htmlelement/transitionend_event/index.html b/files/es/web/api/htmlelement/transitionend_event/index.html new file mode 100644 index 0000000000..8370f0e39e --- /dev/null +++ b/files/es/web/api/htmlelement/transitionend_event/index.html @@ -0,0 +1,183 @@ +--- +title: transitionend +slug: Web/Events/transitionend +tags: + - DOM + - Event + - Referencia + - Transiciones CSS + - Transiciones CSS3 + - TransitionEvent + - transitionend +translation_of: Web/API/HTMLElement/transitionend_event +--- +<p>El evento <code>transitionend</code> es lanzado cuando una <a href="/en-US/docs/CSS/Using_CSS_transitions">transición CSS</a> se ha completado. Si la transición es eliminada antes de haberse completado, como cuando {{cssxref("transition-property")}} es eliminado o {{cssxref("display")}} se establece a <code>"none"</code>, entonces el evento no será generado.</p> + +<h2 id="Información_general">Información general</h2> + +<dl> + <dt style="float: left; text-align: right; width: 120px;">Especificación</dt> + <dd style="margin: 0 0 0 120px;">{{SpecName("CSS3 Transitions")}}</dd> + <dt style="float: left; text-align: right; width: 120px;">Interfaz</dt> + <dd style="margin: 0 0 0 120px;">{{domxref("TransitionEvent")}}</dd> + <dt style="float: left; text-align: right; width: 120px;">Burbuja</dt> + <dd style="margin: 0 0 0 120px;">Sí</dd> + <dt style="float: left; text-align: right; width: 120px;">Cancelable</dt> + <dd style="margin: 0 0 0 120px;">Sí</dd> + <dt style="float: left; text-align: right; width: 120px;">Objetivo</dt> + <dd style="margin: 0 0 0 120px;">{{domxref("Element")}}, {{domxref("Document")}}, {{domxref("Window")}}</dd> + <dt style="float: left; text-align: right; width: 120px;">Acción</dt> + <dd style="margin: 0 0 0 120px;">undefined</dd> +</dl> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col">Type</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyInline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>The event target (the topmost target in the DOM tree).</td> + </tr> + <tr> + <td><code>type</code> {{readonlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The type of event.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Whether the event normally bubbles or not.</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Whether the event is cancellable or not.</td> + </tr> + <tr> + <td><code>propertyName</code> {{readonlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The name of the CSS property associated with the transition.</td> + </tr> + <tr> + <td><code>elapsedTime</code> {{readonlyInline}}</td> + <td>Float</td> + <td>The amount of time the transition has been running, in seconds, as of the time the event was generated. This value is not affected by the value of <code>transition-delay</code>.</td> + </tr> + <tr> + <td><code>pseudoElement</code> {{readonlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The name (beginning with two colons) of the CSS pseudo-element on which the transition occured (in which case the target of the event is that pseudo-element's corresponding element), or the empty string if the transition occurred on an element (which means the target of the event is that element).</td> + </tr> + </tbody> +</table> + +<h2 id="Ejemplo">Ejemplo</h2> + +<p>Este ejemplo establece un manejador de evento para detectar el evento <code>transitionend</code>, y así cambiar el texto que se muestra dentro del elemento cuando la transición se completa.</p> + +<pre class="brush: js">let element = document.getElementById("slidingMenu"); +element.addEventListener("transitionend", function(event) { + element.innerHTML = "Done!"; +}, false); +</pre> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Especificación</th> + <th scope="col">Estado</th> + <th scope="col">Comentario</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName("CSS3 Transitions", "#transitionend", "transitionend")}}</td> + <td>{{Spec2('CSS3 Transitions')}}</td> + <td>Definición inicial.</td> + </tr> + </tbody> +</table> + +<h2 id="Compatibilidad_con_navegadores">Compatibilidad con navegadores</h2> + +<p>{{CompatibilityTable}}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>1.0<sup>[1]</sup><br> + 36</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoDesktop("2.0")}}</td> + <td>10</td> + <td>10.5<sup>[2]</sup><br> + 12<br> + 12.10<br> + 23</td> + <td>3.2<sup>[1]</sup><br> + 7.0.6</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Android</th> + <th>Edge</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>2.1</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoMobile("2.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>10<sup>[2]</sup><br> + 12<br> + 12.10</td> + <td>3.2<sup>[1]</sup></td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Implementado en Chrome 1.0, Android 2.1 y WebKit 3.2 como <code>webkitTransitionEnd</code>. Chrome 36 y WebKit 7.0.6 usan el estándar <code>transitionend</code>.</p> + +<p>[2] Implementado como <code>oTransitionEnd</code> desde Opera 10.5, como <code>otransitionend</code> desde la versión 12 y como el estándar <code>transitionend</code> desde la versión 12.10.</p> + +<h2 id="Véase_también">Véase también</h2> + +<p>La interfaz {{domxref("TransitionEvent")}}</p> + +<ul> + <li>{{event("transitionstart")}}, {{event("transitioncancel")}}</li> + <li>Propiedades CSS: {{cssxref("transition")}}, {{cssxref("transition-delay")}}, {{cssxref("transition-duration")}}, {{cssxref("transition-property")}}, {{cssxref("transition-timing-function")}}.</li> +</ul> diff --git a/files/es/web/api/htmlmediaelement/abort_event/index.html b/files/es/web/api/htmlmediaelement/abort_event/index.html new file mode 100644 index 0000000000..641d144c77 --- /dev/null +++ b/files/es/web/api/htmlmediaelement/abort_event/index.html @@ -0,0 +1,68 @@ +--- +title: abort +slug: Web/Events/abort +translation_of: Web/API/HTMLMediaElement/abort_event +translation_of_original: Web/Events/abort +--- +<p>The <code>abort</code> event is fired when the loading of a resource has been aborted.</p> + +<h2 id="Información_general">Información general</h2> + +<dl> + <dt style="float: left; text-align: right; width: 120px;">Specification</dt> + <dd style="margin: 0 0 0 120px;"><a class="external" href="http://www.w3.org/TR/DOM-Level-3-Events/#event-type-abort">DOM L3</a></dd> + <dt style="float: left; text-align: right; width: 120px;">Interface</dt> + <dd style="margin: 0 0 0 120px;">UIEvent if generated from a user interface, Event otherwise.</dd> + <dt style="float: left; text-align: right; width: 120px;">Bubbles</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Cancelable</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Target</dt> + <dd style="margin: 0 0 0 120px;">Element</dd> + <dt style="float: left; text-align: right; width: 120px;">Default Action</dt> + <dd style="margin: 0 0 0 120px;">None</dd> +</dl> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col">Type</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyInline}}</td> + <td><a href="/en-US/docs/Web/API/EventTarget" title="EventTarget is an interface implemented by objects that can receive events and may have listeners for them."><code>EventTarget</code></a></td> + <td>The event target (the topmost target in the DOM tree).</td> + </tr> + <tr> + <td><code>type</code> {{readonlyInline}}</td> + <td><a href="/en-US/docs/Web/API/DOMString" title="DOMString is a UTF-16 String. As JavaScript already uses such strings, DOMString is mapped directly to a String."><code>DOMString</code></a></td> + <td>The type of event.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyInline}}</td> + <td><a href="/en-US/docs/Web/API/Boolean" title="The Boolean object is an object wrapper for a boolean value."><code>Boolean</code></a></td> + <td>Whether the event normally bubbles or not.</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyInline}}</td> + <td><a href="/en-US/docs/Web/API/Boolean" title="The Boolean object is an object wrapper for a boolean value."><code>Boolean</code></a></td> + <td>Whether the event is cancellable or not.</td> + </tr> + <tr> + <td><code>view</code> {{readonlyInline}}</td> + <td><a class="new" href="/en-US/docs/Web/API/WindowProxy" rel="nofollow" title="The documentation about this has not yet been written; please consider contributing!"><code>WindowProxy</code></a></td> + <td><a href="/en-US/docs/Web/API/Document/defaultView" title="In browsers, document.defaultView returns the window object associated with a document, or null if none is available."><code>document.defaultView</code></a> (<code>window</code> of the document)</td> + </tr> + <tr> + <td><code>detail</code> {{readonlyInline}}</td> + <td><code>long</code> (<code>float</code>)</td> + <td>0.</td> + </tr> + </tbody> +</table> diff --git a/files/es/web/api/htmlelement/dataset/index.html b/files/es/web/api/htmlorforeignelement/dataset/index.html index 10c6f555f9..10c6f555f9 100644 --- a/files/es/web/api/htmlelement/dataset/index.html +++ b/files/es/web/api/htmlorforeignelement/dataset/index.html diff --git a/files/es/web/api/htmlelement/focus/index.html b/files/es/web/api/htmlorforeignelement/focus/index.html index d615cbf12e..d615cbf12e 100644 --- a/files/es/web/api/htmlelement/focus/index.html +++ b/files/es/web/api/htmlorforeignelement/focus/index.html diff --git a/files/es/web/api/elementoshtmlparavideo/index.html b/files/es/web/api/htmlvideoelement/index.html index 4b36d9cba2..4b36d9cba2 100644 --- a/files/es/web/api/elementoshtmlparavideo/index.html +++ b/files/es/web/api/htmlvideoelement/index.html diff --git a/files/es/web/api/indexeddb_api/conceptos_basicos_detras_de_indexeddb/index.html b/files/es/web/api/indexeddb_api/basic_concepts_behind_indexeddb/index.html index 34d4fdd438..34d4fdd438 100644 --- a/files/es/web/api/indexeddb_api/conceptos_basicos_detras_de_indexeddb/index.html +++ b/files/es/web/api/indexeddb_api/basic_concepts_behind_indexeddb/index.html diff --git a/files/es/web/api/indexeddb_api/usando_indexeddb/index.html b/files/es/web/api/indexeddb_api/using_indexeddb/index.html index ea9d2d879c..ea9d2d879c 100644 --- a/files/es/web/api/indexeddb_api/usando_indexeddb/index.html +++ b/files/es/web/api/indexeddb_api/using_indexeddb/index.html diff --git a/files/es/web/api/media_streams_api/index.html b/files/es/web/api/media_streams_api/index.html new file mode 100644 index 0000000000..f8ab5d5c05 --- /dev/null +++ b/files/es/web/api/media_streams_api/index.html @@ -0,0 +1,445 @@ +--- +title: API de MediaStream +slug: WebRTC/MediaStream_API +translation_of: Web/API/Media_Streams_API +--- +<p>{{SeeCompatTable}}</p> +<p>La <strong>API de proceso <a href="#_edn1" name="_ednref1" title=""><strong>[i]</strong></a><em>MediaStream</em></strong>, a veces llamada<em>Media Stream API</em> o<em> Stream API</em>, es parte de la norma <a href="https://developer.mozilla.org/en-US/docs/WebRTC" title="https://developer.mozilla.org/en-US/docs/WebRTC">WebRTC [en]</a> y describe un flujo de datos de audio o video, los métodos para trabajar con ellos, las limitaciones asociadas con este tipo de datos, las respuestas de error y éxito al usar los datos asincrónicamente y los eventos que se disparan durante el proceso.</p> +<div> + </div> +<h2 id="Conceptos_Básicos">Conceptos Básicos</h2> +<p>La API está basada sobre la manipulación de un objeto {{domxref("MediaStream")}} que representa un flujo de datos de audio o video. Generalmente, un objeto <code>MediaStream</code> es una simple cadena URL que puede ser usada para referirse a datos almacenados en un {{domxref("Archivo")}} DOM o un objeto {{domxref("Blob")}} creado con {{domxref("window.URL.createObjectURL()")}}, como se lo describe en<a href="https://developer.mozilla.org/en-US/docs/WebRTC/taking_webcam_photos#Get_the_video" title="https://developer.mozilla.org/en-US/docs/WebRTC/taking_webcam_photos#Get_the_video"> <u>Obtener el video</u></a>.</p> +<p>Un <code>MediaStream</code> está compuesto por más objetos <a href="#_edn1" name="_ednref1" title="">[i]</a>{{domxref("MediaStreamTrack")}} que representan varias <strong>pistas</strong> de audio o video. Cada <code>MediaStreamTrack </code>puede tener uno o más <strong>canales</strong>. El canal representa la unidad menor de un flujo de medio, como una señal de audio asociada a un parlante específico, como el <em>izquierdo</em> o el <em>derecho</em> en una pista de audio estéreo.</p> +<p>Los objetos <code>MediaStream</code> poseen una sola <strong>entrada</strong> y <strong>salida<a href="#_edn2" name="_ednref2" title=""><strong>[ii]</strong></a>. </strong>Un objeto <code>MediaStream</code> creado con <a href="https://developer.mozilla.org/en-US/docs/Web/API/Navigator.getUserMedia?redirectlocale=en-US&redirectslug=WebRTC%2Fnavigator.getUserMedia" title="https://developer.mozilla.org/en-US/docs/Web/API/Navigator.getUserMedia?redirectlocale=en-US&redirectslug=WebRTC%2Fnavigator.getUserMedia"><u>getUserMedia()</u></a> se denomina <em>local </em>y tiene como origen de entrada una de las cámaras o micrófonos del usuario. Un MediaStream no local puede estar representando un elemento de medio como {{HTMLElement("video")}} o {{HTMLElement("audio")}}, un flujo originado en la red y obtenido a través de la <a href="#_edn3" name="_ednref3" title="">[iii]</a><a href="https://developer.mozilla.org/en-US/docs/WebRTC/PeerConnection_API" title="https://developer.mozilla.org/en-US/docs/WebRTC/PeerConnection_API"><em><u>PeerConnection API</u></em></a> o un flujo creado con la <a href="https://developer.mozilla.org/en-US/docs/Web_Audio_API" title="https://developer.mozilla.org/en-US/docs/Web_Audio_API"><u>API de Audio Web</u></a> <a href="#_edn4" name="_ednref4" title="">[iv]</a>{{domxref("MediaStreamAudioSourceNode")}}. La salida de un objeto <code>MediaStream</code> está enlazada a un <strong>consumidor.</strong> El mismo puede ser un elemento de medio como <code><audio> o <video></code>, la <a href="https://developer.mozilla.org/en-US/docs/WebRTC/PeerConnection_API" title="https://developer.mozilla.org/en-US/docs/WebRTC/PeerConnection_API"><u>PeerConnection API</u></a> de WebRTC o una <a href="https://developer.mozilla.org/en-US/docs/Web_Audio_API" title="https://developer.mozilla.org/en-US/docs/Web_Audio_API"><u>API de Audio Web</u></a> <a href="#_edn5" name="_ednref5" title="">[v]</a>{{domxref("MediaStreamAudioDestinationNode")}}.</p> +<div> + </div> +<h2 id="Referencia">Referencia</h2> +<div class="index"> + <ul> + <li>{{event("addtrack")}} (event)</li> + <li>{{domxref("AudioStreamTrack")}}</li> + <li>{{domxref("BlobEvent")}}</li> + <li>{{domxref("BlobEventInit")}}</li> + <li>{{event("ended (MediaStream)")}} (event)</li> + <li>{{event("ended (MediaStreamTrack)")}} (event)</li> + <li>{{domxref("MediaStream")}}</li> + <li>{{domxref("MediaStreamConstraints")}}</li> + <li>{{domxref("MediaStreamTrack")}}</li> + <li>{{domxref("MediaStreamTrackEvent")}}</li> + <li>{{domxref("MediaStreamTrackList")}}</li> + <li>{{domxref("MediaTrackConstraints")}}</li> + <li>{{event("muted")}} (event)</li> + <li>{{domxref("NavigatorUserMedia")}}</li> + <li>{{domxref("NavigatorUserMediaError")}}</li> + <li>{{event("overconstrained")}} (event)</li> + <li>{{event("removetrack")}} (event)</li> + <li>{{event("started")}} (event)</li> + <li>{{event("unmuted")}} (event)</li> + <li>{{domxref("URL")}}</li> + <li>{{domxref("VideoStreamTrack")}}</li> + </ul> +</div> +<h2 id="Pista_de_MediaStream">Pista de MediaStream</h2> +<p>Una <em>MediaStreamTrack </em>puede ser de dos tipos, de audio o video, y representa el origen del medio, como una cámara.</p> +<h3 id="Atributos">Atributos</h3> +<table> + <thead> + <tr> + <th scope="col">Atributo</th> + <th scope="col">Tipo</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td>enabled</td> + <td>Boolean </td> + <td>True si la pista sigue asociada a su fuente.</td> + </tr> + <tr> + <td>id</td> + <td>DOMString, read-only</td> + <td>Un <em>globally unique identifier </em>(GUID) que describe la pista de medios.</td> + </tr> + <tr> + <td>kind</td> + <td>DOMString, read-only</td> + <td>El <strong>audio</strong> o <strong>video</strong> para la pista de origen.</td> + </tr> + <tr> + <td>label</td> + <td>DOMString, read-only</td> + <td>Una cadena de tipo usuario-asignada que identifica la pista de origen, como en "internal microphone." </td> + </tr> + <tr> + <td>onended</td> + <td>EventHandler</td> + <td>Maneja el evento finalizado cuando se lo activa en el objeto MediaStreamTrack.</td> + </tr> + <tr> + <td>onmute </td> + <td>EventHandler</td> + <td>Maneja el evento mudo del objeto MediaStreamTrack. </td> + </tr> + <tr> + <td>onoverconstrained</td> + <td>EventHandler</td> + <td>Maneja el evento superrestricto cuando se lo activa en el objeto MediaStreamTrack.</td> + </tr> + <tr> + <td>onstarted</td> + <td>EventHandler</td> + <td>Maneja el evento iniciado cuando se lo activa en el objeto MediaStreamTrack.</td> + </tr> + <tr> + <td>onunmute </td> + <td>EventHandler</td> + <td>Manjea el evento sin enmudecer cuando se lo activa en el objeto MediaStreamTrack.</td> + </tr> + <tr> + <td>readyState</td> + <td>unsigned short, read-only</td> + <td> + <p>Valores para la pista lista:</p> + <ul> + <li>live - la pista está activa; la salida se puede activar <em>on</em> y <em>off</em> con el atributo habilitado.</li> + <li>muted - el origen del medio subyacente de la pista no puede proveer temporalmente datos en tiempo real.</li> + </ul> + </td> + </tr> + <tr> + <td>sourceId</td> + <td>DOMString, read-only</td> + <td>La identidad de este origen que es único para esta aplicación y persistente. Se recomienda una GUID pero no es obligatoria.</td> + </tr> + <tr> + <td>sourceType</td> + <td>SourceTypeEnum, read-only</td> + <td>Contiene el tipo de información del origen, si es que existe.</td> + </tr> + </tbody> +</table> +<h3 id="Eventos">Eventos</h3> +<table> + <thead> + <tr> + <th scope="col">Evento</th> + <th scope="col">Interfaz</th> + <th scope="col">Descripción </th> + </tr> + </thead> + <tbody> + <tr> + <td>started</td> + <td>Event</td> + <td>El objeto MediaStreamTrack no es más "new" en el readyState.</td> + </tr> + <tr> + <td>muted</td> + <td>Event</td> + <td>El origen del objeto MediaStreamTrack no puede proveer datos temporalmente.</td> + </tr> + <tr> + <td>unmuted </td> + <td>Event</td> + <td>El origen del objeto MediaStreamTrack a recomenzado a proveer datos</td> + </tr> + <tr> + <td>overconstrained</td> + <td>Event</td> + <td>El origen del objeto MediaStreamTrack no puede ser confugurado para que encaje en las restricciones impuestas por la pista. Esto podría ocurrir con la altura en el caso de un video, entre otras posibilidades.</td> + </tr> + <tr> + <td>ended</td> + <td>Event</td> + <td> + <p>El origen del objeto MediaStreamTrack no proveerá datos; puede ocurrir por lo siguiente:</p> + <ul> + <li>el usuario a deshabilitado los permisos de la aplicación</li> + <li>el dispositivo de origen está desconectado</li> + <li>el <em>peer</em> remoto no transmite datos</li> + <li>se llamó el método stop()</li> + </ul> + </td> + </tr> + </tbody> +</table> +<h3 id="appendConstraint()">appendConstraint()</h3> +<p>Agrega la restricción al final de la lista. Esto sólo es un método para añadir restricciones optativas.</p> +<dl> + <dt> + Parámetros</dt> + <dd> + constraintName <strong>DOMString</strong>, required.</dd> + <dd> + constraintValue <strong>Primitive (DOMString, float, etc.) </strong>or<strong> MinMaxConstraint</strong>, required.</dd> + <dt> + Devuelve</dt> + <dd> + void</dd> + <dt> + Excepciones</dt> + <dd> + None.</dd> +</dl> +<h3 id="applyConstraints()">applyConstraints()</h3> +<p>Aplica una lista de opciones optativas a la pista. Sobrescribe cualquier otra restricción optativa ya existente en la pista.</p> +<dl> + <dt> + <strong>Parámetros</strong></dt> + <dd> + constraints <strong>MediaTrackConstraints</strong>, required.</dd> + <dt> + Devuelve</dt> + <dd> + void</dd> + <dt> + Excepciones</dt> + <dd> + None.</dd> +</dl> +<h3 id="constraints()">constraints()</h3> +<p>Devuelte todas las <a href="#_edn1" name="_ednref1" title="">[i]</a>restricciones en la pista, obligatorias y optativas. Si tanto<em> <code>mandatory </code></em>u <code>optional</code> no tienen restricciones, ese campo será <code>undefined</code>. Si ninguno tiene restricciones, entonces<code> constraints()</code> devolverá <code>null<em>.</em></code></p> +<dl> + <dt> + Parámetros</dt> + <dd> + None.</dd> + <dt> + Devuelve</dt> + <dd> + <strong>MediaTrackConstraints</strong> or <strong>null</strong></dd> + <dt> + <span id="cke_bm_186C" style="display: none;"> </span>Excepciones</dt> + <dd> + None.</dd> +</dl> +<h3 id="getConstraint()">getConstraint()</h3> +<p>Trae una restricción específica, por nombre, de la pista. Este método puede devolver una de varias posibilidades:</p> +<ul> + <li>Si su restricción no existe, devuelve <code>null.</code></li> + <li>Si no provee true para parámetro optativo<code>mandatory </code>y su búsqueda resulta en más de una restricción, este método devolverá una lista. Cada ítem de la lista será el nombre de la búsqueda así como su valor o un objeto <code>MinMaxConstraint</code>. La lista se agrupa con la entrada 0º como la más importante y cada entrada posterior es progresivamente menos importante.</li> + <li>Si provee<code>True </code>al parámetro <code>mandatory</code> y su búsqueda es miembro del <code>MediaTrackConstraintSet </code>de la pista, este método devuelve su valor primitivo o su <code>MinMaxConstraint</code>, cualquiera que aplique al caso.</li> +</ul> +<dl> + <dt> + Parámetros</dt> + <dd> + constraintName <strong>DOMString</strong>, required.</dd> + <dd> + mandatory <strong>boolean</strong>, optional, default false.</dd> + <dt> + Devuelve</dt> + <dd> + Any of the possibilities mentioned above.</dd> + <dt> + Excepciones</dt> + <dd> + None.</dd> +</dl> +<p>--</p> +<h3 id="stop()">stop()</h3> +<p>Detiene permanentemente la creación de datos para las pistas y remueve las referencias a los orígines.</p> +<dl> + <dt> + Parámetros</dt> + <dd> + None.</dd> + <dt> + Devuelve</dt> + <dd> + Void.</dd> + <dt> + Excepciones</dt> + <dd> + None.</dd> +</dl> +<h2 id="Lista_de_pistas_de_MediaStream">Lista de pistas de MediaStream</h2> +<p>Un MediaStream tiene dos objetos MediaStreamTrackList, uno para la pista de video y otro para la de audio.</p> +<table> + <thead> + <tr> + <th scope="col">Atributo </th> + <th scope="col">Tipo</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td>length</td> + <td>unsigned long, read-only </td> + <td>El número de pistas en la lista.</td> + </tr> + <tr> + <td>onaddtrack </td> + <td>EventHandler</td> + <td>Maneja el evento addtrack.</td> + </tr> + <tr> + <td>onremovetrack </td> + <td>EventHandler</td> + <td>Maneja el evento removetrack.</td> + </tr> + </tbody> +</table> +<h3 id="Eventos_2">Eventos</h3> +<table> + <thead> + <tr> + <th scope="col">Evento</th> + <th scope="col">Interfaz</th> + <th scope="col">Descripción </th> + </tr> + </thead> + <tbody> + <tr> + <td>addtrack </td> + <td>MediaStreamTrackEvent </td> + <td>Se agregó una MediaStreamTrack a la lista.</td> + </tr> + <tr> + <td>removetrack </td> + <td>MediaStreamTrackEvent</td> + <td>Se removió una MediaStreamTrack de la lista.</td> + </tr> + </tbody> +</table> +<h3 id="add()">add()</h3> +<p>Agrega una MediaStreamTrack a la lista de pistas.</p> +<dl> + <dt> + Parámetros</dt> + <dd> + MediaStreamTrack <strong>track</strong>, required.</dd> + <dt> + Devuelve</dt> + <dd> + Void.</dd> + <dt> + Excepciones</dt> + <dd> + INVALID_STATE_ERR if the stream is finished (all tracks have ended).</dd> +</dl> +<h3 id="item()">item()<span id="cke_bm_369C" style="display: none;"> </span></h3> +<p>Devuelve la MediaStreamTrack al valor de índice (index) especificado.</p> +<dl> + <dt> + Parámetros</dt> + <dd> + unsigned long <strong>index</strong>, required.</dd> + <dt> + Devuelve</dt> + <dd> + MediaStreamTrack</dd> + <dt> + Excepciones</dt> + <dd> + None.</dd> +</dl> +<h3 id="Remove()">Remove()</h3> +<p>Remueve una MediaStreamTrack de la lista de pistas.</p> +<dl> + <dt> + Parámetros</dt> + <dd> + MediaStreamTrack <strong>track</strong>, required.</dd> + <dt> + Devuelve</dt> + <dd> + Void.</dd> + <dt> + Excepciones</dt> + <dd> + INVALID_STATE_ERR if the stream is finished (all tracks have ended).</dd> +</dl> +<h2 id="Compatibilidad_con_navegadores">Compatibilidad con navegadores</h2> +<p>{{ CompatibilityTable() }}</p> +<div id="compat-desktop"> + <table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera </th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Stream API </td> + <td>21{{ property_prefix("webkit") }} </td> + <td>nightly 18{{ property_prefix("moz") }} </td> + <td>{{ CompatUnknown() }} </td> + <td>12</td> + <td>{{ CompatUnknown() }} </td> + </tr> + </tbody> + </table> +</div> +<div id="compat-mobile"> + <table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Stream API </td> + <td>{{ CompatNo() }} </td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }} </td> + <td>{{ CompatNo() }} </td> + <td>{{ CompatNo() }} </td> + </tr> + </tbody> + </table> +</div> +<p>Actualmente, el uso de WebRTC para acceder a la cámara está soportado en Chrome, Opera y Firefox Nightly 18. Habilitar WebRTC en Firefox Nightly requiere que usted establezca una advertencia (flag) en la configuración:</p> +<ul style="margin: 0px 0px 1.286em; padding-top: 0px; padding-right: 0px; padding-bottom: 0px;"> + <li>Escriba "about:config" en la barra de direcciones y diga que sí quiere efectuar los cambios</li> + <li>Busque la entrada de "media.navigator.enabled" entry y establezca su valos a "true" [sin comillas]</li> +</ul> +<div> + <p> </p> + <div> + <br> + <hr> + <div id="edn1"> + <p><a href="#_ednref1" name="_edn1" title="">[i]</a> en castellano,<em>Flujo o transmisión de [multi] Medios</em></p> + </div> + </div> + <hr> + <div id="edn1"> + <p><a href="#_ednref1" name="_edn1" title="">[i]</a> en castellano,<em> Pista de Flujo de Media</em></p> + </div> + <div id="edn2"> + <p><a href="#_ednref2" name="_edn2" title="">[ii]</a> del inglés, <em>input </em>y<em>output</em></p> + </div> + <div id="edn3"> + <p><a href="#_ednref3" name="_edn3" title="">[iii]</a> en castellano, <em>API de Conexión de Pares</em></p> + </div> + <div id="edn4"> + <p><a href="#_ednref4" name="_edn4" title="">[iv]</a> en castellano,<em> Nodo de origen del Audio MediaStream</em></p> + </div> + <div id="edn5"> + <p><a href="#_ednref5" name="_edn5" title="">[v]</a> en castellano, <em>Nodo de destino del Audio MediaStream</em></p> + <div> + <br> + <hr> + <div id="edn1"> + <p><a href="#_ednref1" name="_edn1" title="">[i]</a> del inglés,<em>constraints</em></p> + </div> + </div> + </div> +</div> +<p> </p> +<h2 id="Ver_también">Ver también</h2> +<ul> + <li><a href="/en-US/docs/WebRTC" title="/en-US/docs/WebRTC">WebRTC</a> - la página de introducción a la API</li> + <li><a href="/en-US/docs/WebRTC/navigator.getUserMedia" title="/en-US/docs/WebRTC/navigator.getUserMedia">getUserMedia()</a></li> + <li><a href="/en-US/docs/WebRTC/taking_webcam_photos" title="/en-US/docs/WebRTC/taking_webcam_photos">Taking webcam photos</a> - un tutorial para usar getUserMedia()</li> +</ul> diff --git a/files/es/web/api/navigatorgeolocation/geolocation/index.html b/files/es/web/api/navigator/geolocation/index.html index 94c22ef6b0..94c22ef6b0 100644 --- a/files/es/web/api/navigatorgeolocation/geolocation/index.html +++ b/files/es/web/api/navigator/geolocation/index.html diff --git a/files/es/web/api/navigatorgeolocation/index.html b/files/es/web/api/navigatorgeolocation/index.html deleted file mode 100644 index 0f8895b7b8..0000000000 --- a/files/es/web/api/navigatorgeolocation/index.html +++ /dev/null @@ -1,107 +0,0 @@ ---- -title: NavigatorGeolocation -slug: Web/API/NavigatorGeolocation -tags: - - API -translation_of: Web/API/Geolocation -translation_of_original: Web/API/NavigatorGeolocation ---- -<p>{{APIRef("Geolocation API")}}</p> - -<p><code><strong>NavigatorGeolocation</strong></code> contains a creation method allowing objects implementing it to obtain a {{domxref("Geolocation")}} instance.</p> - -<p>There is no object of type <code>NavigatorGeolocation</code>, but some interfaces, like {{domxref("Navigator")}} implements it.</p> - -<h2 id="Properties">Properties</h2> - -<p><em>The <code>NavigatorGeolocation</code></em><em> interface doesn't inherit any property.</em></p> - -<dl> - <dt>{{domxref("NavigatorGeolocation.geolocation")}} {{readonlyInline}}</dt> - <dd>Returns a {{domxref("Geolocation")}} object allowing accessing the location of the device.</dd> -</dl> - -<h2 id="Methods">Methods</h2> - -<p><em>The </em><em><code>NavigatorGeolocation</code></em><em> interface neither implements, nor inherit any method.</em></p> - -<h2 id="Specifications">Specifications</h2> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Specification</th> - <th scope="col">Status</th> - <th scope="col">Comment</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('Geolocation', '#navi-geo', 'NavigatorGeolocation')}}</td> - <td>{{Spec2('Geolocation')}}</td> - <td>Initial specification.</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_compatibility">Browser compatibility</h2> - -<p>{{ CompatibilityTable() }}</p> - -<div id="compat-desktop"> -<table class="compat-table"> - <tbody> - <tr> - <th>Feature</th> - <th>Chrome</th> - <th>Firefox (Gecko)</th> - <th>Internet Explorer</th> - <th>Opera</th> - <th>Safari</th> - </tr> - <tr> - <td>Basic support</td> - <td>5</td> - <td>{{CompatGeckoDesktop("1.9.1")}}</td> - <td>9</td> - <td>10.60<br> - Removed in 15.0<br> - Reintroduced in 16.0</td> - <td>5</td> - </tr> - </tbody> -</table> -</div> - -<div id="compat-mobile"> -<table class="compat-table"> - <tbody> - <tr> - <th>Feature</th> - <th>Android</th> - <th>Chrome for Android</th> - <th>Firefox Mobile (Gecko)</th> - <th>IE Mobile</th> - <th>Opera Mobile</th> - <th>Safari Mobile</th> - </tr> - <tr> - <td>Basic support</td> - <td>{{CompatUnknown()}}</td> - <td>{{CompatUnknown()}}</td> - <td>{{CompatGeckoMobile("4")}}</td> - <td>{{CompatUnknown()}}</td> - <td>10.60</td> - <td>{{CompatUnknown()}}</td> - </tr> - </tbody> -</table> -</div> - -<h2 id="See_also">See also</h2> - -<ul> - <li><a href="/en-US/docs/WebAPI/Using_geolocation" title="/en-US/docs/WebAPI/Using_geolocation">Using geolocation.</a></li> -</ul> - -<p> </p> diff --git a/files/es/web/api/navigatoronline/eventos_online_y_offline/index.html b/files/es/web/api/navigatoronline/online_and_offline_events/index.html index d4f8a77824..d4f8a77824 100644 --- a/files/es/web/api/navigatoronline/eventos_online_y_offline/index.html +++ b/files/es/web/api/navigatoronline/online_and_offline_events/index.html diff --git a/files/es/web/api/node/insertarantes/index.html b/files/es/web/api/node/insertbefore/index.html index 102d4dfbdd..102d4dfbdd 100644 --- a/files/es/web/api/node/insertarantes/index.html +++ b/files/es/web/api/node/insertbefore/index.html diff --git a/files/es/web/api/node/nodoprincipal/index.html b/files/es/web/api/node/nodoprincipal/index.html deleted file mode 100644 index f6faf58631..0000000000 --- a/files/es/web/api/node/nodoprincipal/index.html +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Nodo.nodoPrincipal -slug: Web/API/Node/nodoPrincipal -tags: - - API - - DOM - - Gecko - - Propiedad -translation_of: Web/API/Node -translation_of_original: Web/API/Node/nodePrincipal ---- -<div> -<div>{{APIRef("DOM")}}</div> -{{Non-standard_header}} - -<p>La propiedad de solo loctura de <code><strong>Nodo.nodePrincipal</strong></code> devuelve el objeto {{Interface("nsIPrincipal")}} representando el contexto de seguridad del nodo actual.</p> - -<p>{{Note("This property exists on all nodes (HTML, XUL, SVG, MathML, etc.), but only if the script trying to use it has chrome privileges.")}}</p> - -<h2 id="Syntax" name="Syntax">Sintaxis</h2> - -<pre class="syntaxbox"><em>principalObj</em> = element.nodePrincipal -</pre> - -<h2 id="Notes" name="Notes">Notas</h2> - -<p>Esta propiedad es de solo lectura; Si intentamos editarla nos lanzará una excepción. Además, esta propiedad tan solo debería ser accesible desde código privilegiado</p> - -<h2 id="Specification" name="Specification">Especificación</h2> - -<p>No hay especificaciones.</p> -</div> - -<p> </p> diff --git a/files/es/web/api/node/elementopadre/index.html b/files/es/web/api/node/parentelement/index.html index 2a2e947a8d..2a2e947a8d 100644 --- a/files/es/web/api/node/elementopadre/index.html +++ b/files/es/web/api/node/parentelement/index.html diff --git a/files/es/web/api/notifications_api/usando_la_api_de_notificaciones/index.html b/files/es/web/api/notifications_api/using_the_notifications_api/index.html index 8220534f63..8220534f63 100644 --- a/files/es/web/api/notifications_api/usando_la_api_de_notificaciones/index.html +++ b/files/es/web/api/notifications_api/using_the_notifications_api/index.html diff --git a/files/es/web/api/pointer_lock_api/index.html b/files/es/web/api/pointer_lock_api/index.html new file mode 100644 index 0000000000..13a27d6d48 --- /dev/null +++ b/files/es/web/api/pointer_lock_api/index.html @@ -0,0 +1,284 @@ +--- +title: API Pointer Lock +slug: WebAPI/Pointer_Lock +translation_of: Web/API/Pointer_Lock_API +--- +<p> </p> + +<p><strong>Pointer Lock </strong>(antes llamado Bloqueo del <em>Mouse</em>) proporciona métodos de entrada basados en el movimiento del ratón a traves del tiempo (es decir, deltas), no sólo la posición absoluta del cursor del <em>mouse</em>. Te da acceso al movimiento <span style="line-height: inherit;">puro </span><span style="line-height: inherit;">del <em>mouse</em>, bloquea el objetivo de los eventos del <em>mouse</em> a un solo elemento, elimina límites en cuanto a que tan lejos puedes mover el <em>mouse</em> en una sola dirección, y quita el cursor de la vista.</span></p> + +<p>Esta API es útil para aplicaciones que requieren bastantes acciones para controlar los movimientos del <em>mouse</em>, rotar objetos y cambiar las entradas. Es especialmente importante para aplicaciones altamente visuales, tales como los que utilizan la perspectiva en primera persona, así como vistas en 3D y modelado.</p> + +<p>Por ejemplo, puedes crear aplicaciones que permiten a los usuarios controlar el ángulo de visión con sólo mover el <em>mouse</em> sin ningún clic, permitiendo liberar <span style="line-height: inherit;">los clics</span><span style="line-height: inherit;"> para otras acciones. Este tipo de entrada del <em>mouse</em> es muy útil para ver mapas, imágenes de satélite, o escenas en primera persona (como en un juego o un vídeo embebido).</span></p> + +<p><strong>Pointer Lock</strong><span style="line-height: inherit;"> te permite acceder a los eventos del </span><em>mouse</em><span style="line-height: inherit;"> incluso cuando el cursor pasa por el límite de la pantalla del navegador. Por ejemplo, los usuarios pueden seguir girando o manipular un modelo 3D moviendo el </span><em>mouse</em><span style="line-height: inherit;"> sin fin. Sin </span><strong>Pointer Lock</strong><span style="line-height: inherit;">, la rotación o la manipulación se detiene en el momento en que el cursor alcanza el borde de la pantalla del navegador. Los jugadores se verán particularmente encantados con esta característica, ya que anciosamente pueden hacer clic en los botones y arrastrar el cursor del </span><em>mouse</em><span style="line-height: inherit;"> de un lado a otro sin tener que preocuparse por salir de la zona de juego ni de cliquear accidentalmente otra aplicación que podría llevar al </span><em>mouse</em><span style="line-height: inherit;"> fuera del juego. Una tragedia!</span></p> + +<h2 id="basics" name="basics">Conceptos Básicos</h2> + +<p><strong>Pointer Lock</strong><strong style="line-height: inherit;"> </strong><span style="line-height: inherit;">está relacionado con la <em>mouse capture</em>. </span><em>mouse capture </em><span style="line-height: inherit;">proporciona la entrega continua de eventos a un elemento de destino, mientras que el <em>mouse</em> se arrastra, pero se detiene cuando se suelta el clic. </span><strong>Pointer Lock</strong><span style="line-height: inherit;"> es diferente de </span><em>mouse capture </em><span style="line-height: inherit;">en las siguientes maneras:</span></p> + +<ul> + <li><span style="line-height: 1.5em;">Es persistente. <strong style="line-height: normal;">Pointer Lock</strong> no libera el <em>mouse</em> hasta que se haga una llamada explícita a la API o el usuario utilize un gesto concreto de lanzamiento.</span></li> + <li><span style="line-height: 1.5em;">No está limitado por los limites del navegador o la pantalla.</span></li> + <li>Envia continuamente eventos independientemente del estado del clic del <em>mouse</em>.</li> + <li>Oculta el cursor.</li> +</ul> + +<h2 id="example" name="example">Ejemplo</h2> + +<p>El siguiente es un ejemplo de cómo se puede configurar <strong>Pointer Lock</strong> en su página web.</p> + +<pre class="brush: js"><button onclick="lockPointer();">Lock it!</button> +<div id="pointer-lock-element"></div> +<script> +// Nota: Al momento de escribir esto, sólo Mozilla y WebKit apoyan Pointer Lock. + +// El elemento que servirá para pantalla completa y pointer lock. +var elem; + +document.addEventListener("mousemove", function(e) { + var movementX = e.movementX || + e.mozMovementX || + e.webkitMovementX || + 0, + movementY = e.movementY || + e.mozMovementY || + e.webkitMovementY || + 0; + + // Imprime los valores delta del movimiento del mouse + console.log("movementX=" + movementX, "movementY=" + movementY); +}, false); + +function fullscreenChange() { + if (document.webkitFullscreenElement === elem || + document.mozFullscreenElement === elem || + document.mozFullScreenElement === elem) { // Older API upper case 'S'. + // El elemento esta en pantalla completa, ahora podemos hacer el request de pointer lock + elem.requestPointerLock = elem.requestPointerLock || + elem.mozRequestPointerLock || + elem.webkitRequestPointerLock; + elem.requestPointerLock(); + } +} + +document.addEventListener('fullscreenchange', fullscreenChange, false); +document.addEventListener('mozfullscreenchange', fullscreenChange, false); +document.addEventListener('webkitfullscreenchange', fullscreenChange, false); + +function pointerLockChange() { + if (document.mozPointerLockElement === elem || + document.webkitPointerLockElement === elem) { + console.log("Pointer Lock was successful."); + } else { + console.log("Pointer Lock was lost."); + } +} + +document.addEventListener('pointerlockchange', pointerLockChange, false); +document.addEventListener('mozpointerlockchange', pointerLockChange, false); +document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + +function pointerLockError() { + console.log("Error while locking pointer."); +} + +document.addEventListener('pointerlockerror', pointerLockError, false); +document.addEventListener('mozpointerlockerror', pointerLockError, false); +document.addEventListener('webkitpointerlockerror', pointerLockError, false); + +function lockPointer() { + elem = document.getElementById("pointer-lock-element"); + // Start by going fullscreen with the element. Current implementations + // require the element to be in fullscreen before requesting pointer + // lock--something that will likely change in the future. + elem.requestFullscreen = elem.requestFullscreen || + elem.mozRequestFullscreen || + elem.mozRequestFullScreen || // Older API upper case 'S'. + elem.webkitRequestFullscreen; + elem.requestFullscreen(); +} +</script> +</pre> + +<h2 id="method_overview" name="method_overview">Propiedades/Métodos</h2> + +<p>La API de bloque de puntero ,similar a la API de Fullscreen,extiende del elemento DOM agregando un nuevo método, <code>requestPointerLock</code>, la cual es dependiente del vendedor(del navegador). Puede escribirse como:</p> + +<pre class="idl"><span class="idlInterface" id="idl-def-MouseLockable"><span class="idlInterface" id="idl-def-MouseLockable">element.webkitRequestPointerLock(); // para Chrome</span></span> + +element.mozRequestPointerLock(); // para Firefox +</pre> + +<p>Current implementations of <code>requestPointerLock</code> are tightly bound to <code>requestFullScreen</code> and the Fullscreen API. Before an element can be pointer locked, it must first enter the fullscreen state. As demonstrated above, the process of locking the pointer is asynchronous, with events (<code>pointerlockchange</code>, <code>pointerlockerror</code>) indicating the success or failure of the request. This matches how the Fullscreen API works, with its <code>requestFullScreen</code> method and <code>fullscreenchange</code> and <code>fullscreenerror</code> events.</p> + +<p>The Pointer lock API also extends the <code>document</code> interface, adding both a new property and a new method. The new property is used for accessing the currently locked element (if any), and is named <code>pointerLockElement</code>, which is vendor-prefixed for now. The new method on <code>document</code> is <code>exitPointerLock</code> and, as the name implies, it is used to exit Pointer lock.</p> + +<p>The <code>pointerLockElement</code> property is useful for determining if any element is currently pointer locked (e.g., for doing a boolean check) and also for obtaining a reference to the locked element, if any. Here is an example of both uses:</p> + +<pre class="idl"><span class="idlInterface" id="idl-def-MouseLockable"><span class="idlInterface" id="idl-def-MouseLockable">document.pointerLockElement = document.pointerLockElement || + document.mozPointerLockElement || + document.webkitPointerLockElement;</span></span> + +// 1) Used as a boolean check--are we pointer locked? +if (!!document.pointerLockElement) { + // pointer is locked +} else { + // pointer is not locked +} + +// 2) Used to access the pointer locked element +if (document.pointerLockElement === someElement) { + // someElement is currently pointer locked +} +</pre> + +<p>The <code>document</code>'s <code>exitPointerLock</code> method is used to exit pointer lock, and like requestPointerLock, works asynchrounously using the <code>pointerlockchange</code> and <code>pointerlockerror</code> events:</p> + +<pre class="idl"><span class="idlInterface" id="idl-def-MouseLockable"><span class="idlInterface" id="idl-def-MouseLockable">document.exitPointerLock = document.exitPointerLock || + document.mozExitPointerLock || + document.webkitExitPointerLock;</span></span> + +function pointerLockChange() { + <span class="idlInterface" id="idl-def-MouseLockable"><span class="idlInterface" id="idl-def-MouseLockable">document.pointerLockElement = document.pointerLockElement || + document.mozPointerLockElement || + document.webkitPointerLockElement;</span></span> + + if (!!document.pointerLockElement) { + console.log("Still locked."); + } else { + console.log("Exited lock."); + } +} + +document.addEventListener('pointerlockchange', pointerLockChange, false); +document.addEventListener('mozpointerlockchange', pointerLockChange, false); +document.addEventListener('webkitpointerlockchange', pointerLockChange, false); + +// Attempt to unlock +document.exitPointerLock(); +</pre> + +<h2 id="mouselocklostevent" name="mouselocklostevent">pointerlockchange event</h2> + +<p>When the Pointer lock state changes—for example, when calling <code>requestPointerLock</code>, <code>exitPointerLock</code>, the user pressing the ESC key, etc.—the <code>pointerlockchange</code> event is dispatched to the <code>document</code>. This is a simple event and contains no extra data.</p> + +<div class="note">This event is currently prefixed as <code>mozpointerlockchange</code> in Firefox and <code>webkitpointerlockchange</code> in Chrome. </div> + +<h2 id="mouselocklostevent" name="mouselocklostevent">pointerlockerror event</h2> + +<p>When there is an error caused by calling <code>requestPointerLock</code> or <code>exitPointerLock</code>, the <code>pointerlockerror</code> event is dispatched to the <code>document</code>. This is a simple event and contains no extra data.</p> + +<div class="note">This event is currently prefixed as <code>mozpointerlockerror</code> in Firefox and <code>webkitpointerlockerror</code> in Chrome. </div> + +<h2 id="extensions" name="extensions">Extensions to mouse events</h2> + +<p>The Pointer lock API extends the normal <code>MouseEvent</code> with movement attributes.</p> + +<pre class="idl"><span class="idlInterface" id="idl-def-MouseEvent">partial interface <span class="idlInterfaceID">MouseEvent</span> { +<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>long</a></span> <span class="idlAttrName"><a href="http://dvcs.w3.org/hg/webevents/raw-file/default/mouse-lock.html#widl-MouseEvent-movementX">movementX</a></span>;</span> +<span class="idlAttribute"> readonly attribute <span class="idlAttrType"><a>long</a></span> <span class="idlAttrName"><a href="http://dvcs.w3.org/hg/webevents/raw-file/default/mouse-lock.html#widl-MouseEvent-movementY">movementY</a></span>;</span> +};</span></pre> + +<div class="note">The movement attributes are currently prefixed as <code>.mozMovementX</code> and <code>.mozMovementY</code> in Firefox, and<code>.webkitMovementX</code> and <code>.webkitMovementY</code> in Chrome.</div> + +<p>Two new parameters to mouse events—<code>movementX</code> and <code>movementY</code>—provide the change in mouse positions. The values of the parameters are the same as the difference between the values of <a href="/en/DOM/MouseEvent" title="en/DOM/Event/UIEvent/MouseEvent"><code>MouseEvent</code></a> properties, <code>screenX</code> and <code>screenY</code>, which are stored in two subsequent <code>mousemove</code> events, <code>eNow</code> and <code>ePrevious</code>. In other words, the Pointer lock parameter <code>movementX = eNow.screenX - ePrevious.screenX</code>.</p> + +<h3 id="locked_state" name="locked_state">Locked state</h3> + +<p>When Pointer lock is enabled, the standard <code>MouseEvent</code> properties <code>clientX</code>, <code>clientY</code>, <code>screenX</code>, and <code>screenY</code> are held constant, as if the mouse is not moving. The <code>movementX</code> and <code>movementY</code> properties continue to provide the mouse's change in position. There is no limit to <code>movementX</code> and <code>movementY</code> values if the mouse is continuously moving in a single direction. The concept of the mouse cursor does not exist and the cursor cannot move off the window or be clamped by a screen edge.</p> + +<h3 id="unlocked_state" name="unlocked_state">Unlocked state</h3> + +<p>The parameters <code>movementX</code> and <code>movementY</code> are valid regardless of the mouse lock state, and are available even when unlocked for convenience.</p> + +<p>When the mouse is unlocked, the system cursor can exit and re-enter the browser window. If that happens, <code>movementX</code> and <code>movementY</code> could be set to zero.</p> + +<h2 id="iframe_limitations">iframe limitations</h2> + +<p>Pointer lock can only lock one iframe at a time. If you lock one iframe, you cannot try to lock another iframe and transfer the target to it; Pointer lock will error out. To avoid this limitation, first unlock the locked iframe, and then lock the other.</p> + +<p>While iframes work by default, "sandboxed" iframes block Pointer lock. The ability to avoid this limitation, in the form of the attribute/value combination <code><iframe sandbox="allow-pointer-lock"></code>, is expected to appear in Chrome soon.</p> + +<h2 id="Specifications">Specifications</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">Comment</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('Pointer Lock')}}</td> + <td>{{Spec2('Pointer Lock')}}</td> + <td>Initial specification.</td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">Browser compatibility</h2> + +<p>{{ CompatibilityTable() }}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Basic support</td> + <td> + <p>Targeting 23{{ property_prefix("webkit") }}*</p> + + <p>See <a class="external" href="http://code.google.com/p/chromium/issues/detail?id=72754" title="http://code.google.com/p/chromium/issues/detail?id=72754">CR/72574</a></p> + </td> + <td> + <p>{{ CompatGeckoDesktop("14.0") }}</p> + + <p>{{bug("633602") }}</p> + </td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + </tr> + </tbody> +</table> +</div> + +<p>* Requires the feature be enabled in <code>about:flags</code> or Chrome started with the <code>--enable-pointer-lock</code> flag.</p> + +<h2 id="See_also" name="See_also">See also</h2> + +<p><a href="/en/DOM/MouseEvent" title="en/DOM/Event/UIEvent/MouseEvent">MouseEvent</a></p> diff --git a/files/es/web/api/push_api/using_the_push_api/index.html b/files/es/web/api/push_api/using_the_push_api/index.html deleted file mode 100644 index 05d101e5fa..0000000000 --- a/files/es/web/api/push_api/using_the_push_api/index.html +++ /dev/null @@ -1,433 +0,0 @@ ---- -title: Usando la API Push -slug: Web/API/Push_API/Using_the_Push_API -translation_of: Web/API/Push_API -translation_of_original: Web/API/Push_API/Using_the_Push_API ---- -<p class="summary"><span class="seoSummary">La W3C <a href="/en-US/docs/Web/API/Push_API">Push API</a> offers some exciting new functionality for developers to use in web applications: this article provides an introduction to getting Push notifications setup and running, with a simple demo.</span></p> - -<p>La habilidad de enviar mensajes o notificaciones de un servidor a un cliente en cualquier momento —si la aplicación está activa en su sitema o no—es algo que ha sido disfrutado por las plataformas nativas durante algún tiempo, y esta finalmente llega a la web! el soporte para muchos push está ahora disponible en Firefox 43+ y Chrome 42+ en escritorio, esperamos seguir pronto con las plataformas moviles. {{domxref("PushMessageData")}} actualmente solo es soportada experimentalmente en Firefox (44+), y la implementación está sujeta a cambios.</p> - -<div class="note"> -<p><strong>Note</strong>: Early versions of Firefox OS used a proprietary version of this API called <a href="/en-US/docs/Web/API/Simple_Push_API">Simple Push</a>. This is being rendered obsolete by the Push API standard.</p> -</div> - -<h2 id="Demo_las_bases_de_una_simple_app_de_servidor_de_chat">Demo: las bases de una simple app de servidor de chat</h2> - -<p>La demo que hemos creado proporciona los principios de una simple app de chat. Esta presenta un formulario para que ingreses un identificador de chat y un boton que al presionar se suscriba a los mensajes push.</p> - -<p>En este punto, el nombre de los nuevos suscriptores aparecerá en la lista de suscriptores, junto con un campo de texto y un botón de envío para permitir al suscriptor enviar mensajes.</p> - -<p>At this point, the new subscriber's name will appear in the subscriber's list, along with a text field and submit button to allow the subscriber to send messages.</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/11823/push-api-demo.png" style="border: 1px solid black; display: block; height: 406px; margin: 0px auto; width: 705px;"></p> - -<p>Para correr la demo, siga las instrucciones de <a href="https://github.com/chrisdavidmills/push-api-demo">push-api-demo README</a>. Tenga en cuenta que el componente server-side aún nesecita un poco de trabajo para que funcione en chrome y se ejecute de una manera más rezonable. Pero los aspectos de push pueden ser explicados a fondo; Nos sumergiremos en ella después de revisar las tecnologías en juego.</p> - -<h2 id="Visión_de_la_tecnología">Visión de la tecnología</h2> - -<p>Esta sección proporciona un esquema de qué tecnologías están involucradas en este ejemplo.</p> - -<p>Los mensajes web push hacen parte de la familia tecnológica <a href="/en-US/docs/Web/API/Service_Worker_API">service workers</a>; en particular, se requiere que un service worker esté activo en la página para recibir mensajes push. el service worker recibe el mensaje push, y acontinuación depende de usted cómo notificar a la página. Usted puede:</p> - -<p>Web Push messages are part of the <a href="/en-US/docs/Web/API/Service_Worker_API">service workers</a> technology family; in particular, a service worker is required to be active on the page for it to receive push messages. The service worker receives the push message, and then it is up to you how to then notify the page. You can:</p> - -<ul> - <li>Enviar una <a href="/en-US/docs/Web/API/Notifications_API">notificación web</a> emergente para alertar al usuario. Esto requiere que sean concedidos los permisos para enviar el mensaje push.</li> - <li>Envía un mensaje a la página principal a través de un {{domxref("MessageChannel")}}.</li> -</ul> - -<p>A menudo una combinación de los dos será necesario; La demo a continuación muestra un ejemplo de cada uno.</p> - -<div class="note"> -<p><strong>Nota</strong>: Usted necesita algún tipo de código que se ejecute en el servidor para manejar el cifrado de punto final/datos y enviar las solicitudes de notificaciones push. En nuestra demostración hemos creado un servidor quick-and-dirty usando <a href="https://nodejs.org/">NodeJS</a>.</p> -</div> - -<p>El service worker también tiene que suscribirse al servicio de mensajería psuh. Cada sesión recibe su propio punto final único cuando se suscribe al servicio de mensajería. Este punto final es obtenido desde la propiedad ({{domxref("PushSubscription.endpoint")}}) en el objeto de suscripción. Este punto final se puede enviar a su servidor y se utiliza para enviar un mensaje al service worker asctivo en esta sesión. Cada navegador tiene su propio servidor de mensajería push para manejar el envío del mensaje push.</p> - -<h3 id="Encryption">Encryption</h3> - -<div class="note"> -<p><strong>Note</strong>: For an interactive walkthrough, try JR Conlin's <a href="https://jrconlin.github.io/WebPushDataTestPage/">Web Push Data Encryption Test Page</a>.</p> -</div> - -<p>To send data via a push message, it needs to be encrypted. This requires a public key created using the {{domxref("PushSubscription.getKey()")}} method, which relies upon some complex encryption mechanisms that are run server-side; read <a href="https://tools.ietf.org/html/draft-ietf-webpush-encryption-01">Message Encryption for Web Push</a> for more details. As time goes on, libraries will appear to handle key generation and encryption/decryption of push messages; for this demo we used Marco Castelluccio's NodeJS <a href="https://github.com/marco-c/web-push">web-push library</a>.</p> - -<div class="note"> -<p><strong>Note</strong>: There is also another library to handle the encryption with a Node and Python version available, see <a href="https://github.com/martinthomson/encrypted-content-encoding">encrypted-content-encoding</a>.</p> -</div> - -<h3 id="Push_workflow_summary">Push workflow summary</h3> - -<p>To summarize, here is what is needed to implement push messaging. You can find more details about specific parts of the demo code in subsequent sections.</p> - -<ol> - <li>Request permission for web notifications, or anything else you are using that requires permissions.</li> - <li>Register a service worker to control the page by calling {{domxref("ServiceWorkerContainer.register()")}}.</li> - <li>Subscribe to the push messaging service using {{domxref("PushManager.subscribe()")}}.</li> - <li>Retrieve the endpoint associated with the subscription and generate a client public key ({{domxref("PushSubscription.endpoint")}} and {{domxref("PushSubscription.getKey()")}}. Note that <code>getKey()</code> is currently experimental and Firefox only.)</li> - <li>Send these details to the server so it can send push message when required. This demo uses {{domxref("XMLHttpRequest")}}, but you could use <a href="/en-US/docs/Web/API/Fetch_API">Fetch</a>.</li> - <li>If you are using the <a href="/en-US/docs/Web/API/Channel_Messaging_API">Channel Messaging API</a> to comunicate with the service worker, set up a new message channel ({{domxref("MessageChannel.MessageChannel()")}}) and send <code>port2</code> over to the service worker by calling {{domxref("Worker.postMessage()")}} on the service worker, in order to open up the communication channel. You should also set up a listener to respond to messages sent back from the service worker.</li> - <li>On the server side, store the endpoint and any other required details so they are available when a push message needs to be sent to a push subscriber (we are using a simple text file, but you could use a database or whatever you like). In a production app, make sure you keep these details hidden, so malicious parties can't steal endpoints and spam subscribers with push messages.</li> - <li>To send a push message, you need to send an HTTP <code>POST</code> to the endpoint URL. The request must include a <code>TTL</code> header that limits how long the message should be queued if the user is not online. To include payload data in your request, you must encrypt it (which involves the client public key). In our demo, we are using the <a href="https://github.com/marco-c/web-push">web-push</a> module, which handles all the hard work for you.</li> - <li>Over in your service worker, set up a <code>push</code> event handler to respond to push messages being received. - <ol> - <li>If you want to respond by sending a channel message back to the main context (see Step 6) you need to first get a reference to the <code>port2</code> we sent over to the service worker context ({{domxref("MessagePort")}}). This is available on the {{domxref("MessageEvent")}} object passed to the <code>onmessage</code> handler ({{domxref("ServiceWorkerGlobalScope.onmessage")}}). Specifically, this is found in the <code>ports</code> property, index 0. Once this is done, you can send a message back to <code>port1</code>, using {{domxref("MessagePort.postMessage()")}}.</li> - <li>If you want to respond by firing a system notification, you can do this by calling {{domxref("ServiceWorkerRegistration.showNotification()")}}. Note that in our code we have run this inside an {{domxref("ExtendableEvent.waitUntil()")}} method — this extends the lifetime of the event until after the notification has been fired, so we can make sure everything has happened that we want to happen.<span id="cke_bm_307E" style="display: none;"> </span></li> - </ol> - </li> -</ol> - -<h2 id="Construyendo_la_demo">Construyendo la demo</h2> - -<p>Vamos a ensayar el código para esta demo, podemos empezar a entender como trabaja todo esto.</p> - -<ul> - <li> - <h3 id="HTML_y_CSS">HTML y CSS</h3> - </li> -</ul> - -<p>No hay nada destacalbe sobre el HTML y el CSS para la demo; el HTML inicialmente contiene un simple formulario que permite introducir un udentificador para la sala de chat, un boton que al hacer click se suscribe a las notificaciones push, y dos listas con los suscriptores y los mensajes. Una vez suscrito, aparecerán controles adicionales para permitir al usuario actual escribir mensajes en el chat.</p> - -<p>El CSS ha sido muy minimo para no desvirtuar la explicación de la funcionalidad Push Api.</p> - -<ul> - <li> - <h3 id="El_archivo_JavaScript_principal">El archivo JavaScript principal</h3> - </li> -</ul> - -<p>El JavaScript es obviamente más sustancial. Echemos un vistazo al archivo JavaScript principal.</p> - -<h4 id="Variables_y_configuración_inicial">Variables y configuración inicial</h4> - -<p>Para iniciar, nosotros declaramos algunas variables a usar en nuestra app:</p> - -<pre class="brush: js">var isPushEnabled = false; -var useNotifications = false; - -var subBtn = document.querySelector('.subscribe'); -var sendBtn; -var sendInput; - -var controlsBlock = document.querySelector('.controls'); -var subscribersList = document.querySelector('.subscribers ul'); -var messagesList = document.querySelector('.messages ul'); - -var nameForm = document.querySelector('#form'); -var nameInput = document.querySelector('#name-input'); -nameForm.onsubmit = function(e) { - e.preventDefault() -}; -nameInput.value = 'Bob';</pre> - -<p>Primero, tenemos dos boleanos para hacer un seguimiento si se a suscrito a push, y si ha permitido las notificaciones.</p> - -<p>A continuación, tomamos una referencia al suscrito/no-suscrito <code>{{htmlelement("button")}}</code>, y se declaran variables para almacenar referencias a nuestro mensaje enviado boton/entrada (sólo se crean cuando la suscripsión es correcta.)</p> - -<p>Las siguientes variables toman referencia a los trés elementos principales <code>{{htmlelement("div")}}</code> en el diseño, por lo que podemos insertar elementos en ellos (por ejemplo cuando aparezca el botón <em>envíar el mensaje de chat</em> o el mensaje de chat aparezca en la lista de <em>mensajes</em>.)</p> - -<p>Finalmente tomamos referencia a nuestro formulario de selección de nombre y el elemento <code>{{htmlelement("input")}},</code> damos a la entrada un valor por defecto, y usamos <code><a href="/en-US/docs/Web/API/Event/preventDefault">preventDefault()</a></code> para detener el envío del formulario cuando este es enviado pulsando return.</p> - -<p>A continuación, pedimos permiso para enviar las notificaciones web, usando <code>{{domxref("Notification.requestPermission","requestPermission()")}}</code>:</p> - -<pre class="brush: js">Notification.requestPermission();</pre> - -<p>Ahora ejecutamos una sección de código cuando se dispara el <code><a href="/en-US/docs/Web/API/GlobalEventHandlers/onload">onload</a></code>, para empezar el proceso de inicialización de la app cuando se carga pro primera vez. En primer lugar añadimos un detector de eventos de clik al botón Sucribirse/unsubscribe que ejecuta nuestra funcion <code>unsubscribe()</code> si actualmente estamos suscritos (<code>isPushEnabled</code> is <code>true</code>), y <code>subscribe()</code> de la otra manera:</p> - -<pre class="brush: js">window.addEventListener('load', function() { - subBtn.addEventListener('click', function() { - if (isPushEnabled) { - unsubscribe(); - } else { - subscribe(); - } - });</pre> - -<p>A continuación verificamos el service worked es soportado. Si es así, registramos un service worker usando <code>{{domxref("ServiceWorkerContainer.register()")}}</code>, y ejecutando nuestra función <code>initialiseState()</code>. Si no es así, entregamos un mensaje de error a la consola.</p> - -<pre class="brush: js"> // Check that service workers are supported, if so, progressively - // enhance and add push messaging support, otherwise continue without it. - if ('serviceWorker' in navigator) { - navigator.serviceWorker.register('sw.js').then(function(reg) { - if(reg.installing) { - console.log('Service worker installing'); - } else if(reg.waiting) { - console.log('Service worker installed'); - } else if(reg.active) { - console.log('Service worker active'); - } - - initialiseState(reg); - }); - } else { - console.log('Service workers aren\'t supported in this browser.'); - } -}); -</pre> - -<p>La siguiente cosa en el código es la función <code>initialiseState()</code> — para el codigo completo comentado, mira en <a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/main.js"><code>initialiseState()</code> source on Github</a> (no lo estamos repitiendo aquí por brevedad.)</p> - -<p><code>initialiseState()</code> primero comprueba si las notificaciones son soportadas en los service workers, entonces establece la variable <code>useNotifications</code> a verdadero. A continuación comprueba si dichas notificaciones están permitidas por el usuario y si los mensajes push están soportados, y reacciona deacuerdo a cada uno.</p> - -<p>Finalmente, se usa <code>{{domxref("ServiceWorkerContainer.ready()")}}</code> para esperar a que el service worker esté activo y listo para hacer las cosas. Una vez se revuelva el promise, recuperamos nuestra suscripsión para enviar los mensajes push usando la propiedad <code>{{domxref("ServiceWorkerRegistration.pushManager")}}</code>, que devuelve un objeto <code>{{domxref("PushManager")}}</code> cuando llamamos a <code>{{domxref("PushManager.getSubscription()")}}</code>. Una vez la segunda promesa interna se resuelva, habilitamos el botón subscribe/unsubscribe (<code>subBtn.disabled = false;</code>), y verificamos que tenemos un objeto suscripsión para trabajar.</p> - -<p>Si lo hacemos, entonces ya estamos suscritos. Esto es posible cuando la app no está abierta en el navegador; el service worker aun puede ser activado en segundo plano. si estamos suscritos, actualizamos la UI para mostrar que estamos suscritos por la actualizacion del label en el botón, entonces establecemos <code>isPushEnabled</code> to <code>true</code>, toma el punto final de suscripsión desde <code>{{domxref("PushSubscription.endpoint")}}</code>, genera una public key usando <code>{{domxref("PushSubscription.getKey()")}}</code>, y ejecutando nuestra función <code>updateStatus()</code>, que como verá más adelante se comunica con el servidor.</p> - -<p>Como un bonus añadido, configuramos un nuevo <code>{{domxref("MessageChannel")}}</code> usando el constructor <code>{{domxref("MessageChannel.MessageChannel()")}}</code>, toma una referencia al service worker activo usando <code>{{domxref("ServiceworkerRegistration.active")}}</code>, luego configure un canal entre el contexto principal del navegador y el contexto del service worker usando <code>{{domxref("Worker.postMessage()")}}</code>. El contexto del navegador recive mensajes en <code>{{domxref("MessageChannel.port1")}}</code>; Cuando esto suceda, ejecutamos la función <code>handleChannelMessage()</code> para decidir que hacer con esos datos (mirar la sección <code>{{anch("Handling channel messages sent from the service worker")}}</code> ).</p> - -<h4 id="Subscribing_and_unsubscribing">Subscribing and unsubscribing</h4> - -<p>Ahora regresamos la atención a las funciones <code>subscribe()</code> y <code>unsubscribe()</code> usadas para subscribe/unsubscribe al servicion de notificaciones push.</p> - -<p>In the case of subscription, we again check that our service worker is active and ready by calling {{domxref("ServiceWorkerContainer.ready()")}}. When the promise resolves, we subscribe to the service using {{domxref("PushManager.subscribe()")}}. If the subscription is successful, we get a {{domxref("PushSubscription")}} object, extract the subscription endpoint from this and generate a public key (again, {{domxref("PushSubscription.endpoint")}} and {{domxref("PushSubscription.getKey()")}}), and pass them to our <code>updateStatus()</code> function along with the update type (<code>subscribe</code>) to send the necessary details to the server.</p> - -<p>We also make the necessary updates to the app state (set <code>isPushEnabled</code> to <code>true</code>) and UI (enable the subscribe/unsubscribe button and set its label text to show that the next time it is pressed it will unsubscribe.)</p> - -<p>The <code>unsubscribe()</code> function is pretty similar in structure, but it basically does the opposite; the most notable difference is that it gets the current subscription using {{domxref("PushManager.getSubscription()")}}, and when that promise resolves it unsubscribes using {{domxref("PushSubscription.unsubscribe()")}}.</p> - -<p>Appropriate error handling is also provided in both functions. </p> - -<p>We only show the <code>subscribe()</code> code below, for brevity; see the full <a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/main.js">subscribe/unsubscribe code on Github</a>.</p> - -<pre class="brush: js">function subscribe() { - // Disable the button so it can't be changed while - // we process the permission request - - subBtn.disabled = true; - - navigator.serviceWorker.ready.then(function(reg) { - reg.pushManager.subscribe({userVisibleOnly: true}) - .then(function(subscription) { - // The subscription was successful - isPushEnabled = true; - subBtn.textContent = 'Unsubscribe from Push Messaging'; - subBtn.disabled = false; - - // Update status to subscribe current user on server, and to let - // other users know this user has subscribed - var endpoint = subscription.endpoint; - var key = subscription.getKey('p256dh'); - updateStatus(endpoint,key,'subscribe'); - }) - .catch(function(e) { - if (Notification.permission === 'denied') { - // The user denied the notification permission which - // means we failed to subscribe and the user will need - // to manually change the notification permission to - // subscribe to push messages - console.log('Permission for Notifications was denied'); - - } else { - // A problem occurred with the subscription, this can - // often be down to an issue or lack of the gcm_sender_id - // and / or gcm_user_visible_only - console.log('Unable to subscribe to push.', e); - subBtn.disabled = false; - subBtn.textContent = 'Subscribe to Push Messaging'; - } - }); - }); -}</pre> - -<h4 id="Updating_the_status_in_the_app_and_server">Updating the status in the app and server</h4> - -<p>The next function in our main JavaScript is <code>updateStatus()</code>, which updates the UI for sending chat messages when subscribing/unsubscribing and sends a request to update this information on the server.</p> - -<p>The function does one of three different things, depending on the value of the <code>statusType</code> parameter passed into it:</p> - -<ul> - <li><code>subscribe</code>: The button and text input for sending chat messages are created and inserted into the UI, and an object is sent to the server via XHR containing the status type (<code>subscribe</code>), username of the subscriber, subscription endpoint, and client public key.</li> - <li><code>unsubscribe</code>: This basically works in the opposite way to subscribe — the chat UI elements are removed, and an object is sent to the server to tell it that the user has unsubscribed.</li> - <li><code>init</code>: This is run when the app is first loaded/initialised — it creates the chat UI elements, and sends an object to the server to tell it that which user has reinitialised (reloaded.)</li> -</ul> - -<p>Again, we have not included the entire function listing for brevity. Examine the <a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/main.js">full <code>updateStatus()</code> code on Github</a>.</p> - -<h4 id="Handling_channel_messages_sent_from_the_service_worker">Handling channel messages sent from the service worker</h4> - -<p>As mentioned earlier, when a <a href="/en-US/docs/Web/API/Channel_Messaging_API">channel message</a> is received from the service worker, our <code>handleChannelMessage()</code> function is called to handle it. This is done by our handler for the {{event("message")}} event, {{domxref("channel.port1.onmessage")}}:</p> - -<pre class="brush: js">channel.port1.onmessage = function(e) { - handleChannelMessage(e.data); -}</pre> - -<p>This occurs when the <a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/sw.js#L8">service worker sends a channel message over</a>.</p> - -<p>The <code>handleChannelMessage()</code> function looks like this:</p> - -<pre class="brush: js">function handleChannelMessage(data) { - if(data.action === 'subscribe' || data.action === 'init') { - var listItem = document.createElement('li'); - listItem.textContent = data.name; - subscribersList.appendChild(listItem); - } else if(data.action === 'unsubscribe') { - for(i = 0; i < subscribersList.children.length; i++) { - if(subscribersList.children[i].textContent === data.name) { - subscribersList.children[i].parentNode.removeChild(subscribersList.children[i]); - } - } - nameInput.disabled = false; - } else if(data.action === 'chatMsg') { - var listItem = document.createElement('li'); - listItem.textContent = data.name + ": " + data.msg; - messagesList.appendChild(listItem); - sendInput.value = ''; - } -}</pre> - -<p>What happens here depends on what the <code>action</code> property on the <code>data</code> object is set to:</p> - -<ul> - <li><code>subscribe</code> or <code>init</code> (at both startup and restart, we need to do the same thing in this sample): An {{htmlelement("li")}} element is created, its text content is set to <code>data.name</code> (the name of the subscriber), and it is appended to the subscribers list (a simple {{htmlelement("ul")}} element) so there is visual feedback that a subscriber has (re)joined the chat.</li> - <li><code>unsubscribe</code>: We loop through the children of the subscribers list, find the one whose text content is equal to <code>data.name</code> (the name of the unsubscriber), and delete that node to provide visual feedback that someone has unsubscribed.</li> - <li><code>chatMsg</code>: In a similar manner to the first case, an {{htmlelement("li")}} element is created, its text content is set to <code>data.name + ": " + data.msg</code> (so for example "Chris: This is my message"), and it is appended to the chat messages list; this is how the chat messages appear on the UI for each user.</li> -</ul> - -<div class="note"> -<p><strong>Note</strong>: We have to pass the data back to the main context before we do DOM updates because service workers don't have access to the DOM. You should be aware of the limitations of service workers before attemping to ue them. Read <a href="/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers">Using Service Workers</a> for more details.</p> -</div> - -<h4 id="Sending_chat_messages">Sending chat messages</h4> - -<p>When the <em>Send Chat Message</em> button is clicked, the content of the associated text field is sent as a chat message. This is handled by the <a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/main.js"><code>sendChatMessage()</code> function</a> (again, not shown in full for brevity). This works in a similar way to the different parts of the <code>updateStatus()</code> function (see {{anch("Updating the status in the app and server")}}) — we retrieve an endpoint and public key via a {{domxref("PushSubscription")}} object, which is itself retrieved via {{domxref("ServiceWorkerContainer.ready()")}} and {{domxref("PushManager.subscribe()")}}. These are sent to the server via {{domxref("XMLHttpRequest")}} in a message object, along with the name of the subscribed user, the chat message to send, and a <code>statusType</code> of <code>chatMsg</code>.</p> - -<h3 id="The_server">The server</h3> - -<p>As mentioned above, we need a server-side component in our app, to handle storing subscription details, and send out push messages when updates occur. We've hacked together a quick-and-dirty server using <a href="http://nodejs.org/">NodeJS</a> (<code><a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/server.js">server.js</a></code>), which handles the XHR requests sent by our client-side JavaScript code.</p> - -<p>It uses a text file (<code><a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/endpoint.txt">endpoint.txt</a></code>) to store subscription details; this file starts out empty. There are four different types of request, marked by the <code>statusType</code> property of the object sent over in the request; these are the same as those understood client-side, and perform the required server actions for that same situation. Here's what each means in the context of the server:</p> - -<ul> - <li><code>subscribe</code>: The server adds the new subscriber's details into the subscription data store (<code><a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/endpoint.txt">endpoint.txt</a></code>), including the endpoint, and then sends a push message to all the endpoints it has stored to tell each subscriber that someone new has joined the chat.</li> - <li><code>unsubscribe</code>: The server finds the sending subscriber's details in the subscription store and removes it, then sends a push message to all remaining subscribers telling them the user has unsubscribed.</li> - <li><code>init</code>: The server reads all the current subscribers from the text file, and sends each one a push message to tell them a user has initialized (rejoined) the chat.</li> - <li><code>chatMsg</code>: Sent by a subscriber that wishes to deliver a message to all users; the server reads the list of all current subscribers from the subscription store file, then sends each one a push message containing the new chat message they should display.</li> -</ul> - -<p>A couple more things to note:</p> - -<ul> - <li>We are using the Node.js <a href="https://nodejs.org/api/https.html">https module</a> to create the server, because for security purposes, service workers only work on a secure connection. This is why we need to include the <code>.pfx</code> security cert in the app, and reference it when creating the server in the Node code.</li> - <li>When you send a push message without data, you simply send it to the endpoint URL using an HTTP <code>POST</code> request. However, when the push message contains data, you need to encrypt it, which is quite a complex process. As time goes on, libraries will appear to do this kind of thing for you; for this demo we used Marco Castelluccio's NodeJS <a href="https://github.com/marco-c/web-push">web-push library</a>. Have a look at the source code to get more of an idea of how the encryption is done (and read <a href="https://tools.ietf.org/html/draft-ietf-webpush-encryption-01">Message Encryption for Web Push</a> for more details.) The library <a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/server.js#L43-L46">makes sending a push message simple</a>.</li> - <li>If you wish to have messages that collapse (newer updates will replace older updates), you can use the Topic feature. A topic is a special class of subscription update that has a <code>Topic</code> header. A topic name can be any URL safe, base64 string. For example, a header like "<code>Topic: MyFavoriteTopic-For2016</code>" is fine, but "<code>Topic: OMG! Kitties :)</code>" is not. Topic messages are collapsed when the subscriber is offline or unavailable. When they come back, they will receive only the lastest message per topic, along with whatever other messages are pending. "<a href="https://hacks.mozilla.org/2016/11/mozilla-push-server-now-supports-topics/">Mozilla Push Server now supports Topics</a>" on the Mozilla Hacks blog gives more details and examples.</li> -</ul> - -<h3 id="The_service_worker">The service worker</h3> - -<p>Now let's have a look at the service worker code (<code><a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/sw.js">sw.js</a></code>), which responds to the push messages, represented by {{Event("push")}} events. These are handled on the service worker's scope by the ({{domxref("ServiceWorkerGlobalScope.onpush")}}) event handler; its job is to work out what to do in response to each received message. We first convert the received message back into an object by calling {{domxref("PushMessageData.json()")}}. Next, we check what type of push message it is, by looking at the object's <code>action</code> property:</p> - -<ul> - <li><code>subscribe</code> or <code>unsubscribe</code>: We send a system notification via the <code>fireNotification()</code> function, but also send a message back to the main context on our {{domxref("MessageChannel")}} so we can update the subscriber list accordingly (see {{anch("Handling channel messages sent from the service worker")}} for more details).</li> - <li><code>init</code> or <code>chatMsg</code>: We just send a channel message back to the main context to handle the <code>init</code> and <code>chatMsg</code> cases (these don't need a system notification).</li> -</ul> - -<pre class="brush: js">self.addEventListener('push', function(event) { - var obj = event.data.json(); - - if(obj.action === 'subscribe' || obj.action === 'unsubscribe') { - fireNotification(obj, event); - port.postMessage(obj); - } else if(obj.action === 'init' || obj.action === 'chatMsg') { - port.postMessage(obj); - } -});</pre> - -<p>Next, let's look at the <code>fireNotification()</code> function (which is blissfully pretty simple).</p> - -<pre class="brush: js">function fireNotification(obj, event) { - var title = 'Subscription change'; - var body = obj.name + ' has ' + obj.action + 'd.'; - var icon = 'push-icon.png'; - var tag = 'push'; - - event.waitUntil(self.registration.showNotification(title, { - body: body, - icon: icon, - tag: tag - })); -}</pre> - -<p>Here we assemble the assets needed by the notification box: the title, body, and icon. Then we send a notification via the {{domxref("ServiceWorkerRegistration.showNotification()")}} method, providing that information as well as the tag "push", which we can use to identify this notification among any other notifications we might be using. When the notification is successfully sent, it manifests as a system notification dialog on the users computers/devices in whatever style system notifications look like on those systems (the following image shows a Mac OSX system notification.)</p> - -<p><img alt="" src="https://mdn.mozillademos.org/files/11855/subscribe-notification.png" style="display: block; height: 65px; margin: 0px auto; width: 326px;"></p> - -<p>Note that we do this from inside an {{domxref("ExtendableEvent.waitUntil()")}} method; this is to make sure the service worker remains active until the notification has been sent. <code>waitUntil()</code> will extend the life cycle of the service worker until everything inside this method has completed.</p> - -<div class="note"> -<p><strong>Note</strong>: Web notifications from service workers were introduced around Firefox version 42, but are likely to be removed again while the surrounding functionality (such as <code>Clients.openWindow()</code>) is properly implemented (see {{bug(1203324)}} for more details.)</p> -</div> - -<h2 id="Handling_premature_subscription_expiration">Handling premature subscription expiration</h2> - -<p>Sometimes push subscriptions expire prematurely, without {{domxref("PushSubscription.unsubscribe()")}} being called. This can happen when the server gets overloaded, or if you are offline for a long time, for example. This is highly server-dependent, so the exact behavior is difficult to predict. In any case, you can handle this problem by watching for the {{Event("pushsubscriptionchange")}} event, which you can listen for by providing a {{domxref("ServiceWorkerGlobalScope.onpushsubscriptionchange")}} event handler; this event is fired only in this specific case.</p> - -<pre class="brush: js language-js"><code class="language-js">self<span class="punctuation token">.</span><span class="function token">addEventListener<span class="punctuation token">(</span></span><span class="string token">'pushsubscriptionchange'</span><span class="punctuation token">,</span> <span class="keyword token">function</span><span class="punctuation token">(</span><span class="punctuation token">)</span> <span class="punctuation token">{</span> - <span class="comment token"> // do something, usually resubscribe to push and -</span> <span class="comment token"> // send the new subscription details back to the -</span> <span class="comment token"> // server via XHR or Fetch -</span><span class="punctuation token">}</span><span class="punctuation token">)</span><span class="punctuation token">;</span></code></pre> - -<p>Note that we don't cover this case in our demo, as a subscription ending is not a big deal for a simple chat server. But for a more complex example you'd probably want to resubscribe the user.</p> - -<h2 id="Extra_steps_for_Chrome_support">Extra steps for Chrome support</h2> - -<p>To get the app working on Chrome, we need a few extra steps, as Chrome currently relies on Google's Cloud Messaging service to work.</p> - -<h3 id="Setting_up_Google_Cloud_Messaging">Setting up Google Cloud Messaging</h3> - -<p>To get this set up, follow these steps:</p> - -<ol> - <li>Navigate to the <a href="https://console.developers.google.com">Google Developers Console</a> and set up a new project.</li> - <li>Go to your project's homepage (ours is at <code>https://console.developers.google.com/project/push-project-978</code>, for example), then - <ol> - <li>Select the <em>Enable Google APIs for use in your apps</em> option.</li> - <li>In the next screen, click <em>Cloud Messaging for Android</em> under the <em>Mobile APIs</em> section.</li> - <li>Click the <em>Enable API</em> button.</li> - </ol> - </li> - <li>Now you need to make a note of your project number and API key because you'll need them later. To find them: - <ol> - <li><strong>Project number</strong>: click <em>Home</em> on the left; the project number is clearly marked at the top of your project's home page.</li> - <li><strong>API key</strong>: click <em>Credentials</em> on the left hand menu; the API key can be found on that screen.</li> - </ol> - </li> -</ol> - -<h3 id="manifest.json">manifest.json</h3> - -<p>You need to include a Google app-style <code>manifest.json</code> file in your app, which references the project number you made a note of earlier in the <code>gcm_sender_id</code> parameter. Here is our simple example <a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/manifest.json">manifest.json</a>:</p> - -<pre class="brush: js">{ - "name": "Push Demo", - "short_name": "Push Demo", - "icons": [{ - "src": "push-icon.png", - "sizes": "111x111", - "type": "image/png" - }], - "start_url": "/index.html", - "display": "standalone", - "gcm_sender_id": "224273183921" -}</pre> - -<p>You also need to reference your manifest using a {{HTMLElement("link")}} element in your HTML:</p> - -<pre class="brush: html"><link rel="manifest" href="manifest.json"></pre> - -<h3 id="userVisibleOnly">userVisibleOnly</h3> - -<p>Chrome requires you to set the <a href="/en-US/docs/Web/API/PushManager/subscribe#Parameters"><code>userVisibleOnly</code> parameter</a> to <code>true</code> when subscribing to the push service, which indicates that we are promising to show a notification whenever a push is received. This can be <a href="https://github.com/chrisdavidmills/push-api-demo/blob/gh-pages/main.js#L127">seen in action in our <code>subscribe()</code> function</a>.</p> - -<h2 id="See_also">See also</h2> - -<ul> - <li><a href="/en-US/docs/Web/API/Push_API">Push API</a></li> - <li><a href="/en-US/docs/Web/API/Service_Worker_API">Service Worker API</a></li> -</ul> - -<div class="note"> -<p><strong>Note</strong>: Some of the client-side code in our Push demo is heavily influenced by Matt Gaunt's excellent examples in <a href="http://updates.html5rocks.com/2015/03/push-notificatons-on-the-open-web">Push Notifications on the Open Web</a>. Thanks for the awesome work, Matt!</p> -</div> diff --git a/files/es/web/api/randomsource/index.html b/files/es/web/api/randomsource/index.html deleted file mode 100644 index 76e8d7fdc2..0000000000 --- a/files/es/web/api/randomsource/index.html +++ /dev/null @@ -1,111 +0,0 @@ ---- -title: RandomSource -slug: Web/API/RandomSource -tags: - - API - - Interface - - NeedsTranslation - - RandomSource - - Reference - - TopicStub - - Web Crypto API -translation_of: Web/API/Crypto/getRandomValues -translation_of_original: Web/API/RandomSource ---- -<p>{{APIRef("Web Crypto API")}}</p> - -<p><strong><code>RandomSource</code></strong> represents a source of cryptographically secure random numbers. It is available via the {{domxref("Crypto")}} object of the global object: {{domxref("Window.crypto")}} on Web pages, {{domxref("WorkerGlobalScope.crypto")}} in workers.</p> - -<p><code>RandomSource</code> is a not an interface and no object of this type can be created.</p> - -<h2 id="Properties">Properties</h2> - -<p><em><code>RandomSource</code> neither defines nor inherits any property.</em></p> - -<dl> -</dl> - -<h2 id="Methods">Methods</h2> - -<dl> - <dt>{{ domxref("RandomSource.getRandomValues()") }}</dt> - <dd>Fills the passed {{ domxref("ArrayBufferView") }} with cryptographically sound random values.</dd> -</dl> - -<h2 id="Specification" name="Specification">Specification</h2> - -<table class="standard-table"> - <tbody> - <tr> - <th scope="col">Specification</th> - <th scope="col">Status</th> - <th scope="col">Comment</th> - </tr> - <tr> - <td>{{SpecName('Web Crypto API', '#dfn-RandomSource')}}</td> - <td>{{Spec2('Web Crypto API')}}</td> - <td>Initial definition</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_Compatibility">Browser Compatibility</h2> - -<p>{{ CompatibilityTable() }}</p> - -<div id="compat-desktop"> -<table class="compat-table"> - <tbody> - <tr> - <th>Feature</th> - <th>Chrome</th> - <th>Firefox (Gecko)</th> - <th>Internet Explorer</th> - <th>Opera</th> - <th>Safari</th> - </tr> - <tr> - <td>Basic support</td> - <td>11.0 {{ webkitbug("22049") }}</td> - <td>{{CompatGeckoDesktop(21)}} [1]</td> - <td>11.0</td> - <td>15.0</td> - <td>3.1</td> - </tr> - </tbody> -</table> -</div> - -<div id="compat-mobile"> -<table class="compat-table"> - <tbody> - <tr> - <th>Feature</th> - <th>Android</th> - <th>Chrome for Android</th> - <th>Firefox Mobile (Gecko)</th> - <th>IE Mobile</th> - <th>Opera Mobile</th> - <th>Safari Mobile</th> - </tr> - <tr> - <td>Basic support</td> - <td>{{ CompatNo() }}</td> - <td>23</td> - <td>{{CompatGeckoMobile(21)}}</td> - <td>{{ CompatNo() }}</td> - <td>{{ CompatNo() }}</td> - <td>6</td> - </tr> - </tbody> -</table> -</div> - -<p>[1] Although the transparent <code>RandomSource</code> is only available since Firefox 26, the feature was available in Firefox 21.</p> - -<h2 id="See_also">See also</h2> - -<ul> - <li>{{ domxref("Window.crypto") }} to get a {{domxref("Crypto")}} object.</li> - <li>{{jsxref("Math.random")}}, a non-cryptographic source of random numbers.</li> -</ul> diff --git a/files/es/web/api/server-sent_events/index.html b/files/es/web/api/server-sent_events/index.html new file mode 100644 index 0000000000..9b22801732 --- /dev/null +++ b/files/es/web/api/server-sent_events/index.html @@ -0,0 +1,99 @@ +--- +title: Server-sent events +slug: Server-sent_events +tags: + - NeedsTranslation + - Server-sent events + - TopicStub +translation_of: Web/API/Server-sent_events +--- +<p>Traditionally, a web page has to send a request to the server to receive new data; that is, the page requests data from the server. With server-sent events, it's possible for a server to send new data to a web page at any time, by pushing messages to the web page. These incoming messages can be treated as <em><a href="/en-US/docs/DOM/event" title="DOM/Event">Events</a> + data</em> inside the web page.</p> +<table class="topicpage-table"> + <tbody> + <tr> + <td> + <h2 class="Documentation" id="Documentation" name="Documentation">Documentation</h2> + <dl> + <dt> + <a href="/en-US/docs/Server-sent_events/Using_server-sent_events" title="Server-sent events/Using server-sent events">Using server-sent events</a></dt> + <dd> + A tutorial guide to writing both server and client side part of a server-sent events app.</dd> + <dt> + <a href="/en-US/docs/Server-sent_events/EventSource" title="Server-sent events/EventSource">EventSource reference</a></dt> + <dd> + A reference to the client-side EventSource API.</dd> + </dl> + <p><span class="alllinks"><a href="/en-US/docs/tag/Server-sent_events" title="tag/Server-sent events">View All...</a></span></p> + </td> + <td> + <h2 class="Tools" id="Tools" name="Tools">Tools</h2> + <ul> + <li>Remy Sharp’s <a class="link-https" href="https://github.com/remy/polyfills/blob/master/EventSource.js">EventSource polyfill</a></li> + <li>Yaffle’s <a class="link-https" href="https://github.com/Yaffle/EventSource" title="https://github.com/Yaffle/EventSource">EventSource polyfill</a></li> + <li>Rick Waldron’s <a class="link-https" href="https://github.com/rwldrn/jquery.eventsource">jquery plugin</a></li> + </ul> + <h2 class="Related_Topics" id="Related_Topics" name="Related_Topics">Related Topics</h2> + <ul> + <li><a href="/en-US/docs/AJAX" title="AJAX">AJAX</a>, <a href="/en-US/docs/JavaScript" title="JavaScript">JavaScript</a>, <a href="/en-US/docs/WebSockets" title="WebSockets">WebSockets</a></li> + </ul> + </td> + </tr> + </tbody> +</table> +<h2 id="See_also">See also</h2> +<ul> + <li>A <a href="http://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/" title="http://hacks.mozilla.org/2011/06/a-wall-powered-by-eventsource-and-server-sent-events/">Twitter like application</a> powered by server-sent events and <a class="link-https" href="https://github.com/mozilla/webowonder-demos/tree/master/demos/friends%20timeline" title="https://github.com/mozilla/webowonder-demos/tree/master/demos/friends timeline">its code on Github</a>.</li> + <li><a href="http://dsheiko.com/weblog/html5-and-server-sent-events" title="http://dsheiko.com/weblog/html5-and-server-sent-events">HTML5 and Server-sent events</a></li> + <li><a href="http://rajudasa.blogspot.in/2012/05/html5-server-sent-events-using-aspnet.html" title="http://rajudasa.blogspot.in/2012/05/html5-server-sent-events-using-aspnet.html">Server-sent events using Asp.Net</a></li> +</ul> +<h2 id="Specification">Specification</h2> +<ul> + <li><a href="http://dev.w3.org/html5/eventsource/" title="http://dev.w3.org/html5/eventsource/">Server-sent events</a></li> +</ul> +<h2 id="Browser_compatibility">Browser compatibility</h2> +<div> + {{CompatibilityTable}}</div> +<div id="compat-desktop"> + <table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>EventSource support</td> + <td>9</td> + <td>{{CompatGeckoDesktop("6.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>11</td> + <td>5</td> + </tr> + </tbody> + </table> +</div> +<div id="compat-mobile"> + <table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>EventSource support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> + </table> +</div> diff --git a/files/es/web/api/server-sent_events/using_server-sent_events/index.html b/files/es/web/api/server-sent_events/using_server-sent_events/index.html new file mode 100644 index 0000000000..81a2f5dacc --- /dev/null +++ b/files/es/web/api/server-sent_events/using_server-sent_events/index.html @@ -0,0 +1,231 @@ +--- +title: Utilizando eventos enviados por el servidor (server-sent event) +slug: Server-sent_events/utilizando_server_sent_events_sse +translation_of: Web/API/Server-sent_events/Using_server-sent_events +--- +<p>Desarrollar una aplicación web que utilice server-sent events es muy fácil. Solo necesitas un pequeño código del lado del servidor para transmitir los eventos a la aplicación web, pero del lado de la aplicacion web se trabaja prácticamente igual que con cualquier otro tipo de eventos.</p> + +<p>Puedes ver un ejemplo <a href="https://developer.mozilla.org/samples/sse/">aqui</a> (actualmente no funciona).</p> + +<p><a href="http://www.w3schools.com/html/tryit.asp?filename=tryhtml5_sse">ejemplo2</a></p> + +<h2 id="Recibiendo_eventos_desde_el_servidor">Recibiendo eventos desde el servidor</h2> + +<p>El server-sent event API está contenido en la interfaz <a href="https://developer.mozilla.org/en/Server-sent_events/EventSource"><code>EventSource</code></a>; para abrir una conexión al servidor para recibir eventos de él. Se crea un nuevo objeto new <a href="https://developer.mozilla.org/en/Server-sent_events/EventSource">EventSource</a>, especificando el URI de un script que genera los eventos, Por ejemplo:</p> + +<pre class="brush: js">var evtSource = new EventSource("ssedemo.php"); +</pre> + +<div class="note"><strong>Nota</strong>: Aunque todavía no es parte de la norma, EventSource es soportado por Firefox 11 y posteriores. Se espera que pronto forme parte del estándar.</div> + +<p>Una vez que ha instanciado el origen del evento, puede comenzar a escuchar los mensajes:</p> + +<pre class="brush: js">evtSource.onmessage = function(e) { + var newElement = document.createElement("li"); + + newElement.innerHTML = "message: " + e.data; + eventList.appendChild(newElement); +} +</pre> + +<p>Este codigo escucha todos los mensajes entrantes (Es decir, todos los avisos del servidor, que no tienen un campo de eventos en ellos) y anexa texto del mensaje a la lista en el documento HTML.</p> + +<p>También puedes escuchar eventos, usando <code>addEventListener()</code>:</p> + +<pre class="brush: js">evtSource.addEventListener("ping", function(e) { + var newElement = document.createElement("li"); + + var obj = JSON.parse(e.data); + newElement.innerHTML = "ping at " + obj.time; + eventList.appendChild(newElement); +}, false); +</pre> + +<p>Este código es similar, excepto que este se activa cada vez que el servidor envia un mensaje con el campo de evento "ping"; entonces se analiza el JSON en el campo de datos y retorna esa informacion.</p> + +<h2 id="Enviando_eventos_desde_el_servidor">Enviando eventos desde el servidor</h2> + +<p>El script del servidor que envia los datos tiene que responder con el tipo MIME text/event-stream. Cada notificación se envia con un bloque de texto terminado en un par de saltos de línea, para mas detalles sobre el formato sobre la secuencia de evetos, ver {{ anch("Event stream format") }},</p> + +<p>El codigo PHP para este ejemplo que estamos utilizando:</p> + +<pre class="brush: php">date_default_timezone_set("America/New_York"); +header("Content-Type: text/event-stream\n\n"); + +$counter = rand(1, 10); +while (1) { + // Every second, sent a "ping" event. + + echo "event: ping\n"; + $curDate = date(DATE_ISO8601); + echo 'data: {"time": "' . $curDate . '"}'; + echo "\n\n"; + + // Send a simple message at random intervals. + + $counter--; + + if (!$counter) { + echo 'data: This is a message at time ' . $curDate . "\n\n"; + $counter = rand(1, 10); + } + + ob_flush(); + flush(); + sleep(1); +} +</pre> + +<p>Se genera un evento cada segundo, con el evento "ping". Los datos de cada evento es un objeto JSON que contiene, en este caso, solo la fecha en formato ISO 8601 correspondiente a la hora en que se generó el evento. A intervalos aleatorios, se envia un mensaje simple (sin ningún tipo de evento)</p> + +<h2 id="Gestion_de_errores">Gestion de errores</h2> + +<p>Cuando se producen problemas (como un tiempo de espera o problemas relacionados con el control de acceso), se genera un evento de error. Puedes tomar acción sobre esto al implementar una devolución de llamada al objeto EventSource:</p> + +<pre class="brush: js">evtSource.onerror = function(e) { + alert("EventSource failed."); +}; +</pre> + +<p>En Firefox 22, no parece que haya manera de distinguir entre los diferentes de eventos de error.</p> + +<h2 id="Cerrando_flujo_de_eventos" style="margin-bottom: 20px; line-height: 30px; font-size: 2.14285714285714rem;">Cerrando flujo de eventos</h2> + +<p>Por defecto, si la conexión entre el cliente y el servidor se cierra, la conexión es reiniciada. Podemos terminar la conexión con el método <code>.close()</code></p> + +<pre class="language-html" style="padding: 1em 0px 1em 30px; font-size: 14px; white-space: normal; color: rgb(77, 78, 83);"><code class="language-html" style="font-family: Consolas, Monaco, 'Andale Mono', monospace; direction: ltr; white-space: pre;">evtSource.close();</code></pre> + +<div> </div> + +<h2 id="Formato_de_flujo_de_eventos_(formato_stream)">Formato de flujo de eventos (formato stream)</h2> + +<p>El flujo de eventos es una corriente sencilla de datos de texto, que deben ser codificados usando UTF-8. Los mensajes en el flujo de eventos están separados por un par de caracteres de salto de línea. Si hay un símbolo de dos puntos como primer caracter de una línea, se entiende que es un comentario y es ignorado. </p> + +<div class="note"><strong>Nota:</strong> La línea de comentario se puede usar para prevenir que la conexión se agote por tiempo (timeout); un sevidor puede enviar periódicamente un comentario para mantener viva la conexión.</div> + +<p>Cada mensaje consiste en una o más líneas de texto que enumeran los campos para ese mensaje. Cada campo está representado por el nombre del campo, seguido por los datos de texto para el valor de ese campo.</p> + +<h3 id="Campos">Campos</h3> + +<p>Los siguientes nombres de campo son definidos por la especificación:</p> + +<h4 id="event">event</h4> + +<p style="margin-left: 40px;">El tipo de evento. Si se especifica, un evento se enviará al navegador a la escucha para el nombre del evento especificado, el sitio web usaria <code>addEventLister()</code> para escuchar eventos nombrados. El controlador <code>onmessage</code> se llama si no se especifica el nombre del evento para un mensaje.</p> + +<h4 id="data">data</h4> + +<p style="margin-left: 40px;">El campo de datos para el mensaje. Cuando el EventSource recibe múltiples lineas con "<code>data:</code>", se concatenara, insertando un caracter de nueva de linea entre cada uno. Se eliminan los saltos de línea al final <strong>[VERIFICAR].</strong></p> + +<h4 id="id"><strong>id</strong></h4> + +<p style="margin-left: 40px;"> El ID del evento que establecerá el último ID del objeto EventSource.</p> + +<h4 id="Retry"><strong>Retry</strong></h4> + +<p style="margin-left: 40px;">El tiempo de reconexión para usar al intentar enviar el evento. [Qué código maneja esto?] Este debe ser un número entero, que especifica el tiempo de reconexion en milisegundos. Si se especifica un valor no entero, el campo se ignora. </p> + +<p>Se omiten todos los demas nombres de campo.</p> + +<div class="note"><strong>Nota:</strong> Si una línea no contiene dos puntos, la línea entera se tratara como un nombre de campo, con una cadena de valor vacio.</div> + +<h3 id="Ejemplos">Ejemplos</h3> + +<h4 id="Mensajes_con_datos_únicamente">Mensajes con datos únicamente</h4> + +<p>En el siguiente ejemplo, hay tres mensajes enviados. El primero es solo un comentario, debido a que empieza con dos puntos. Como se mencionó anteriormente, esto puede ser útil para mantener la conexión viva si los mensajes no son enviados regularmente.</p> + +<p>The second message contains a data field with the value "some text". The third message contains a data field with the value "another message\nwith two lines". Note the newline in the value.</p> + +<p>El segundo mensaje contiene un campo de datos con el valor "some text". El tercer mensaje contiene un campo de datos con el valor "another message\nwith two lines". Nota la nueva línea en el valor.</p> + +<pre>: this is a test stream + +data: some text + +data: another message +data: with two lines +</pre> + +<h4 id="Eventos_nombrados">Eventos nombrados</h4> + +<p>Este ejemplo envia algunos eventos nombrados. Cada uno tiene un nombre de evento especificado por el campo <code>event</code>, y un campo <code>data</code> cuyo valor es una cadena JSON apropiada con los datos necesarios para que el cliente actue sobre el evento. El campo <code>data</code>, podria, por supuesto, tener cualquier cadena; no tiene que ser un JSON.</p> + +<pre>event: userconnect +data: {"username": "bobby", "time": "02:33:48"} + +event: usermessage +data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."} + +event: userdisconnect +data: {"username": "bobby", "time": "02:34:23"} + +event: usermessage +data: {"username": "sean", "time": "02:34:36", "text": "Bye, bobby."} +</pre> + +<h4 id="Mezclando_y_emparejando">Mezclando y emparejando</h4> + +<p>No tienes que usar solamente mensajes sin nombrar o eventos tipados; puedes mezclarlo juntos en un solo flujo de evento.</p> + +<pre>event: userconnect +data: {"username": "bobby", "time": "02:33:48"} + +data: Here's a system message of some kind that will get used +data: to accomplish some task. + +event: usermessage +data: {"username": "bobby", "time": "02:34:11", "text": "Hi everyone."} +</pre> + +<h2 id="Compatibilidad_con_navegadores">Compatibilidad con navegadores</h2> + +<p>{{ CompatibilityTable() }}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>EventSource support</td> + <td>9</td> + <td>{{ CompatGeckoDesktop("6.0") }}</td> + <td>{{ CompatNo() }}</td> + <td>11</td> + <td>5</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android-and-Meego</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>EventSource support</td> + <td>6 a 24 b</td> + <td>1.0</td> + <td>{{ CompatUnknown() }}</td> + <td>11.1</td> + <td>4</td> + </tr> + </tbody> +</table> +</div> + +<p> </p> diff --git a/files/es/web/api/storage/localstorage/index.html b/files/es/web/api/storage/localstorage/index.html deleted file mode 100644 index 5c46cb9559..0000000000 --- a/files/es/web/api/storage/localstorage/index.html +++ /dev/null @@ -1,136 +0,0 @@ ---- -title: LocalStorage -slug: Web/API/Storage/LocalStorage -tags: - - Almacenamiento en Navegador - - Almacenamiento local -translation_of: Web/API/Window/localStorage -translation_of_original: Web/API/Web_Storage_API/Local_storage ---- -<p><code>localStorage</code> (almacenamiento local) es lo mismo que<code> <a href="/en-US/docs/Web/API/sessionStorage">sessionStorage</a> </code>(almacenamiento de sesión), con las mismas reglas de mismo-origen aplicadas, pero es persistente a través de diferentes sesiones. <code>localStorage</code> se introdujo en la version Firefox 3.5.</p> - -<div class="note"><strong>Nota:</strong> Cuando el navegador está en modo de navegación privado, una nueva base de datos temporal se crea para guardar <em>datos </em>de almacenamiento local. Esta base de datos se vacía y descarta cuando salimos del modo de navegación privado.</div> - -<pre class="brush:js notranslate" style="font-size: 14px;">// Guardar datos al almacenamiento local actual -localStorage.setItem("nombredeusuario", "John"); - -// Acceder a datos almacenados -alert( "nombredeusuario = " + localStorage.getItem("nombredeusuario"));</pre> - -<p class="note">La persistencia de <code>localStorage</code> lo hace útil para una variedad de cosas, incluyendo contadores de páginas, como se demuestra en <a href="http://codepen.io/awesom3/pen/Hlfma">este tutorial en Codepen</a>.</p> - -<h4 id="Compatibilidad" style="line-height: 18px; font-size: 1.28571428571429rem;">Compatibilidad</h4> - -<p>Los objetos de <code>Storage</code> (almacenamiento) son una adición reciente al estándar, por lo que pueden no estar presentes en todos los navegadores. Esto se puede solucionar si introduce uno de los dos códigos al principio de sus <em>scripts</em>, permitiendo el uso de el objeto <code>localStorage</code> en implementaciones que no lo soportan de forma nativa.</p> - -<p>Este algoritmo es una imitación exacta del objeto <code>localStorage</code>, pero hace uso de cookies.</p> - -<pre class="brush:js notranslate" style="font-size: 14px;">if (!window.localStorage) { - Object.defineProperty(window, "localStorage", new (function () { - var aKeys = [], oStorage = {}; - Object.defineProperty(oStorage, "getItem", { - value: function (sKey) { return sKey ? this[sKey] : null; }, - writable: false, - configurable: false, - enumerable: false - }); - Object.defineProperty(oStorage, "key", { - value: function (nKeyId) { return aKeys[nKeyId]; }, - writable: false, - configurable: false, - enumerable: false - }); - Object.defineProperty(oStorage, "setItem", { - value: function (sKey, sValue) { - if(!sKey) { return; } - document.cookie = escape(sKey) + "=" + escape(sValue) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"; - }, - writable: false, - configurable: false, - enumerable: false - }); - Object.defineProperty(oStorage, "length", { - get: function () { return aKeys.length; }, - configurable: false, - enumerable: false - }); - Object.defineProperty(oStorage, "removeItem", { - value: function (sKey) { - if(!sKey) { return; } - document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"; - }, - writable: false, - configurable: false, - enumerable: false - }); - this.get = function () { - var iThisIndx; - for (var sKey in oStorage) { - iThisIndx = aKeys.indexOf(sKey); - if (iThisIndx === -1) { oStorage.setItem(sKey, oStorage[sKey]); } - else { aKeys.splice(iThisIndx, 1); } - delete oStorage[sKey]; - } - for (aKeys; aKeys.length > 0; aKeys.splice(0, 1)) { oStorage.removeItem(aKeys[0]); } - for (var aCouple, iKey, nIdx = 0, aCouples = document.cookie.split(/\s*;\s*/); nIdx < aCouples.length; nIdx++) { - aCouple = aCouples[nIdx].split(/\s*=\s*/); - if (aCouple.length > 1) { - oStorage[iKey = unescape(aCouple[0])] = unescape(aCouple[1]); - aKeys.push(iKey); - } - } - return oStorage; - }; - this.configurable = false; - this.enumerable = true; - })()); -} -</pre> - -<div class="note"><strong>Nota:</strong> El tamaño máximo de datos que se puede guardar está muy restringido por el uso de cookies. Con este algoritmo, utilize las funciones <code>localStorage.getItem()</code>, <code>localStorage.setItem()</code>, y <code>localStorage.removeItem()</code> para agregar, cambiar, o quitar una clave. El uso del método <code>localStorage.suClave</code> para obtener, establecer, o borrar una clave <strong>no está permitido con este código</strong>. También se puede cambiar el nombre y usarse sólo para gestionar las cookies de el documento sin importar el objeto localStorage.</div> - -<div class="note"><strong>Nota:</strong> Al cambiar la cadena <code style="background: rgb(204, 204, 204);">"; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"</code> a: <code style="background: rgb(204, 204, 204);">"; path=/"</code> (y al cambiar el nombre del objeto), esto se pasará a ser un <code>sessionStorage</code> <em>polyfill</em> en vez de un <code>localStorage</code> <em>polyfill</em>. Sin embargo, esta implementación compartirá valores almacenados a través de pestañas y ventanas del navegador (y sólo se borrará cuando todas las ventanas del navegador hayan sido cerradas), mientras que una implementación <span style="font-family: 'Courier New','Andale Mono',monospace; line-height: normal;">sessionStorage</span><span style="line-height: 1.5em;"> completamente compatible sólo restringirá los valores guardados al contexto actual del navegador.</span></div> - -<p>Esta es otra imitación menos exacta de el objeto <code>localStorage</code>, es más simple que la anterior, pero es compatible con navegadores antiguos, como Internet Explorer < 8 (<strong>probado y funcional incluso en Internet Explorer 6</strong>). También hace uso de cookies.</p> - -<pre class="brush:js notranslate" style="font-size: 14px;">if (!window.localStorage) { - window.localStorage = { - getItem: function (sKey) { - if (!sKey || !this.hasOwnProperty(sKey)) { return null; } - return unescape(document.cookie.replace(new RegExp("(?:^|.*;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*((?:[^;](?!;))*[^;]?).*"), "$1")); - }, - key: function (nKeyId) { - return unescape(document.cookie.replace(/\s*\=(?:.(?!;))*$/, "").split(/\s*\=(?:[^;](?!;))*[^;]?;\s*/)[nKeyId]); - }, - setItem: function (sKey, sValue) { - if(!sKey) { return; } - document.cookie = escape(sKey) + "=" + escape(sValue) + "; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"; - this.length = document.cookie.match(/\=/g).length; - }, - length: 0, - removeItem: function (sKey) { - if (!sKey || !this.hasOwnProperty(sKey)) { return; } - document.cookie = escape(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=/"; - this.length--; - }, - hasOwnProperty: function (sKey) { - return (new RegExp("(?:^|;\\s*)" + escape(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie); - } - }; - window.localStorage.length = (document.cookie.match(/\=/g) || window.localStorage).length; -} -</pre> - -<div class="note"><strong>Nota:</strong> El tamaño máximo de datos que se puede guardar está muy restringido por el uso de cookies. Con este algoritmo, utilize las funciones <code>localStorage.getItem()</code>, <code>localStorage.setItem()</code>, y <code>localStorage.removeItem()</code> para agregar, cambiar, o quitar una clave. El uso del método <code>localStorage.suClave</code> para obtener, establecer, o borrar una clave <strong>no está permitido con este código</strong>. También se puede cambiar el nombre y usarse sólo para gestionar las cookies de el documento sin importar el objeto localStorage.</div> - -<div class="note"><strong>Nota:</strong> Al cambiar la cadena <code style="background: rgb(204, 204, 204);">"; expires=Tue, 19 Jan 2038 03:14:07 GMT; path=/"</code> a: <code style="background: rgb(204, 204, 204);">"; path=/"</code> (y al cambiar el nombre del objeto), esto se volverá un <code>sessionStorage</code> <em>polyfill</em> en vez de un <code>localStorage</code> <em>polyfill</em>. Sin embargo, esta implementación compartirá valores almacenados a través de pestañas y ventanas del navegador (y sólo se borrará cuando todas las ventanas del navegador hayan sido cerradas), mientras que una implementación <span style="font-family: 'Courier New','Andale Mono',monospace; line-height: normal;">sessionStorage</span><span style="line-height: 1.5em;"> completamente compatible sólo restringirá los valores guardados al contexto actual del navegador.</span></div> - -<h4 id="Compatibilidad_y_relación_con_globalStorage" style="line-height: 18px; font-size: 1.28571428571429rem;">Compatibilidad y relación con globalStorage</h4> - -<p class="note"><code>localStorage</code> es lo mismo que <code>globalStorage[location.hostname]</code>, con la excepción de que tiene un ámbito de origen HTML5 (<em>esquema </em>+ <em>nombre del host </em>+ <em>puerto no estandar</em>), y <code>localStorage</code> es una instancia de <code>Storage</code>, al contrario que <code>globalStorage[location.hostname]</code>, que es una instancia de <code>StorageObsolete</code>, como se explica más adelante. Por ejemplo, <a class="external" href="http://example.com" rel="freelink">http://ejemplo.com</a> no puede acceder al mismo objeto <code>localStorage</code> que <a class="link-https" href="https://example.com" rel="freelink">https://ejemplo.com,</a> pero los dos pueden acceder al mismo elemento de <code>globalStorage</code>. --<code>localStorage</code> es una interfaz estándar mientras que <code>globalStorage</code> no lo es, así que no se debe depender de ella.</p> - -<p>Nótese que al establecer una propiedad en <code>globalStorage[location.hostname]</code> <strong>no</strong> la establece en <code>localStorage</code>, y al extender <code>Storage.prototype</code> no afecta a los elementos de <code>globalStorage</code>; sólo al extender <code>StorageObsolete.prototype</code> los afecta.</p> - -<h4 id="El_formato_de_Storage">El formato de Storage</h4> - -<p>Las claves y valores de <code>Storage</code> se guardan en el formato UTF-16 <a href="/en-US/docs/Web/API/DOMString">DOMString</a>, que usa 2 bytes por carácter.</p> diff --git a/files/es/web/api/subtlecrypto/encrypt/index.html b/files/es/web/api/subtlecrypto/encrypt/index.html deleted file mode 100644 index 8f35030d35..0000000000 --- a/files/es/web/api/subtlecrypto/encrypt/index.html +++ /dev/null @@ -1,142 +0,0 @@ ---- -title: SubtleCrypto.digest() -slug: Web/API/SubtleCrypto/encrypt -tags: - - API - - Encriptación - - Referencia - - SubtleCrypto - - Web Crypto API - - encrypt -translation_of: Web/HTTP/Headers/Digest ---- -<div>{{APIRef("Web Crypto API")}}</div> - -<p>El método <code><strong>digest()</strong></code> de la interfaz {{domxref("SubtleCrypto")}} genera un digest de los datos proveidos. Un {{domxref("digest")}} es un valor corto de longitud fija derivado de alguna entrada de longitud variable. Los digest criptográficos deben mostrar resistencia a colisiones, lo que significa que es difícil encontrar dos entradas diferentes que tengan el mismo valor de digest.</p> - -<p>Toma como argumento un identificador para el algoritmo digest a utilizar y los datos a codificar. Devuelve un <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" title="The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value."><code>Promise</code></a> que se completará con el digest.</p> - -<h2 id="Sintaxis">Sintaxis</h2> - -<pre class="syntaxbox">const digest = <em>crypto</em><code>.subtle.digest(<em>algorithm</em>, <em>data</em>)</code>; -</pre> - -<h3 id="Parámetros">Parámetros</h3> - -<ul> - <li><em><code>algorithm</code></em> es un {{domxref("DOMString")}} definiendo la función hash a utilizar. Los valores admitidos son: - - <ul> - <li><code>SHA-1</code> (pero no debe utilizarse en aplicaciones criptográficas)</li> - <li><code>SHA-256</code></li> - <li><code>SHA-384</code></li> - <li><code>SHA-512</code></li> - </ul> - </li> - <li><em><code>data</code></em> es un {{jsxref("ArrayBuffer")}} o {{domxref("ArrayBufferView")}} que contiene los datos a ser digitalizados.</li> -</ul> - -<h3 id="Valor_de_retorno">Valor de retorno</h3> - -<ul> - <li><code><em>digest</em></code> es un <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise" title="The Promise object represents the eventual completion (or failure) of an asynchronous operation, and its resulting value."><code>Promise</code></a> que se completa con un <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer" title="The ArrayBuffer object is used to represent a generic, fixed-length raw binary data buffer. You cannot directly manipulate the contents of an ArrayBuffer; instead, you create one of the typed array objects or a DataView object which represents the buffer in a specific format, and use that to read and write the contents of the buffer."><code>ArrayBuffer</code></a> conteniendo el digest.</li> -</ul> - -<h2 id="Algoritmos_soportados">Algoritmos soportados</h2> - -<p>Los argoritmos digest, también conocidos como <a href="/en-US/docs/Glossary/Cryptographic_hash_function">funciones criptográficas hash</a>, transforman un bloque de datos arbitrariamente grande en una salida de tamaño fijo, normalmente mucho más corta que la entrada. Tienen una variedad de aplicaciones en criptografía.</p> - -<h3 id="SHA-1">SHA-1</h3> - -<p>Este algoritmo se especifica en <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf">FIPS 180-4</a>, sección 6.1, y produce una salida de 160 bits de largo.</p> - -<div class="blockIndicator warning"> -<p><strong>Advertencia</strong>: Este algoritmo se considera ahora vulnerable y no debe utilizarse para aplicaciones criptográficas.</p> -</div> - -<h3 id="SHA-256">SHA-256</h3> - -<p>Este algoritmo se especifica en <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf">FIPS 180-4</a>, sección 6.2, y produce una salida de 256 bits de largo.</p> - -<h3 id="SHA-384">SHA-384</h3> - -<p>Este algoritmo se especifica en <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf">FIPS 180-4</a>, sección 6.5, y produce una salida de 384 bits de largo.</p> - -<h3 id="SHA-512">SHA-512</h3> - -<p>Este algoritmo se especifica en <a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf">FIPS 180-4</a>, sección 6.4, y produce una salida de 512 bits de largo.</p> - -<div class="blockIndicator note"> -<p>Sugerencia: Si estás buscando aquí cómo crear un código de autenticación de mensajes "keyed-hash" (<a href="/en-US/docs/Glossary/HMAC">HMAC</a>), necesitas usar <a href="/en-US/docs/Web/API/SubtleCrypto/sign#HMAC">SubtleCrypto.sign()</a> en su lugar.</p> -</div> - -<h2 id="Ejemplos">Ejemplos</h2> - -<h3 id="Ejemplo_básico">Ejemplo básico</h3> - -<p>Este ejemplo codifica un mensaje, luego calcula su digest SHA-256 y muestra la longitud del mismo:</p> - -<pre class="brush: js">const text = 'An obscure body in the S-K System, your majesty. The inhabitants refer to it as the planet Earth.'; - -async function digestMessage(message) { - const encoder = new TextEncoder(); - const data = encoder.encode(message); - const hash = await crypto.subtle.digest('SHA-256', data); - return hash; -} - -const digestBuffer = await digestMessage(text); -console.log(digestBuffer.byteLength); -</pre> - -<h3 id="Convirtiendo_un_digest_a_una_cadena_hexadecimal">Convirtiendo un digest a una cadena hexadecimal</h3> - -<p>El resumen se devuelve como un <code>ArrayBuffer</code>, pero para la comparación y visualización los digests se representan a menudo como cadenas hexadecimales. Este ejemplo calcula un digest, y luego convierte el <code>ArrayBuffer</code> a un string hexadecimal:</p> - -<pre class="brush: js">const text = 'An obscure body in the S-K System, your majesty. The inhabitants refer to it as the planet Earth.'; - -async function digestMessage(message) { - const msgUint8 = new TextEncoder().encode(message); // encode as (utf-8) Uint8Array - const hashBuffer = await crypto.subtle.digest('SHA-256', msgUint8); // hash the message - const hashArray = Array.from(new Uint8Array(hashBuffer)); // convert buffer to byte array - const hashHex = hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); // convert bytes to hex string - return hashHex; -} - -const digestHex = await digestMessage(text); -console.log(digestHex); -</pre> - -<h2 id="Especificaciones">Especificaciones</h2> - -<table class="standard-table"> - <tbody> - <tr> - <th scope="col">Especificación</th> - <th scope="col">Estado</th> - <th scope="col">Comentario</th> - </tr> - <tr> - <td>{{SpecName('Web Crypto API', '#dfn-SubtleCrypto-method-digest', 'SubtleCrypto.digest()')}}</td> - <td>{{Spec2('Web Crypto API')}}</td> - <td>Definición inicial.</td> - </tr> - </tbody> -</table> - -<h2 id="Compatibilidad_del_navegador">Compatibilidad del navegador</h2> - -<div class="hidden">La tabla de compatibilidad de esta página se genera a partir de datos estructurados. Si desea contribuir a los datos, por favor, revise <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> y envíenos un pull request.</div> - -<p>{{Compat("api.SubtleCrypto.digest")}}</p> - -<div class="blockIndicator note"> -<p>En Chrome 60, se añadió una característica que deshabilita crypto.subtle para conexiones no TLS.</p> -</div> - -<h2 id="Ver_también">Ver también</h2> - -<ul> - <li><a href="https://www.chromium.org/Home/chromium-security/prefer-secure-origins-for-powerful-new-features">Chromium especificación de origines seguro</a></li> - <li><a href="https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf" rel="noopener">FIPS 180-4</a> especifica la familia de algoritmos de digest SHA.</li> -</ul> diff --git a/files/es/web/api/touch_events/index.html b/files/es/web/api/touch_events/index.html new file mode 100644 index 0000000000..02a4a4eacb --- /dev/null +++ b/files/es/web/api/touch_events/index.html @@ -0,0 +1,292 @@ +--- +title: Eventos de toque +slug: DOM/Touch_events +tags: + - DOM + - Event + - Mobile + - NeedsMobileBrowserCompatTable + - eventos +translation_of: Web/API/Touch_events +--- +<p>Con el fin de proporcionar soporte de calidad para usuarios de interfaces táctiles, los eventos táctiles dan la posibilidad de interpretar la actividad de los dedos en pantallas táctiles o trackpads.</p> + +<h2 id="Definiciones">Definiciones</h2> + +<dl> + <dt>Superficie</dt> + <dd>La superficie sensible al tacto. Esta puede ser una pantalla o un trackpad.</dd> +</dl> + +<dl> + <dt><strong style="font-weight: bold;">Punto de toque</strong></dt> + <dd>Un punto de contacto con la superficie. Esto podría ser un dedo (o un codo, oreja, nariz, o lo que sea, pero probablemente un dedo) o un stylus.</dd> +</dl> + +<h2 id="Interfaces">Interfaces</h2> + +<dl> + <dt>{{ domxref("TouchEvent") }}</dt> + <dd>Representa un evento que ocurre cuando el estado de los toques en la superficie cambian.</dd> + <dt>{{ domxref("Touch") }}</dt> + <dd>Represeta un único punto de contacto entre el usuario y la superficie táctil.</dd> + <dt>{{ domxref("TouchList") }}</dt> + <dd>Representa varios puntos de toque: esto se utiliza cuando el usuario tiene, por ejemplo, varios dedos en la superficie al mismo tiempo.</dd> + <dt>{{ domxref("DocumentTouch") }}</dt> + <dd>Contiene varios métodos para crear objetos de {{domxref("Touch")}} y {{domxref("TouchList")}}.</dd> +</dl> + +<h2 id="Ejemplo">Ejemplo</h2> + +<p>Este ejemplo muestra múltiples puntos de toques al mismo tiempo, permitiendo al usuario dibujar en un {{ HTMLElement("canvas") }} con más de un dedo a la vez. Esto funciona solamente en un navegador que soporte eventos táctiles.</p> + +<div class="note"><strong>Not</strong><strong>a:</strong> El texto de abajo usa el término "dedo" cuando describe el contacto con la superficie, pero esto podría ser, por supuesto, también un stylus u otro método de contacto.</div> + +<h3 id="Configurando_los_eventos_de_manipulación">Configurando los eventos de manipulación</h3> + +<p>Cuando la página carga, la función <code>startup()</code> mostrada a continuación es llamada por nuestro atributo <code>onload</code> del elemento {{ HTMLElement("body") }}.</p> + +<pre class="brush: js">function startup() { + var el = document.getElementsByTagName("canvas")[0]; + el.addEventListener("touchstart", handleStart, false); + el.addEventListener("touchend", handleEnd, false); + el.addEventListener("touchcancel", handleCancel, false); + el.addEventListener("touchleave", handleLeave, false); + el.addEventListener("touchmove", handleMove, false); +} +</pre> + +<p>Esto simplemente configura todos los detectores de eventos para nuestro elemento {{ HTMLElement("canvas") }}, por lo que podremos manejar todos los eventos de toque cuando se produzcan.</p> + +<h3 id="Seguimiento_de_nuevos_toques">Seguimiento de nuevos toques</h3> + +<p>Cuando un evento <code>touchstart</code> ocurre, indicando que un nuevo toque sobre la superficie se ha producido, la función <code>handleStart()</code> de a continuación es llamada.</p> + +<pre class="brush: js">function handleStart(evt) { + evt.preventDefault(); + var el = document.getElementsByTagName("canvas")[0]; + var ctx = el.getContext("2d"); + var touches = evt.changedTouches; + + for (var i=0; i<touches.length; i++) { + ongoingTouches.push(touches[i]); + var color = colorForTouch(touches[i]); + ctx.fillStyle = color; + ctx.fillRect(touches[i].pageX-2, touches[i].pageY-2, 4, 4); + } +} +</pre> + +<p>Esto llama a {{ domxref("event.preventDefault()") }} para mantener al navegador procesando el evento de toque (esto también previene que un evento del ratón o mouse sea entregado). Entonces obtenemos el contexto y lanzamos la lista de puntos de contacto cambiados de la propiedad {{ domxref("TouchEvent.changedTouches") }} del evento.</p> + +<p>Después de ello, iteramos sobre todos los objetos {{ domxref("Touch") }} de la lista, insertándolo en una matriz de puntos de toque activos y dibujando el punto de inicio como un pequeño rectángulo; estamos usando una línea de 4 pixeles de ancho, por tanto estamos dibujando un cuadrado de 4 por 4 píxeles como punto de consistencia.</p> + +<h3 id="Dibujando_mientras_los_eventos_de_toque_se_mueven">Dibujando mientras los eventos de toque se mueven</h3> + +<p>Cada vez que uno o más dedos se mueven, un evento <code>touchmove</code> es entregado, resultando en una llamada a nuestra función <code>handleMove()</code>. Su responsabilidad en este ejemplo es actualizar la información de toque cacheada y dibujar una línea desde la posición previa a la posición actual en cada toque.</p> + +<pre class="brush: js">function handleMove(evt) { + evt.preventDefault(); + var el = document.getElementsByTagName("canvas")[0]; + var ctx = el.getContext("2d"); + var touches = evt.changedTouches; + + ctx.lineWidth = 4; + + for (var i=0; i<touches.length; i++) { + var color = colorForTouch(touches[i]); + var idx = ongoingTouchIndexById(touches[i].identifier); + + ctx.fillStyle = color; + ctx.beginPath(); + ctx.moveTo(ongoingTouches[idx].pageX, ongoingTouches[idx].pageY); + ctx.lineTo(touches[i].pageX, touches[i].pageY); + ctx.closePath(); + ctx.stroke(); + ongoingTouches.splice(idx, 1, touches[i]); // swap in the new touch record + } +} +</pre> + +<p>Esto se repite también en los toques cambiados, pero mira en nuestra matriz de información de toques cacheados la información previa de cada toque con el fin de determinar los puntos de inicio para cada nuevo segmento de línea de toques que será dibujada. Esto se hace mirando cada propiedad de los toques de {{ domxref("Touch.identifier") }} . Esta propiedad es un único entero para cada toque, y sigue siendo consistente para cada evento durante la duración del contacto de cada dedo con la superficie.</p> + +<p>Esto nos permite conseguir las coordenadas de la posición previa de cada toque y usar el método apropiado de contexto para dibujar un segmento de línea uniendo dos posiciones a la vez.</p> + +<p>Después de dibujar la línea, llamamos a <a href="/en/JavaScript/Reference/Global_Objects/Array/splice" title="en/JavaScript/Reference/Global Objects/Array/splice"><code>Array.splice()</code></a> para reemplazar la información previa sobre el punto de toque con la información actual de la matriz <code>ongoingTouches</code>.</p> + +<h3 id="Manejando_el_final_de_un_toque">Manejando el final de un toque</h3> + +<p>Cuando el usuario levanta un dedo de la superficie, un evento <code>touchend</code> es enviado. De igual manera, si el dedo se desliza fuera de nuestro lienzo, obtenemos un evento <code>touchleave</code>. Manejamos ambos casos de la misma manera: llamando a la función <code>handleEnd()</code> de abajo. Su trabajo es dibujar el último segmento de línea para cada toque que ha finalizado y remueve el punto de toque de la lista de toques en marcha.</p> + +<pre class="brush: js">function handleEnd(evt) { + evt.preventDefault(); + var el = document.getElementsByTagName("canvas")[0]; + var ctx = el.getContext("2d"); + var touches = evt.changedTouches; + + ctx.lineWidth = 4; + + for (var i=0; i<touches.length; i++) { + var color = colorForTouch(touches[i]); + var idx = ongoingTouchIndexById(touches[i].identifier); + + ctx.fillStyle = color; + ctx.beginPath(); + ctx.moveTo(ongoingTouches[i].pageX, ongoingTouches[i].pageY); + ctx.lineTo(touches[i].pageX, touches[i].pageY); + ongoingTouches.splice(i, 1); // remove it; we're done + } +} +</pre> + +<p>Esto es muy similar a la función previa; la única diferencia real es que cuando llamamos a <a href="/en/JavaScript/Reference/Global_Objects/Array/splice" title="en/JavaScript/Reference/Global Objects/Array/splice"><code>Array.splice()</code></a>, simplemente remueve la antigua entrada de la lista de toques en marcha, sin añadir la información actualizada. El resultado es que detenemos el seguimiento del punto de toque.</p> + +<h3 id="Manejando_los_toques_cancelados">Manejando los toques cancelados</h3> + +<p>Si el dedo del usuario se equivoca en la Interfaz del navegador, o el toque necesita ser cancelado, el evento <code>touchcancel</code> es enviado, y llamamos a la función <code>handleCancel()</code> abajo.</p> + +<pre class="brush: js">function handleCancel(evt) { + evt.preventDefault(); + var touches = evt.changedTouches; + + for (var i=0; i<touches.length; i++) { + ongoingTouches.splice(i, 1); // remove it; we're done + } +} +</pre> + +<p>Dado que la idea es cancelar el toque inmediatamente, simplemente lo removemos de la lista de toques en marcha sin dibujar un segmento de línea final.</p> + +<h3 id="Funciones_de_conveniencia">Funciones de conveniencia</h3> + +<p>Este ejemplo usa dos funciones de convenience que deben mirarse brevemente para ayudar a que el resto del código sea más claro.</p> + +<h4 id="Seleccionando_un_color_para_cada_toque">Seleccionando un color para cada toque</h4> + +<p>Con el fin de hacer que cada dibujo de toque se vea diferente, la función <code>colorForTouch()</code> es usada para elegir un color basado en el identificador único de toque. Este identificador estará siempre entre 0 y un valor menos que el número de toques activos. Puesto que es muy improbable que alguna persona con más de 16 dedos use este demo, convertimos estos directamente en colores de escalas grises.</p> + +<pre class="brush: js">function colorForTouch(touch) { + var id = touch.identifier; + id = id.toString(16); // make it a hex digit + return "#" + id + id + id; +} +</pre> + +<p>El resultado de esta función es un string o cadena que puede ser usada cuando se llame a funciones {{ HTMLElement("canvas") }} para configurar los colores de dibujos. Por ejemplo, para un valor {{ domxref("Touch.identifier") }} de 10, el resultado string o cadena es "#aaa".</p> + +<h4 id="Encontrando_un_toque_continuo">Encontrando un toque continuo</h4> + +<p>La función <code>ongoingTouchIndexById()</code> abajo explora mediante la matriz <code>ongoingTouches</code> para encontrar el toque que coincida con el identificador dado, luego devuelve los índices de toques a la matriz.</p> + +<pre class="brush: js">function ongoingTouchIndexById(idToFind) { + for (var i=0; i<ongoingTouches.length; i++) { + var id = ongoingTouches[i].identifier; + + if (id == idToFind) { + return i; + } + } + return -1; // not found +} +</pre> + +<p><a href="/samples/domref/touchevents.html">Ver ejemplo en vivo</a></p> + +<h2 id="Consejos_adicionales">Consejos adicionales</h2> + +<p>Esta sección provee consejos adicionales sobre como manejar los eventos de toques en tu aplicación web.</p> + +<h3 id="Manejando_los_clics">Manejando los clics</h3> + +<p>Ya que la llamada <code>preventDefault()</code> en un <code>touchstart</code> o el primer evento <code>touchmove</code> de una serie impide que los eventos correspondientes eventos del mouse o ratón se disparen, es común llamar a <code>preventDefault()</code> en <code>touchmove</code> en lugar de <code>touchstart</code>. De esta manera, los eventos del ratón pueden todavía ser disparados y cosas como enlaces siguen funcionando. Alternativamente, algunos frameworks tienen que referirse a eventos de toque como eventos de ratón para este mismo propósito. (Este ejemplo es muy simplificado y podria resultar en un extraño comportamiento. Solo se diseñó como guía).</p> + +<pre class="brush: js">function onTouch(evt) { + evt.preventDefault(); + if (evt.touches.length > 1 || (evt.type == "touchend" && evt.touches.length > 0)) + return; + + var newEvt = <a href="https://developer.mozilla.org/en/DOM/document.createEvent" rel="internal" title="en/DOM/document.createEvent">document.createEvent</a>("MouseEvents"); + var type = null; + var touch = null; + switch (event.type) { + case "touchstart": type = "mousedown"; touch = event.changedTouches[[0]; + case "touchmove": type = "mousemove"; touch = event.changedTouches[[0]; + case "touchend": type = "mouseup"; touch = event.changedTouches[0]; + } + newEvt.<strong>initMouseEvent</strong>(type, true, true, event.<code><a href="https://developer.mozilla.org/en/DOM/event.originalTarget" rel="custom">originalTarget</a>.ownerDocument.defaultView</code>, 0, + touch.screenX, touch.screenY, touch.clientX, touch.clientY, + evt.ctrlKey, evt.altKey, evt.shirtKey, evt.metaKey, 0, null); + event.<code><a href="https://developer.mozilla.org/en/DOM/event.originalTarget" rel="custom">originalTarget</a></code>.<a href="https://developer.mozilla.org/en/DOM/element.dispatchEvent" rel="internal" title="en/DOM/element.dispatchEvent">dispatchEvent</a>(newEvt); +} +</pre> + +<h3 id="Llamando_a_preventDefault()_solo_en_un_segundo_toque">Llamando a preventDefault() solo en un segundo toque</h3> + +<p>Una cosa para prevenir cosas como <code>pinchZoom</code> en una página es llamar a <code>preventDefault()</code> en el segundo toque de una serie. Este comportamiento no está bien definido en los eventos de toque, y resulta en diferentes comportamientos en diferentes navegadores (osea iOS evitará el zoom o acercamiento pero permitirá vista panorámica con ambos dedos. Android permitirá zoom o acercamiento pero no una panorámica. Opera and Firefox actualmente evita panorámica y zoom o acercamiento). Actualmente, no se recomienda depender de ningún comportamiento en particular en este caso, si no mas bien depender de una meta vista para evitar el zoom.</p> + +<dl> +</dl> + +<h2 id="Compatibilidad_de_navegadores">Compatibilidad de navegadores</h2> + +<p>{{ CompatibilityTable() }}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>{{ CompatChrome("22.0") }}</td> + <td>{{ CompatGeckoDesktop("18.0") }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + <td>{{ CompatNo() }}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>{{ CompatVersionUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatGeckoMobile("6.0") }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatUnknown() }}</td> + <td>{{ CompatVersionUnknown() }}</td> + </tr> + </tbody> +</table> +</div> + +<h3 id="Notas_de_Gecko">Notas de Gecko</h3> + +<p>La preferencia <code>dom.w3c_touch_events.enabled</code> puede ser utilizada para activar o desactivar el soporte de eventos de toque estándares; por defecto, están activados.</p> + +<div class="geckoVersionNote" style=""> +<p>{{ gecko_callout_heading("12.0") }}</p> + +<p>Antes de Gecko 12.0 {{ geckoRelease("12.0") }}, Gecko no soportaba multi-toques; solo un toque cada vez era reportado.</p> +</div> + +<div class="note"><strong>Note: </strong>Antes de Gecko 6.0 {{ geckoRelease("6.0") }}, Gecko ofrecía una <a href="/en/DOM/Touch_events_(Mozilla_experimental)" title="en/DOM/Touch events (Mozilla experimental)">API de eventos de toque propietaria</a>. Está API está obsoleta actualmente; deberías cambiar a esta."</div> diff --git a/files/es/web/api/vibration_api/index.html b/files/es/web/api/vibration_api/index.html new file mode 100644 index 0000000000..8c9c7b5f06 --- /dev/null +++ b/files/es/web/api/vibration_api/index.html @@ -0,0 +1,155 @@ +--- +title: Vibración API +slug: Web/Guide/API/Vibration +tags: + - API + - Firefox OS + - Mobile + - Principiante + - Vibración + - Vibrado + - Vibrar + - WebAPI +translation_of: Web/API/Vibration_API +--- +<p>La mayoría de los dispositivos modernos pueden vibrar a través del hardware, esto permite que a través del código de software se pueda emitir estas vibraciones. La <strong>Vibration API</strong> ofrece a las aplicaciones web la capacidad de acceder a este hardware en caso este lo soporte, caso contrario el dispositivo no hace nada.</p> + +<h2 id="Describiendo_vibraciones">Describiendo vibraciones</h2> + +<p>Vibración se puede describir como un patrón de prender y apagar pulsos, los cuales pueden variar en longitud. El patrón puede consistir de un sólo número que indica cuantos milisegundos vibrará, o un arreglo de enteros describiendo un patrón de vibraciones y pausas. La vibración es controlada por un solo método:</p> + +<p><span style="font-size: 13.63636302948px; line-height: 19.0909080505371px;">{{domxref("window.navigator.vibrate()")}}.</span></p> + +<h3 id="Vibración_simple">Vibración simple</h3> + +<p>Puedes iniciar una sola vibración del hardware pasando como argumento un sólo número, o un arreglo de un sólo número:</p> + +<pre class="brush:js">window.navigator.vibrate(200); +window.navigator.vibrate([200]); +</pre> + +<p>Ambos ejemplos hacen vibrar el dispositivo por 200 ms.</p> + +<h3 id="Patrones_de_vibración">Patrones de vibración</h3> + +<p>Un arreglo de valores describen que las vibraciones serán por períodos alternados, es decir, el dispositivo vibrará luego no lo hará, así según la secuencia definida. Cada valor en el arreglo es convertido a entero para luego ser interpretado alternadamente como el tiempo que el dispositivo debe vibrar y el tiempo que no debe vibrar. Ejemplo:</p> + +<pre class="brush: js">window.navigator.vibrate([200, 100, 200]); +</pre> + +<p>Según este ejemplo el dispositivo vibrará por 200ms, luego se detiene por 100ms y luego vibra 200ms.</p> + +<p>Puedes especificar cuantas vibraciones/pausas desees, y el arreglo puede tener un tamaño par o impar. No importa que agregues una pausa como el último valor del arreglo, ya que el celular dejará de vibrar de todas formas al final de cada vibración.</p> + +<h3 id="Cancelar_vibraciones_existentes">Cancelar vibraciones existentes</h3> + +<p>Llamar {{domxref("window.navigator.vibrate()")}} con un valor de <code>0</code>, arreglo vació, o arreglo que contenga 0's detendrá cualquier vibración en curso.</p> + +<h3 id="Vibraciones_continuas">Vibraciones continuas</h3> + +<p style="margin: 0px 0px 0.8em; padding: 0px; border: 0px; font-family: 'Open Sans', Arial, sans-serif; line-height: 1.6em; font-size: 16px; vertical-align: baseline;">Algunas básicas acciones son <code style="margin: 0px; padding: 2px 7px; border: 0px; font-family: monospace, sans-serif; font-style: inherit; font-variant: inherit; font-weight: bold; line-height: inherit; font-size: 16px; vertical-align: baseline; background-color: rgb(248, 248, 248); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px;">setInterval</code> y <code style="margin: 0px; padding: 2px 7px; border: 0px; font-family: monospace, sans-serif; font-style: inherit; font-variant: inherit; font-weight: bold; line-height: inherit; font-size: 16px; vertical-align: baseline; background-color: rgb(248, 248, 248); border-top-left-radius: 4px; border-top-right-radius: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px;">clearInterval</code> que nos permitirán crear vibraciones persistentes:</p> + +<pre class="js language-js" style="margin-top: 0.5em; margin-bottom: 0.5em; padding: 1em; border: 0px; font-family: Consolas, Monaco, 'Andale Mono', monospace; line-height: 1.6em; font-size: 0.8em; vertical-align: baseline; background-color: rgb(245, 242, 240); color: black; text-shadow: white 0px 1px; direction: ltr;"><code class="language-js" style="margin: 0px; padding: 0px; border: 0px; font-family: Consolas, Monaco, 'Andale Mono', monospace; font-style: inherit; font-variant: inherit; line-height: inherit; font-size: 13px; vertical-align: baseline; text-shadow: white 0px 1px; direction: ltr;"><span class="token keyword" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(0, 119, 170);">var</span> intervaloDeVibrado<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">;</span> +<span class="token comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(112, 128, 144);"> +// Iniciar la vibración +</span><span class="token keyword" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(0, 119, 170);">function</span> <span class="token function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline;">iniciarVibrado<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span></span>duracion<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span> <span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">{</span> + navigator<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">.</span><span class="token function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline;">vibrate<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span></span>duracion)<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">;</span> +<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">}</span> +<span class="token comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(112, 128, 144);"> +// Detiene la vibración +</span><span class="token keyword" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(0, 119, 170);">function</span> <span class="token function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline;">detenerVibrado<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span></span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span> <span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">{</span> +<span class="token comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(112, 128, 144);"> // Limpiar el intervalo y detener las vibraciones existentes +</span> <span class="token keyword" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(0, 119, 170);">if</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span>intervaloDeVibrado<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span> <span class="token function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline;">clearInterval<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span></span>intervaloDeVibrado<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">;</span> + navigator<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">.</span><span class="token function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline;">vibrate<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span></span><span class="token number" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 0, 85);">0</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">;</span> +<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">}</span> +<span class="token comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(112, 128, 144);"> +// Iniciar las vibraciones con una determinado tiempo e intervalo +</span><span class="token comment" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(112, 128, 144);">// Asumir que el valor recibido es un entero +</span><span class="token keyword" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(0, 119, 170);">function</span> iniciarVibradoPersistente<span class="token function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline;"><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span></span>duracion<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">,</span> intervalo<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span> <span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">{</span> + intervaloDeVibrado <span class="token operator" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(166, 127, 89); background-color: rgba(255, 255, 255, 0.498039);">=</span> <span class="token function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline;">setInterval<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span></span><span class="token keyword" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(0, 119, 170);">function</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span> <span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">{</span> + <span class="token function" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline;">iniciarVibrado<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">(</span></span>duracion<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">;</span> + <span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">}</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">,</span> intervalo<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">)</span><span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">;</span> +<span class="token punctuation" style="margin: 0px; padding: 0px; border: 0px; font-family: inherit; font-style: inherit; font-variant: inherit; line-height: inherit; vertical-align: baseline; color: rgb(153, 153, 153);">}</span></code></pre> + +<p style="margin: 0px 0px 0.8em; padding: 0px; border: 0px; font-family: 'Open Sans', Arial, sans-serif; line-height: 1.6em; font-size: 16px; vertical-align: baseline;">Claro que el código de arriba no toma en cuenta el método de utilizar un arreglo de vibración, utilizar un arreglo para vibración persistente necesitaría recalcular la suma de los elementos del arregloo y crear un intervalo basado en esos números (agregando adicionalmente las pausas)</p> + +<h3 id="¿Por_qué_utilizar_Vibration_API">¿Por qué utilizar Vibration API?</h3> + +<p style="margin: 0px 0px 0.8em; padding: 0px; border: 0px; font-family: 'Open Sans', Arial, sans-serif; line-height: 1.6em; font-size: 16px; vertical-align: baseline;">Esta API es claramente accesible a través de dispositivos móbiles. Vibration API puede servir para alertas en las aplicaciones web del celular, y sería es asombrosa cuando se utiliza en juegos o en aplicaciones pesadas. Imagínate mirando un video en tu celular y durante la escena de explosión,tu teléfono vibra un poco. O la sensación que tendría tu usuario al sentir el estallido de una bomba en el juego Bomberman.</p> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Especificación</th> + <th scope="col">Estado</th> + <th scope="col">Comentario</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName('Vibration API')}}</td> + <td>{{Spec2('Vibration API')}}</td> + <td>Especificación inicial.</td> + </tr> + </tbody> +</table> + +<h2 id="Compatibilidad_entre_navegadores">Compatibilidad entre navegadores</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Caracteŕistica</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>{{CompatVersionUnknown}} {{property_prefix("webkit")}}</td> + <td>11.0 {{property_prefix("moz")}}<br> + 16 (no prefix)</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Característica</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Soporte básico</td> + <td>{{CompatVersionUnknown}} {{property_prefix("webkit")}}</td> + <td>11.0 {{property_prefix("moz")}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="Ver_También">Ver También</h2> + +<ul> + <li>{{domxref("window.navigator.vibrate()")}}</li> + <li><a href="http://davidwalsh.name/vibration-api">Vibration API - David Walsh</a></li> +</ul> diff --git a/files/es/web/api/web_audio_api/index.html b/files/es/web/api/web_audio_api/index.html new file mode 100644 index 0000000000..e7cb54d803 --- /dev/null +++ b/files/es/web/api/web_audio_api/index.html @@ -0,0 +1,510 @@ +--- +title: Web Audio API +slug: Web_Audio_API +translation_of: Web/API/Web_Audio_API +--- +<div>{{apiref("Web Audio API")}}</div> + +<p class="summary">La API de Audio Web provee un sistema poderoso y versatil para controlar audio en la Web, permitiendo a los desarrolladores escoger fuentes de audio, agregar efectos al audio, crear visualizaciones de audios, aplicar efectos espaciales (como paneo) y mucho más.</p> + +<h2 id="Conceptos_y_uso_de_audio_Web">Conceptos y uso de audio Web</h2> + +<p>La API de Audio Web involucra manejar operaciones de audio dentro de un <strong>contexto de audio</strong>, y ha sido diseñada para permitir <strong>enrutamiento modular</strong>. Las operaciones de audio básicas son realizadas con <strong>nodos de audio</strong>, que están enlazados juntos para formar un <strong>gráfico de enrutamiento de audio</strong>. Muchas fuentes — con diferentes tipos de diseño de canales — están soportadas incluso dentro de un único contexto. Este diseño modular provee flexibilidad para crear funciones de audio complejas con efectos dinámicos.</p> + +<p>Los nodos de audio están enlazados en cadenas y redes simples por sus entradas y salidas. Éstos típicamente empiezan con una o más fuentes. Las fuentes provee matrices de intensidades de sonidos (muestras) en segmentos de tiempo muy pequeños, a menudo decenas de miles de éstos por segundo. Éstos podrían ser calculados matemáticamente (como {{domxref("OscillatorNode")}}), o pueden ser grabaciones de archivos de audio o video (como {{domxref("AudioBufferSourceNode")}} y {{domxref("MediaElementAudioSourceNode")}}) y transmisiones de audio ({{domxref("MediaStreamAudioSourceNode")}}). De hecho, los archivos de sonido son sólo grabaciones de intensidades de sonido, que vienen desde micrófonos o instrumentos eléctricos, y mezclados en una onda única y complicada.</p> + +<p>Los resultados de éstos nodos podrían ser enlazados a las entradas de otros, que mezclan o modifican estas transmisiones de muestras de audio en diferentes transmisiones. Una modificación común es multiplicar las muestras por un valor para hacerlas más fuertes o silenciosas (como es el caso con {{domxref("GainNode")}}). Una vez que el sonido ha sido lo suficientemente procesado por el efecto necesario, puede ser enlazados a la entrada de un destino({{domxref("AudioContext.destination")}}), que enviá el sonido a los altavoces o auriculares. Esta última conexión sólo es necesaria si el usuario debe escuchar el audio.</p> + +<p>Un diagrama de flujo simple y típico para el audio web se vería algo como esto:</p> + +<ol> + <li>Crear contexto de audio</li> + <li>Dentro del contexto, crear fuentes — como <code><audio></code>, oscillator, stream</li> + <li>Crear nodos de efectos, <span class="short_text" id="result_box" lang="es"><span>tales como reverberación, filtro biquad, panner, compresor</span></span></li> + <li>Ecoge el destino final del audio, por ejemplo tu sistema de altavoces</li> + <li>Conecta las fuentes a los efectos, y los efectos al destino.</li> +</ol> + +<p><img alt="A simple box diagram with an outer box labeled Audio context, and three inner boxes labeled Sources, Effects and Destination. The three inner boxes have arrow between them pointing from left to right, indicating the flow of audio information." src="https://mdn.mozillademos.org/files/12241/webaudioAPI_en.svg" style="display: block; height: 143px; margin: 0px auto; width: 643px;"></p> + +<p>El tiempo es controlado con alta precisión baja latencia, permitiendo a los desarrolladores escribir código que responda con precisión a los eventos y sea capaz de apuntar a muestras específicas, incluso en una alta frecuencia de muestreo. <span id="result_box" lang="es"><span>Por lo tanto, las aplicaciones como las cajas de ritmos y los secuenciadores están a su alcance.</span></span></p> + +<p>El API de Audio Web también nos permite controlar cómo el audio es <em>espacializado</em>. Usando un sistema basado en un <em>modelo fuente-oyente</em>, esto permite controlar el <em>modeo de paneo</em> y que se ocupa de la <em>atenuación inducida por distancia </em>o <em>desplazamiento doppler</em> i<span class="short_text" id="result_box" lang="es"><span>nducido por una fuente en movimiento (o un oyente en movimiento).</span></span></p> + +<div class="note"> +<p>Puedes leear sobre la teoría del API de Audio Web con más detalle en nuestro artículo <a href="/en-US/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API">Conceptos Básicos detrás del API de Audio Web</a>.</p> +</div> + +<h2 id="Interfaces_del_API_de_Audio_Web">Interfaces del API de Audio Web</h2> + +<p>La API de Audio Web tiene un número de interfaces y eventos asociados, que han sido divididos en nueve categorias de funcionalidad.</p> + +<h3 id="Definición_general_del_gráfico_de_audio">Definición general del gráfico de audio</h3> + +<p><span id="result_box" lang="es"><span>Contenedores y definiciones generales que dan forma a los gráficos de audio en el uso de Web Audio API</span></span>.</p> + +<dl> + <dt>{{domxref("AudioContext")}}</dt> + <dd>La interfaz <strong><code>AudioContext</code></strong> representa un gráfico de procesamiento de audio construido de módulos de audio enlazados juntos, cada uno representado por un {{domxref("AudioNode")}}. Un contexto de audio controla la creación de los nodos que contiene y la ejecución del procesamiento del audio, or decoding. Necesitas crear un <code>AudioContext</code> antes de hacer cualquier cosa, ya que todo pasa dentro de un contexto de audio.</dd> + <dt>{{domxref("AudioNode")}}</dt> + <dd>La interfaz <strong><code>AudioNode</code></strong><strong> </strong>representa un módulo de procesamiento de audio como una <em>fuente de audio</em> (por ejemplo un ejemplo HTML {{HTMLElement("audio")}} or {{HTMLElement("video")}}), <em>destino de audio</em>, <em>módulo de procesamiento intermedio</em> (por ejemplo un filtro como {{domxref("BiquadFilterNode")}}, o <em>control de volumen</em> como {{domxref("GainNode")}}).</dd> + <dt>{{domxref("AudioParam")}}</dt> + <dd>La interfaz <strong><code>AudioParam</code></strong><strong> </strong>representa un parámetro relacionado al audio, como uno de un {{domxref("AudioNode")}}. Esto puede ser establecido a un valor específico o un cambio de valor, y puede ser agendado para que ocurra en un momento específico y siguiendo un patrón específico.</dd> + <dt>{{domxref("AudioParamMap")}}</dt> + <dd>Provee una interfaz como para mapear a un grupo de interfaces {{domxref("AudioParam")}}, lo que significa que proporciona los métodos <code>forEach()</code>, <code>get()</code>, <code>has()</code>, <code>keys()</code>, y <code>values()</code>, como también una propiedad <code>size</code>.</dd> + <dt>{{domxref("BaseAudioContext")}}</dt> + <dd>La interfaz <strong><code>BaseAudioContext</code></strong> actúa como una definición base para procesamiento de gráficos de audio en y fuera de línea, como lo representa {{domxref("AudioContext")}} y {{domxref("OfflineAudioContext")}} resepectivamente. No tendrás que usar <code>BaseAudioContext</code> directamente — tendrás que usar sus características a través de una de éstas dos interfaces heredadas.</dd> + <dt>El evento {{event("ended")}}</dt> + <dd>El evento <code>ended</code> es lanzado cuando la reproducción se detiene porque se alcanzó el fin del archivo de medio.</dd> +</dl> + +<h3 id="Definiendo_fuentes_de_audio">Definiendo fuentes de audio</h3> + +<p>Las interfaces que definen fuentes de audio para usar en la API de Web.</p> + +<dl> + <dt>{{domxref("AudioScheduledSourceNode")}}</dt> + <dd>La interfaz <strong><code>AudioScheduledSourceNode</code></strong> es una interfaz padre para muchos tipos de interfaces de nodos de fuentes de audio. Es un {{domxref("AudioNode")}}.</dd> +</dl> + +<dl> + <dt>{{domxref("OscillatorNode")}}</dt> + <dd>La interfaz <strong><code style="font-size: 14px;">OscillatorNode</code></strong><strong> </strong>representa una forma de onda periódica, como una onda sinusoidal o triangular. Es un módulo de procesamiento de audio {{domxref("AudioNode")}} que causa que se cree una <em>frecuencia</em> de onda determinada.</dd> + <dt>{{domxref("AudioBuffer")}}</dt> + <dd>La interfaz <strong><code>AudioBuffer</code></strong> representa un recurso de audio corto que reside en la memoria, creado desde un archivo de audio usando el método {{ domxref("AudioContext.decodeAudioData()") }}, o creado con datos sin procesar usando {{ domxref("AudioContext.createBuffer()") }}. Una vez decodificado en esta forma, el audio puede ser colocado en un {{ domxref("AudioBufferSourceNode") }}.</dd> + <dt>{{domxref("AudioBufferSourceNode")}}</dt> + <dd>La interfaz <strong><code>AudioBufferSourceNode</code></strong> representa una fuente de audio que consiste en una datos de audio en la memoria, almacenada en un {{domxref("AudioBuffer")}}. Es un {{domxref("AudioNode")}} que actúa como una fuente de audio.</dd> + <dt>{{domxref("MediaElementAudioSourceNode")}}</dt> + <dd>La interfaz <code><strong>MediaElementAudio</strong></code><strong><code>SourceNode</code></strong> representa una fuente de audio que consiste en un elemento {{ htmlelement("audio") }} o {{ htmlelement("video") }} de HTML5. Es un {{domxref("AudioNode")}} que actúa como una fuente de audio.</dd> + <dt>{{domxref("MediaStreamAudioSourceNode")}}</dt> + <dd>La interfaz <code><strong>MediaStreamAudio</strong></code><strong><code>SourceNode</code></strong> representa una fuente de audio que consiste en un {{domxref("MediaStream")}} de <a href="/en-US/docs/WebRTC" title="/en-US/docs/WebRTC">WebRTC</a> (como una cámara web, micrófono, o una transmisión siendo enviada a una computadora remota). Es un {{domxref("AudioNode")}} que actúa como una fuente de audio.</dd> +</dl> + +<h3 id="Definiendo_filtros_de_efectos_de_audio">Definiendo filtros de efectos de audio</h3> + +<p>Interfaces para definir efectos que quieras aplicar a tus fuentes de audio.</p> + +<dl> + <dt>{{domxref("BiquadFilterNode")}}</dt> + <dd>La interfaz <strong><code>BiquadFilterNode</code></strong><strong> </strong>representa una filtro de bajo orden sencillo. Es un {{domxref("AudioNode")}} que puede representar diferentes tipos de filtros, dispositivos de control de tono, o ecualizadores gráficos. Un <code>BiquadFilterNode</code> siempre tiene exactamente una entrada y una salida.</dd> + <dt>{{domxref("ConvolverNode")}}</dt> + <dd>La interfaz <code><strong>Convolver</strong></code><strong><code>Node</code></strong><strong> </strong>es un <span style="line-height: 1.5;">{{domxref("AudioNode")}} que realiza una Convolución Lineal en un</span><span style="line-height: 1.5;"> {{domxref("AudioBuffer")}} determinado, y es usado a menudo para lograr un efecto de reverberación</span><span style="line-height: 1.5;">.</span></dd> + <dt>{{domxref("DelayNode")}}</dt> + <dd>La interfaz <strong><code>DelayNode</code></strong> representa una <a href="http://en.wikipedia.org/wiki/Digital_delay_line" title="http://en.wikipedia.org/wiki/Digital_delay_line">línea de detardo</a>; un módulo de procesamiento de audio de {{domxref("AudioNode")}} que causa un retardo entre la llegada de una entrada de datos y su propagación a la salida.</dd> + <dt>{{domxref("DynamicsCompressorNode")}}</dt> + <dd>La intefaz <strong><code>DynamicsCompressorNode</code></strong> proporciona un efecto de compresión, que reduce el volumen de las partes más ruidosas de la señal para ayudar a evitar el recorte y la distorsión que pueden ocurrir cuando se reproducen y multiplexan múltiples sonidos a la vez.</dd> + <dt>{{domxref("GainNode")}}</dt> + <dd>La intefaz <strong><code>GainNode</code></strong><strong> </strong>representa un cambio de volumen. Es un módulo de procesamiento de audio de {{domxref("AudioNode")}} que causa que una <em>ganancia</em> determinada para ser aplicada a la entrada de datos antes de su propacación a la salida.</dd> + <dt>{{domxref("WaveShaperNode")}}</dt> + <dd>La interfaz <strong><code>WaveShaperNode</code></strong><strong> </strong>representa un la interfaz representa un distorsionador no lineal. Es un {{domxref("AudioNode")}} que usa una curva para aplicar una distorsión en forma de onda a la señal. Además de los obvios efectos de distorsión, a menudo se usa para agregar una sensación cálida a la señal.</dd> + <dt>{{domxref("PeriodicWave")}}</dt> + <dd>Describe una forma de onda periódica que puede ser usada para dar forma a la salida de un {{ domxref("OscillatorNode") }}.</dd> + <dt>{{domxref("IIRFilterNode")}}</dt> + <dd>Implementa un filtro de <strong><a class="external external-icon" href="https://en.wikipedia.org/wiki/infinite%20impulse%20response" title="infinite impulse response">respuesta de pulso infinito</a></strong> (IIR) general; este tipo de filtro se puede usar para implementar dispositivos de control de tono y ecualizadores gráficos también.</dd> +</dl> + +<h3 id="Definición_de_destinos_de_audio">Definición de destinos de audio</h3> + +<p>Una vez que haya terminado de procesar su audio, estas interfaces definen dónde emitirlo.</p> + +<dl> + <dt>{{domxref("AudioDestinationNode")}}</dt> + <dd>La interfaz <strong><code>AudioDestinationNode</code></strong> representa el destino final de una fuente de audio en contexto determinado — usualmente los altavoces de tu dispositivo.</dd> + <dt>{{domxref("MediaStreamAudioDestinationNode")}}</dt> + <dd>La interfaz <code><strong>MediaStreamAudio</strong></code><strong><code>DestinationNode</code></strong> representa un destino de audio que consiste en un {{domxref("MediaStream")}} de <a href="/en-US/docs/WebRTC" title="/en-US/docs/WebRTC">WebRTC</a> con un <code>AudioMediaStreamTrack</code> sencillo, que puede ser usado de una manera similiar a un {{domxref("MediaStream")}} obtenido desde {{ domxref("MediaDevices.getUserMedia", "getUserMedia()") }}. Es un {{domxref("AudioNode")}} que actúa como un destino de audio.</dd> +</dl> + +<h3 id="Análisis_y_visualización_de_datos">Análisis y visualización de datos</h3> + +<p>Si quieres extraer el tiempo, frecuencia, y otros datos de tu audio, <code>AnalyserNode</code> es lo que necesitas.</p> + +<dl> + <dt>{{domxref("AnalyserNode")}}</dt> + <dd>La interfaz <strong><code>AnalyserNode</code></strong> representa un nodo capáz de proveer la frecuencia en tiempo real y la información del análisis del dominio de tiempo, para propósitos de análisis y visualización de datos.</dd> +</dl> + +<h3 id="División_y_fusión_de_canales_de_audio">División y fusión de canales de audio</h3> + +<p>Para dividir y fusionar canales de audio, deberás usar estas interfaces.</p> + +<dl> + <dt>{{domxref("ChannelSplitterNode")}}</dt> + <dd>La interfaz <code><strong>ChannelSplitterNode</strong></code> separa los diferentes canales de una fuente de audio enn un conjunto de salidas <em>mono</em>.</dd> + <dt>{{domxref("ChannelMergerNode")}}</dt> + <dd>La interfaz <code><strong>ChannelMergerNode</strong></code> reune las diferentes salidas mono en una sola salida. Cada entrada deberá ser usada para llenar un canal de la salida.</dd> +</dl> + +<h3 id="Espacialización_de_audio">Espacialización de audio</h3> + +<p>Estas interfaces te permiten agregar efectos de paneo de especialización de audio a tus fuentes de audio.</p> + +<dl> + <dt>{{domxref("AudioListener")}}</dt> + <dd>La interfaz <strong><code>AudioListener</code></strong><strong> </strong>representa la posición y orientación de la única persona escuchando la escena de audio usada en la espacialización de audio.</dd> + <dt>{{domxref("PannerNode")}}</dt> + <dd>La interfaz <code><strong>PannerNode</strong></code> representa la posición y comportamiento de una señal de fuente de audio en un espacio 3D, permitiéndote crear efectos de paneo complejos.</dd> + <dt>{{domxref("StereoPannerNode")}}</dt> + <dd>La interfaz <code><strong>StereoPannerNode</strong></code> representa un nodo de panner estéreo simple que se puede usar para panoramizar un flujo de audio hacia la izquierda o hacia la derecha.</dd> +</dl> + +<h3 id="Proccesamiento_de_audio_en_JavaScript">Proccesamiento de audio en JavaScript</h3> + +<p>Usando worklets de audio (pequeñas tareas), puedes definir nodos personalizados de audio escritos en JavaScript o <a href="/en-US/docs/WebAssembly">WebAssembly</a>. Los worklets de audios implementan la interfaz {{domxref("Worklet")}}, una versión ligera de la interfaz {{domxref("Worker")}}. A partir del enero de 2018, los worklets de audio están disponibles en Chrome 64 detrás de un identificador.</p> + +<dl> + <dt>{{domxref("AudioWorklet")}} {{experimental_inline}}</dt> + <dd>La interfaz <code>AudioWorklet</code> está disponible a través de {{domxref("BaseAudioContext.audioWorklet")}} y te permite agregar nuevos móduloss al worklet de audio.</dd> + <dt>{{domxref("AudioWorkletNode")}} {{experimental_inline}}</dt> + <dd>La intefaz <code>AudioWorkletNode</code> representa un {{domxref("AudioNode")}} que está insertada en un gráfico de audio y puede pasar mensajes a la <code>AudioWorkletProcessor</code>.</dd> + <dt>{{domxref("AudioWorkletProcessor")}} {{experimental_inline}}</dt> + <dd>La interfaz <code>AudioWorkletProcessor</code> representa código de procesamiento de audio que se ejecuta en un <code>AudioWorkletGlobalScope</code> que genera, procesa, o analiza audio directamente, y puede pasar mensajes al <code>AudioWorkletNode</code>.</dd> + <dt>{{domxref("AudioWorkletGlobalScope")}} {{experimental_inline}}</dt> + <dd>La interfaz <code>AudioWorkletGlobalScope</code> es un objeto derivado de <code>WorkletGlobalScope</code> que representa un contexto del worker en el que se ejecuta un script de procesamiento de audio; está diseñado para permitir la generación, procesamiento, y análisis de datos de audio directamente usando JavaScript en un hilo worklet.</dd> +</dl> + +<p>Antes de que se definieran los worklets de audio, la API de Web Audio usó <code>ScriptProcessorNode</code> {{deprecated_inline}} para procesamiento de audio basado en JavaScript. Como el código se ejecuta en el hilo principal, tuvo un mal rendimiento. <code>ScriptProcessorNode</code> se mantiene por razones históricas pero está marcada como obsoleta y será removida en una versión futura de la especificación.</p> + +<dl> + <dt>{{domxref("ScriptProcessorNode")}} {{deprecated_inline}}</dt> + <dd>La interfaz <strong><code>ScriptProcessorNode</code></strong><strong> </strong>permite la generación, procesamiento, o análisis de audio usando JavaScript. Es un módulo de procesamiento de audio {{domxref("AudioNode")}} que está enlazado a dos buffers, uno conteniendo la actual entrada, uno conteniendo la salida. Un evento, implementando la interfaz {{domxref("AudioProcessingEvent")}}, es enviado al objeto cada vez que el buffer de entrada contiene nuevos datos, y el manejador del evento termina cuando ha llenado el buffer de salida con datos.</dd> + <dt>{{event("audioprocess")}} (event) {{deprecated_inline}}</dt> + <dd>El evento <code>audioprocess</code> es lanzado cuando un buffer de entrada de un {{domxref("ScriptProcessorNode")}} del API del Audio Web está listo para ser procesado.</dd> + <dt>{{domxref("AudioProcessingEvent")}} {{deprecated_inline}}</dt> + <dd>El evento <code>AudioProcessingEvent</code> del <a href="/en-US/docs/Web_Audio_API" title="/en-US/docs/Web_Audio_API">API de Audio Web</a> representa los eventos que ocurren cuando un buffer de entrada {{domxref("ScriptProcessorNode")}} está listo para ser procesado.</dd> +</dl> + +<h3 id="Procesamiento_de_audio_offlineen_segundo_plano">Procesamiento de audio offline/en segundo plano</h3> + +<p>Es posible procesar/renderizar un gráfico de muy rápidamente en segundo plano — renderizándolo en un {{domxref("AudioBuffer")}} en lugar de hacerlo a los altavoces del equipo — con lo siguiente.</p> + +<dl> + <dt>{{domxref("OfflineAudioContext")}}</dt> + <dd>La interfaz <strong><code>OfflineAudioContext</code></strong> es una interfaz {{domxref("AudioContext")}} representando un gráfico de procesamiento de audio construido a partir de varios {{domxref("AudioNode")}} enlazados juntos. En contraste con un <code>AudioContext</code> estándar, un <code>OfflineAudioContext</code> realmente no procesa el audio sino que lo genera, <em>lo más rápido que puede</em>, en un buffer.</dd> + <dt>{{event("complete")}} (event)</dt> + <dd>El evento <code>complete</code> es lanzado cuando el renderizado de un {{domxref("OfflineAudioContext")}} está terminado.</dd> + <dt>{{domxref("OfflineAudioCompletionEvent")}}</dt> + <dd>La interfaz <code>OfflineAudioCompletionEvent</code> representa los eventos que ocurren cuando procesamiento de un {{domxref("OfflineAudioContext")}} is terminado. El evento {{event("complete")}} implementa esta interfaz.</dd> +</dl> + +<h2 id="Example" name="Example">Interfaces obsoletas</h2> + +<p>Las siguientes interfaces fueron definidas en versiones antiguas de la especificación del API de Audio Web, pero ahora están obsoletas y han sido reemplazadas por otras interfaces.</p> + +<dl> + <dt>{{domxref("JavaScriptNode")}}</dt> + <dd>Usada para dirigir procesamiento de audio a través de JavaScript. Esta interfaz está obsoleta, y ha sido reemplazada por {{domxref("ScriptProcessorNode")}}.</dd> + <dt>{{domxref("WaveTableNode")}}</dt> + <dd>Usada para definir una forma de onda periórica. Esta interfaz está obsoleta, y ha sido reemplazada por {{domxref("PeriodicWave")}}.</dd> +</dl> + +<h2 id="Example" name="Example">Ejemplo</h2> + +<p>Este ejemplo muestra una amplia variedad de funciones del API de Audio Web siendo usadas. Puedes ver este código en acción en la demostración de <a href="https://mdn.github.io/voice-change-o-matic/">Voice-change-o-matic</a> (también revisa el <a href="https://github.com/mdn/voice-change-o-matic">código completo en Github</a>) — este es un demo experimental de juguete cambiador de voz; manten tus parlantes en bajo volumen cuando lo uses ¡Al menos al comenzar!</p> + +<p>Las líneas del API de Audio Web están resaltadas; si quieres saber más sobre lo que hacen los diferentes métodos, etc., busca en las páginas de referencia.</p> + +<pre class="brush: js; highlight:[1,2,9,10,11,12,36,37,38,39,40,41,62,63,72,114,115,121,123,124,125,147,151]">var audioCtx = new (window.AudioContext || window.webkitAudioContext)(); // definir contexto de audio +// los navegadores Webkit/blink necesitan prefijo, Safari no funcionará sin window. + +var voiceSelect = document.getElementById("voice"); // caja de selección para la selección de opciones de efectos de voz +var visualSelect = document.getElementById("visual"); // caja<span id="result_box" lang="es"><span class="alt-edited"> de selección para la selección de opciones de visualización de audio</span></span> +var mute = document.querySelector('.mute'); // botón de silencio +var drawVisual; // requestAnimationFrame + +var analyser = audioCtx.createAnalyser(); +var distortion = audioCtx.createWaveShaper(); +var gainNode = audioCtx.createGain(); +var biquadFilter = audioCtx.createBiquadFilter(); + +function makeDistortionCurve(amount) { // función para hacer que la forma de curva para distorsión / nodo modificador de onda para usar + var k = typeof amount === 'number' ? amount : 50, + n_samples = 44100, + curve = new Float32Array(n_samples), + deg = Math.PI / 180, + i = 0, + x; + for ( ; i < n_samples; ++i ) { + x = i * 2 / n_samples - 1; + curve[i] = ( 3 + k ) * x * 20 * deg / ( Math.PI + k * Math.abs(x) ); + } + return curve; +}; + +navigator.getUserMedia ( + // restricciones - solo el audio es necesario para esta aplicación + { + audio: true + }, + + // Retrollamada de éxito + function(stream) { + source = audioCtx.createMediaStreamSource(stream); + source.connect(analyser); + analyser.connect(distortion); + distortion.connect(biquadFilter); + biquadFilter.connect(gainNode); + gainNode.connect(audioCtx.destination); // conectando los diferentes nodos de grafo de audio juntos + + visualize(stream); + voiceChange(); + + }, + + // Retrollamada de error + function(err) { + console.log('Se produjo el siguiente error gUM: ' + err); + } +); + +function visualize(stream) { + WIDTH = canvas.width; + HEIGHT = canvas.height; + + var visualSetting = visualSelect.value; + console.log(visualSetting); + + if(visualSetting == "sinewave") { + analyser.fftSize = 2048; + var bufferLength = analyser.frequencyBinCount; // la mitad del valor de FFT + var dataArray = new Uint8Array(bufferLength); // crear una matriz para almacenar los datos + + canvasCtx.clearRect(0, 0, WIDTH, HEIGHT); + + function draw() { + + drawVisual = requestAnimationFrame(draw); + + analyser.getByteTimeDomainData(dataArray); // obtener datos de forma de onda y ponerlo en la matriz creada arriba + + canvasCtx.fillStyle = 'rgb(200, 200, 200)'; // dibujar onda con canvas + canvasCtx.fillRect(0, 0, WIDTH, HEIGHT); + + canvasCtx.lineWidth = 2; + canvasCtx.strokeStyle = 'rgb(0, 0, 0)'; + + canvasCtx.beginPath(); + + var sliceWidth = WIDTH * 1.0 / bufferLength; + var x = 0; + + for(var i = 0; i < bufferLength; i++) { + + var v = dataArray[i] / 128.0; + var y = v * HEIGHT/2; + + if(i === 0) { + canvasCtx.moveTo(x, y); + } else { + canvasCtx.lineTo(x, y); + } + + x += sliceWidth; + } + + canvasCtx.lineTo(canvas.width, canvas.height/2); + canvasCtx.stroke(); + }; + + draw(); + + } else if(visualSetting == "off") { + canvasCtx.clearRect(0, 0, WIDTH, HEIGHT); + canvasCtx.fillStyle = "red"; + canvasCtx.fillRect(0, 0, WIDTH, HEIGHT); + } + +} + +function voiceChange() { + distortion.curve = new Float32Array; + biquadFilter.gain.value = 0; // restablecer los efectos cada vez que se ejecuta la función VoiceChange + + var voiceSetting = voiceSelect.value; + console.log(voiceSetting); + + if(voiceSetting == "distortion") { + distortion.curve = makeDistortionCurve(400); // aplicar distorsión al sonido usando el nodo waveshaper + } else if(voiceSetting == "biquad") { + biquadFilter.type = "lowshelf"; + biquadFilter.frequency.value = 1000; + biquadFilter.gain.value = 25; // aplicar el filtro lowshelf a los sonidos usando biquad + } else if(voiceSetting == "off") { + console.log("Voice settings turned off"); // no hacer nada, ya que se eligió la opción de apagado + } + +} + +// oyentes de eventos para cambiar la visualización y la configuración de voz + +visualSelect.onchange = function() { + window.cancelAnimationFrame(drawVisual); + visualize(stream); +} + +voiceSelect.onchange = function() { + voiceChange(); +} + +mute.onclick = voiceMute; + +function voiceMute() { // alternar para silenciar y activar el sonido + if(mute.id == "") { + gainNode.gain.value = 0; // ganancia establecida en 0 para silenciar el sonido + mute.id = "activated"; + mute.innerHTML = "Unmute"; + } else { + gainNode.gain.value = 1; // ganancia establecida en 1 para activar el sonido + mute.id = ""; + mute.innerHTML = "Mute"; + } +} +</pre> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Especificación</th> + <th scope="col">Estado</th> + <th scope="col">Comentario</th> + </tr> + <tr> + <td>{{SpecName('Web Audio API')}}</td> + <td>{{Spec2('Web Audio API')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Compatibilidad_en_navegadores">Compatibilidad en navegadores</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Soporte Básico</td> + <td>14 {{property_prefix("webkit")}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>23</td> + <td>{{CompatNo}}</td> + <td>15 {{property_prefix("webkit")}}<br> + 22 (unprefixed)</td> + <td>6 {{property_prefix("webkit")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox Mobile (Gecko)</th> + <th>Firefox OS</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Soporte Básico</td> + <td>{{CompatNo}}</td> + <td>28 {{property_prefix("webkit")}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>25</td> + <td>1.2</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>6 {{property_prefix("webkit")}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="También_ver">También ver</h2> + +<ul> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Using_Web_Audio_API">Usando el API de Audio Web</a></li> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API">Visualizaciones con el API de Audio Web</a></li> + <li><a href="http://mdn.github.io/voice-change-o-matic/">Voice-change-O-matic example</a></li> + <li><a href="http://mdn.github.io/violent-theremin/">Violent Theremin example</a></li> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Web_audio_spatialization_basics">Bases de la espacialización de audio Web</a></li> + <li><a href="http://www.html5rocks.com/tutorials/webaudio/positional_audio/" title="http://www.html5rocks.com/tutorials/webaudio/positional_audio/">Mixing Positional Audio and WebGL</a></li> + <li><a href="http://www.html5rocks.com/tutorials/webaudio/games/" title="http://www.html5rocks.com/tutorials/webaudio/games/">Developing Game Audio with the Web Audio API</a></li> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext" title="/en-US/docs/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext">Porting webkitAudioContext code to standards based AudioContext</a></li> + <li><a href="https://github.com/bit101/tones">Tonos</a>: Una sencilla librería para reproducción de tonos/notas específicas usando el API de Audio Web.</li> + <li><a href="https://github.com/goldfire/howler.js/">howler.js</a>: a JS audio library that defaults to <a href="https://dvcs.w3.org/hg/audio/raw-file/tip/webaudio/specification.html">Web Audio API</a> and falls back to <a href="http://www.whatwg.org/specs/web-apps/current-work/#the-audio-element">HTML5 Audio</a>, as well as providing other useful features.</li> + <li><a href="https://github.com/mattlima/mooog">Mooog</a>: jQuery-style chaining of AudioNodes, mixer-style sends/returns, and more.</li> + <li><a class="external external-icon" href="https://github.com/chrisjohndigital/OpenLang">OpenLang</a>: HTML5 video language lab web application using the Web Audio API to record and combine video and audio from different sources into a single file (<a class="external external-icon" href="https://github.com/chrisjohndigital/OpenLang">source on GitHub</a>)</li> +</ul> + +<h3 id="Enlaces_rápidos">Enlaces rápidos</h3> + +<ol> + <li><strong>Guíass</strong> + + <ol> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Basic_concepts_behind_Web_Audio_API">Conceptos básicos detrás del API de Audio Web</a></li> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Using_Web_Audio_API">Usando el API de Audio Web</a></li> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Visualizations_with_Web_Audio_API">Visualizaciones con el API de Audio Web</a></li> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Web_audio_spatialization_basics">Bases de la espacialización de audio Web</a></li> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext" title="/en-US/docs/Web_Audio_API/Porting_webkitAudioContext_code_to_standards_based_AudioContext">Portando código de webkitAudioContext a estándares basados en AudioContext</a></li> + </ol> + </li> + <li><strong>Ejemplos</strong> + <ol> + <li><a href="/en-US/docs/Web/API/Web_Audio_API/Simple_synth">Teclado sintetizador sencillo</a></li> + <li><a href="http://mdn.github.io/voice-change-o-matic/">Voice-change-O-matic</a></li> + <li><a href="http://mdn.github.io/violent-theremin/">Violent Theremin</a></li> + </ol> + </li> + <li><strong>Interfaces</strong> + <ol> + <li>{{domxref("AnalyserNode")}}</li> + <li>{{domxref("AudioBuffer")}}</li> + <li>{{domxref("AudioScheduledSourceNode")}}</li> + <li>{{domxref("AudioBufferSourceNode")}}</li> + <li>{{domxref("AudioContext")}}</li> + <li>{{domxref("AudioDestinationNode")}}</li> + <li>{{domxref("AudioListener")}}</li> + <li>{{domxref("AudioNode")}}</li> + <li>{{domxref("AudioParam")}}</li> + <li>{{event("audioprocess")}} (event)</li> + <li>{{domxref("AudioProcessingEvent")}}</li> + <li>{{domxref("BiquadFilterNode")}}</li> + <li>{{domxref("ChannelMergerNode")}}</li> + <li>{{domxref("ChannelSplitterNode")}}</li> + <li>{{event("complete")}} (event)</li> + <li>{{domxref("ConvolverNode")}}</li> + <li>{{domxref("DelayNode")}}</li> + <li>{{domxref("DynamicsCompressorNode")}}</li> + <li>{{event("ended_(Web_Audio)", "ended")}} (event)</li> + <li>{{domxref("GainNode")}}</li> + <li>{{domxref("MediaElementAudioSourceNode")}}</li> + <li>{{domxref("MediaStreamAudioDestinationNode")}}</li> + <li>{{domxref("MediaStreamAudioSourceNode")}}</li> + <li>{{domxref("OfflineAudioCompletionEvent")}}</li> + <li>{{domxref("OfflineAudioContext")}}</li> + <li>{{domxref("OscillatorNode")}}</li> + <li>{{domxref("PannerNode")}}</li> + <li>{{domxref("PeriodicWave")}}</li> + <li>{{domxref("ScriptProcessorNode")}}</li> + <li>{{domxref("WaveShaperNode")}}</li> + </ol> + </li> +</ol> diff --git a/files/es/web/api/web_crypto_api/checking_authenticity_with_password/index.html b/files/es/web/api/web_crypto_api/checking_authenticity_with_password/index.html deleted file mode 100644 index f2e2ef65fd..0000000000 --- a/files/es/web/api/web_crypto_api/checking_authenticity_with_password/index.html +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: Verificando la autenticidad usando contraseña -slug: Web/API/Web_Crypto_API/Checking_authenticity_with_password -translation_of: Web/API/Web_Crypto_API/Checking_authenticity_with_password ---- -<p>{{APIRef("Web Crypto API")}}{{draft}}</p> - -<p>La autenticidad del mensaje puede ser verificada usando el API Crypto Web. En este artículo mostrarémos como crear y controlar una firma digital utilizando una contraseña y una función hash.</p> - -<p>Un algoritmo HMAC toma una llave y genera un código digerido de la llave y los datos a firmar. Posteriormente, cualquiera con la llave puede volver a generar el mismo código digerido para verificar si los datos han sido alterados. Además, mediante el conocimiento de una clave secreta, permite almacenar juntos el código digerido y los datos: un atacante no podrá generar un código digerido sobre datos manipulados si no conoce la clave secreta.</p> - -<p>Note that this algorithm doesn't carry any information about the person owning the data, nor its unicity: the mere knowledge of the key is enough to alter the data.</p> - -<p>Let's assume that the data is stored on the computer. To access it, both for writing and reading, we will use <code>localforage.js</code> a small library wrapping the different storages capabilities of a browser in the same interface. This library is not an essential component of this use case and is used here for convenience, to keep focused on what really matter, the cryptographic part.</p> - -<p>The data we want to access is of the form:</p> - -<p> </p> - -<p>where <code>data</code><em> </em>is the information to guarantee the integrity and <code>signature</code> the information used to verify it.</p> - -<p>Cryptographic keys can't be remembered by heart by human, and passwords, or passphrases, make bad, that is unsecure, cryptographic key. To solve this problem, cryptographers have designed algorithms generating cryptographically-sound keys from password. Knowing the password allowed to regenerate the same key and to use it.</p> - -<p>We ask the user for a password, and we use it to generate the key:</p> - -<pre> </pre> - -<p>With that key, we will be able to compute the <em>mac</em> of the data.</p> - -<pre> </pre> diff --git a/files/es/web/api/web_speech_api/uso_de_la_web_speech_api/index.html b/files/es/web/api/web_speech_api/using_the_web_speech_api/index.html index 407de0e10d..407de0e10d 100644 --- a/files/es/web/api/web_speech_api/uso_de_la_web_speech_api/index.html +++ b/files/es/web/api/web_speech_api/using_the_web_speech_api/index.html diff --git a/files/es/web/api/api_de_almacenamiento_web/index.html b/files/es/web/api/web_storage_api/index.html index 26a858d254..26a858d254 100644 --- a/files/es/web/api/api_de_almacenamiento_web/index.html +++ b/files/es/web/api/web_storage_api/index.html diff --git a/files/es/web/api/api_de_almacenamiento_web/usando_la_api_de_almacenamiento_web/index.html b/files/es/web/api/web_storage_api/using_the_web_storage_api/index.html index 086af18610..086af18610 100644 --- a/files/es/web/api/api_de_almacenamiento_web/usando_la_api_de_almacenamiento_web/index.html +++ b/files/es/web/api/web_storage_api/using_the_web_storage_api/index.html diff --git a/files/es/web/api/web_workers_api/using_web_workers/index.html b/files/es/web/api/web_workers_api/using_web_workers/index.html new file mode 100644 index 0000000000..db4dbc07e3 --- /dev/null +++ b/files/es/web/api/web_workers_api/using_web_workers/index.html @@ -0,0 +1,633 @@ +--- +title: Usando Web Workers +slug: Web/Guide/Performance/Usando_web_workers +translation_of: Web/API/Web_Workers_API/Using_web_workers +--- +<p><span class="seoSummary">Los Web Workers dedicados proveen un medio sencillo para que el contenido web ejecute scripts en hilos en segundo plano. Una vez creado, un worker puede enviar mensajes a la tarea creada mediante envio de mensajes al manejador de eventos especificado por el creador.</span> Sin embargo, <strong>los workers trabajan dentro de un <a href="https://developer.mozilla.org/en-US/docs/JavaScript/DedicatedWorkerGlobalScope">contexto global</a> diferente de la ventana actual</strong> (usar el atajo <span style="line-height: 1.5;"> {{ domxref("window") }} en lugar de </span><span style="line-height: 1.5;">{{ domxref("window.self","self") }} con el fin de obtener el scope actual dentro de un </span><span style="line-height: 1.5;">{{ domxref("Worker") }} retornaría, de hecho, un error).</span></p> + +<p>El hilo worker puede realizar tareas sin interferir con la interfaz de usuario. Ademas, pueden realizar I/O usando <code style="font-size: 14px;"><a class="internal" href="/en/nsIXMLHttpRequest" title="En/XMLHttpRequest">XMLHttpRequest</a></code><span style="line-height: 1.5;"> (aunque el responseXML y los atributos channel son siempre null).</span></p> + +<p><span style="line-height: 1.5;">Para documentacion de referencia acerca de workers busca </span><span style="line-height: 1.5;">{{ domxref("Worker") }} ; este articulo complementa ese ofreciendo ejemplos y detalles adicionales. Para una lista de las funciones disponibles sobre workers, visita </span><span style="line-height: 1.5;"> </span><a href="https://developer.mozilla.org/en-US/docs/Web/Guide/Needs_categorization/Functions_available_to_workers?redirect=no" style="line-height: 1.5;" title="En/DOM/Worker/Functions available to workers">Functions and interfaces available to workers</a><span style="line-height: 1.5;">.</span></p> + +<h2 id="Acerca_de_seguridad_de_hilos" style="line-height: 22.79199981689453px;">Acerca de seguridad de hilos</h2> + +<p>La interfaz <span style="line-height: 1.5;"> {{ domxref("Worker") }} crea hilos a nivel de SO reales, y la concurrencia puede causar effectos interesantes en tu código si no eres cuidadoso. Sin embargo, en el caso de los web workers, el control cuidadoso de los puntos de comunicacion con otros hilos indica que es realmente muy dificil causar problemas de concurrencia. No existe acceso a componentes no-hilo seguros o al DOM y debes pasar la informacion entrante o saliente del hilo a traves de objetos serializados. Así que debes poner esfuerzo para causar problemas en tu código.</span></p> + +<p><strong style="">Creando un web worker</strong></p> + +<p>Crear un nuevo worker es simple. Sólo tienes que llamar el constructor {{ domxref("Worker.Worker", "Worker()") }}, especificando la URI de un script a ejecutar en el hilo del worker (<em>worker thread</em>), y, si deseas poder recibir notificaciones del worker, establece la propiedad {{domxref("Worker.onmessage")}} del worker a una función de manejo de eventos apropiada.</p> + +<div style="overflow: hidden;"> +<pre class="brush: js notranslate">var myWorker = new Worker("my_task.js"); + +myWorker.onmessage = function (oEvent) { + console.log("Called back by the worker!\n"); +};</pre> +</div> + +<p>Alternativamente, puedes usar <code>addEventListener()</code> :</p> + +<div style="overflow: hidden;"> +<pre class="brush: js notranslate">var myWorker = new Worker("my_task.js"); + +myWorker.addEventListener("message", function (oEvent) { + console.log("Called back by the worker!\n"); +}, false); + +myWorker.postMessage(""); // start the worker.</pre> +</div> + +<p>La Línea 1 en este ejemplo crea un nuevo worker (<em>worker thread)</em>. La Línea 3 configura un manejador de eventos (<em>listener</em>) para encargarse de los eventos <code>message</code> del worker. Este manejador de eventos se llamará cuando el worker llame a su propia función {{domxref("Worker.postMessage()")}}. Finalmente, la Linea 7 inicia el worker <em>(worker thread)</em>.</p> + +<div class="note"><strong>Nota</strong> : La URI pasada como parámetro del constructor de <code>Worker</code> debe obedecer la política <a href="/en/Same_origin_policy_for_JavaScript" title="Same origin policy for JavaScript">same-origin policy</a> . Actualmente hay desacuerdo entre los desarolladores de navegadores sobre qué URIs son del mismo origen; Gecko 10.0 {{ geckoRelease("10.0") }} y posteriores sí permiten data URIs e Internet Explorer 10 no permite Blob URIs como un script válido para los workers.</div> + +<h2 id="Pasando_datos">Pasando datos</h2> + +<p>Los datos pasan entre la página principal y los workers son <strong>copiados</strong>, no compartidos. Los objetos se serializan a medida que se entregan al worker, y posteriormente, se deserializan en el otro extremo. La página y el worker <strong>no comparten la misma instancia</strong>, por lo que el resultado final es que un duplicado es creado en cada extremo. La mayoría de los navegadores implementan esta característica como <a href="/en/DOM/The_structured_clone_algorithm" title="The structured clone algorithm">structured cloning</a>.</p> + +<p>Antes de continuar, vamos a crear con fines didácticos una función llamada <code>emulateMessage()</code> que simulará el comportamiento de un valor el cual es clonado y no compartido durante el paso desde un <em>worker </em>a la página principal o viceversa:</p> + +<pre class="brush: js notranslate">function emulateMessage (vVal) { + return eval("(" + JSON.stringify(vVal) + ")"); +} + +// Tests + +// test #1 +var example1 = new Number(3); +alert(typeof example1); // object +alert(typeof emulateMessage(example1)); // number + +// test #2 +var example2 = true; +alert(typeof example2); // boolean +alert(typeof emulateMessage(example2)); // boolean + +// test #3 +var example3 = new String("Hello World"); +alert(typeof example3); // object +alert(typeof emulateMessage(example3)); // string + +// test #4 +var example4 = { + "name": "John Smith", + "age": 43 +}; +alert(typeof example4); // object +alert(typeof emulateMessage(example4)); // object + +// test #5 +function Animal (sType, nAge) { + this.type = sType; + this.age = nAge; +} +var example5 = new Animal("Cat", 3); +alert(example5.constructor); // Animal +alert(emulateMessage(example5).constructor); // Object</pre> + +<p>A Un valor que es clonado y no compartido se denomina <em>mensaje</em>. De vuelta con los workers, los <em>mensajes</em> pueden ser enviados hacia y desde el hilo principal empleando <code>postMessage()</code>. Los eventos de <code>mensaje</code> {{domxref("MessageEvent.data", "data")}} atributo contienen datos devueltos desde el worker.</p> + +<p><strong>example.html</strong>: (la página principal):</p> + +<pre class="brush: js notranslate">var myWorker = new Worker("my_task.js"); + +myWorker.onmessage = function (oEvent) { + console.log("Worker said : " + oEvent.data); +}; + +myWorker.postMessage("ali");</pre> + +<p><strong>my_task.js</strong> (el worker):</p> + +<pre class="brush: js notranslate">postMessage("I\'m working before postMessage(\'ali\')."); + +onmessage = function (oEvent) { + postMessage("Hi " + oEvent.data); +};</pre> + +<div class="note"><strong>Note:</strong> Como siempre, los hilos en segundo plano -incluyendo workers- <strong>no pueden manipular el DOM</strong>. Si acciones tomadas por el hilo en segundo planos resultarían en cambios en el DOM, deberian enviar mensajes a sus creadores para llevarlos a cabo.</div> + +<p>The <a href="/en-US/docs/Web/Guide/DOM/The_structured_clone_algorithm" style="line-height: 1.572;" title="The structured clone algorithm">structured cloning</a> algorithm can accept JSON and a few things that JSON can't like circular references.</p> + +<h3 id="Ejemplos_pasando_datos">Ejemplos pasando datos</h3> + +<h4 id="Example_1_Crear_un_eval_asíncrono_genérico">Example #1: Crear un "<code>eval() asíncrono</code>" genérico</h4> + +<p>El siguiente ejemplo muestra como usar un worker para ejecutar <strong>asíncronamente</strong> cualquier tipo de código en Javascript a traves de <a href="/en-US/docs/JavaScript/Reference/Global_Objects/eval" title="/en-US/docs/JavaScript/Reference/Global_Objects/eval"><code>eval</code></a> dentro del worker:</p> + +<pre class="brush: js notranslate">// Syntax: asyncEval(code[, listener]) + +var asyncEval = (function () { + + var aListeners = [], oParser = new Worker("data:text/javascript;charset=US-ASCII,onmessage%20%3D%20function%20%28oEvent%29%20%7B%0A%09postMessage%28%7B%0A%09%09%22id%22%3A%20oEvent.data.id%2C%0A%09%09%22evaluated%22%3A%20eval%28oEvent.data.code%29%0A%09%7D%29%3B%0A%7D"); + + oParser.onmessage = function (oEvent) { + if (aListeners[oEvent.data.id]) { aListeners[oEvent.data.id](oEvent.data.evaluated); } + delete aListeners[oEvent.data.id]; + }; + + + return function (sCode, fListener) { + aListeners.push(fListener || null); + oParser.postMessage({ + "id": aListeners.length - 1, + "code": sCode + }); + }; + +})();</pre> + +<p>Ejemplo de uso:</p> + +<pre class="brush: js notranslate">// asynchronous alert message... +asyncEval("3 + 2", function (sMessage) { + alert("3 + 2 = " + sMessage); +}); + +// asynchronous print message... +asyncEval("\"Hello World!!!\"", function (sHTML) { + document.body.appendChild(document.createTextNode(sHTML)); +}); + +// asynchronous void... +asyncEval("(function () {\n\tvar oReq = new XMLHttpRequest();\n\toReq.open(\"get\", \"http://www.mozilla.org/\", false);\n\toReq.send(null);\n\treturn oReq.responseText;\n})()");</pre> + +<h4 id="Ejemplo_2_Paso_avanzado_de_JSON_Data_y_creación_de_un_sistema_de_conmutación">Ejemplo #2: Paso avanzado de JSON Data y creación de un sistema de conmutación</h4> + +<p>Si tiene que pasar datos complejos y tienes que llamar a muchas funciones diferentes tanto en la página principal como en el Worker, puede crear un sistema como el siguiente.</p> + +<p><strong>example.html</strong> (the main page):</p> + +<pre class="brush: html notranslate"><!doctype html> +<html> +<head> +<meta charset="UTF-8" /> +<title>MDN Example - Queryable worker</title> +<script type="text/javascript"> + /* + QueryableWorker instances methods: + * sendQuery(queryable function name, argument to pass 1, argument to pass 2, etc. etc): calls a Worker's queryable function + * postMessage(string or JSON Data): see Worker.prototype.postMessage() + * terminate(): terminates the Worker + * addListener(name, function): adds a listener + * removeListener(name): removes a listener + QueryableWorker instances properties: + * defaultListener: the default listener executed only when the Worker calls the postMessage() function directly + */ + function QueryableWorker (sURL, fDefListener, fOnError) { + var oInstance = this, oWorker = new Worker(sURL), oListeners = {}; + this.defaultListener = fDefListener || function () {}; + oWorker.onmessage = function (oEvent) { + if (oEvent.data instanceof Object && oEvent.data.hasOwnProperty("vo42t30") && oEvent.data.hasOwnProperty("rnb93qh")) { + oListeners[oEvent.data.vo42t30].apply(oInstance, oEvent.data.rnb93qh); + } else { + this.defaultListener.call(oInstance, oEvent.data); + } + }; + if (fOnError) { oWorker.onerror = fOnError; } + this.sendQuery = function (/* queryable function name, argument to pass 1, argument to pass 2, etc. etc */) { + if (arguments.length < 1) { throw new TypeError("QueryableWorker.sendQuery - not enough arguments"); return; } + oWorker.postMessage({ "bk4e1h0": arguments[0], "ktp3fm1": Array.prototype.slice.call(arguments, 1) }); + }; + this.postMessage = function (vMsg) { + //I just think there is no need to use call() method + //how about just oWorker.postMessage(vMsg); + //the same situation with terminate + //well,just a little faster,no search up the prototye chain + Worker.prototype.postMessage.call(oWorker, vMsg); + }; + this.terminate = function () { + Worker.prototype.terminate.call(oWorker); + }; + this.addListener = function (sName, fListener) { + oListeners[sName] = fListener; + }; + this.removeListener = function (sName) { + delete oListeners[sName]; + }; + }; + + // your custom "queryable" worker + var oMyTask = new QueryableWorker("my_task.js" /* , yourDefaultMessageListenerHere [optional], yourErrorListenerHere [optional] */); + + // your custom "listeners" + + oMyTask.addListener("printSomething", function (nResult) { + document.getElementById("firstLink").parentNode.appendChild(document.createTextNode(" The difference is " + nResult + "!")); + }); + + oMyTask.addListener("alertSomething", function (nDeltaT, sUnit) { + alert("Worker waited for " + nDeltaT + " " + sUnit + " :-)"); + }); +</script> +</head> +<body> + <ul> + <li><a id="firstLink" href="javascript:oMyTask.sendQuery('getDifference', 5, 3);">What is the difference between 5 and 3?</a></li> + <li><a href="javascript:oMyTask.sendQuery('waitSomething');">Wait 3 seconds</a></li> + <li><a href="javascript:oMyTask.terminate();">terminate() the Worker</a></li> + </ul> +</body> +</html></pre> + +<p><strong>my_task.js</strong> (el worker):</p> + +<pre class="brush: js notranslate">// your custom PRIVATE functions + +function myPrivateFunc1 () { + // do something +} + +function myPrivateFunc2 () { + // do something +} + +// etc. etc. + +// your custom PUBLIC functions (i.e. queryable from the main page) + +var queryableFunctions = { + // example #1: get the difference between two numbers: + getDifference: function (nMinuend, nSubtrahend) { + reply("printSomething", nMinuend - nSubtrahend); + }, + // example #2: wait three seconds + waitSomething: function () { + setTimeout(function() { reply("alertSomething", 3, "seconds"); }, 3000); + } +}; + +// system functions + +function defaultQuery (vMsg) { + // your default PUBLIC function executed only when main page calls the queryableWorker.postMessage() method directly + // do something +} + +function reply (/* listener name, argument to pass 1, argument to pass 2, etc. etc */) { + if (arguments.length < 1) { throw new TypeError("reply - not enough arguments"); return; } + postMessage({ "vo42t30": arguments[0], "rnb93qh": Array.prototype.slice.call(arguments, 1) }); +} + +onmessage = function (oEvent) { + if (oEvent.data instanceof Object && oEvent.data.hasOwnProperty("bk4e1h0") && oEvent.data.hasOwnProperty("ktp3fm1")) { + queryableFunctions[oEvent.data.bk4e1h0].apply(self, oEvent.data.ktp3fm1); + } else { + defaultQuery(oEvent.data); + } +};</pre> + +<p>Es un método posible para conmutar el contenido de cada mensaje de cada mainpage-worker y viceversa.</p> + +<h3 id="Pasando_datos_mediante_transferencia_de_propiedades_objetos_transferibles">Pasando datos mediante transferencia de propiedades (objetos transferibles)</h3> + +<p>Google Chrome 17 y Firefox 18 implementan un método adicional para enviar ciertos tipos de objetos desde o hacia el worker con un mejor rendimiento. Estos objetos se denominan objetos transferibles (transferable objects), es decir, o<span class="external">bjetos que implementan la interfaz {{domxref("Transferable")}}</span>. Los objetos transferibles se transfieren de un contexto a otro con una operación "zero-copy". Esto supone una gran mejora de rendimiento al enviar grandes cantidades de datos. Piensa en ello como un paso por referencia si vienes del mundo de C/C++. Sin embargo, a diferecia del paso por referencia, la "versión" original no queda disponible una vez transferida. Su contenido es transferido al nuevo contexto. Por ejemplo, cuando se transfiere un {{domxref("ArrayBuffer")}} de tu aplicacion al Worker, el contenido del {{domxref("ArrayBuffer")}} original se vacía y no se puede utilizar posteriormente. Su contenido es (literalmente) transferido al contexto del Worker.</p> + +<pre class="brush: js notranslate">// Create a 32MB "file" and fill it. +var uInt8Array = new Uint8Array(1024*1024*32); // 32MB +for (var i = 0; i < uInt8Array.length; ++i) { + uInt8Array[i] = i; +} + +worker.postMessage(uInt8Array.buffer, [uInt8Array.buffer]); +</pre> + +<p>Para más información sobre los objetos transferibles, <a class="external" href="http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fast" title="http://updates.html5rocks.com/2011/12/Transferable-Objects-Lightning-Fast">visita HTML5Rocks</a> .</p> + +<h2 id="Spawning_subworkers">Spawning subworkers</h2> + +<p>Workers may spawn more workers if they wish. So-called subworkers must be hosted within the same origin as the parent page. Also, the URIs for subworkers are resolved relative to the parent worker's location rather than that of the owning page. This makes it easier for workers to keep track of where their dependencies are.</p> + +<p>Subworkers are currently not supported in Chrome. See <a class="external" href="http://code.google.com/p/chromium/issues/detail?id=31666" title="http://code.google.com/p/chromium/issues/detail?id=31666">crbug.com/31666</a> .</p> + +<h2 id="Embedded_workers">Embedded workers</h2> + +<p>There is not an "official" way to embed the code of a worker within a web page as for the {{ HTMLElement("script") }} elements. But a {{ HTMLElement("script") }} element which does not have a <code>src</code> attribute and has a <code>type</code> attribute that does not identify an executable mime-type will be considered a data block element, that JavaScript could use. "Data blocks" is a more general feature of HTML5 that can carry almost any textual data. So, a worker could be embedded in this way:</p> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> +<head> +<meta charset="UTF-8" /> +<title>MDN Example - Embedded worker</title> +<script type="text/js-worker"> + // This script WON'T be parsed by JS engines because its mime-type is text/js-worker. + var myVar = "Hello World!"; + // Rest of your worker code goes here. +</script> +<script type="text/javascript"> + // This script WILL be parsed by JS engines because its mime-type is text/javascript. + function pageLog (sMsg) { + // Use a fragment: browser will only render/reflow once. + var oFragm = document.createDocumentFragment(); + oFragm.appendChild(document.createTextNode(sMsg)); + oFragm.appendChild(document.createElement("br")); + document.querySelector("#logDisplay").appendChild(oFragm); + } +</script> +<script type="text/js-worker"> + // This script WON'T be parsed by JS engines because its mime-type is text/js-worker. + onmessage = function (oEvent) { + postMessage(myVar); + }; + // Rest of your worker code goes here. +</script> +<script type="text/javascript"> + // This script WILL be parsed by JS engines because its mime-type is text/javascript. + + // In the past...: + // blob builder existed + // ...but now we use Blob...: + var blob = new Blob(Array.prototype.map.call(document.querySelectorAll("script[type=\"text\/js-worker\"]"), function (oScript) { return oScript.textContent; }),{type: "text/javascript"}); + + // Creating a new document.worker property containing all our "text/js-worker" scripts. + document.worker = new Worker(window.URL.createObjectURL(blob)); + + document.worker.onmessage = function (oEvent) { + pageLog("Received: " + oEvent.data); + }; + + // Start the worker. + window.onload = function() { document.worker.postMessage(""); }; +</script> +</head> +<body><div id="logDisplay"></div></body> +</html></pre> + +<p>The embedded worker is now nested into a new custom <code>document.worker</code> property.</p> + +<h2 id="Tiempos_fuera_e_intervalos">Tiempos fuera e intervalos</h2> + +<p>Los trabajadores pueden usar tiempos fuera e intervalos de la misma forma que el "hilo principal". Esto puede ser útil, por ejemplo, si quieres tener a tu hilo trabajador corriendo codigo periodicamente en lugar de sin parar.</p> + +<p>Ver <a class="internal" href="/en/DOM/window.setTimeout" title="En/DOM/Window.setTimeout"><code>setTimeout()</code> </a> , <a class="internal" href="/en/DOM/window.clearTimeout" title="En/DOM/Window.clearTimeout"> <code>clearTimeout()</code> </a> , <a class="internal" href="/en/DOM/window.setInterval" title="En/DOM/Window.setInterval"> <code>setInterval()</code> </a> , y <a class="internal" href="/en/DOM/window.clearInterval" title="En/DOM/Window.clearInterval"><code>clearInterval()</code> </a> para más detalles. Ver también: <a href="/en-US/docs/JavaScript/Timers" title="/en-US/docs/JavaScript/Timers">JavaScript Timers</a>.</p> + +<h2 id="Terminating_a_worker">Terminating a worker</h2> + +<p>If you need to immediately terminate a running worker, you can do so by calling the worker's <code>terminate()</code> method:</p> + +<pre class="syntaxbox notranslate">myWorker.terminate();</pre> + +<p>The worker thread is killed immediately without an opportunity to complete its operations or clean up after itself.</p> + +<p>Workers may close themselves by calling their own {{ ifmethod("nsIWorkerScope", "close") }} method:</p> + +<pre class="syntaxbox notranslate">self.close();</pre> + +<h2 id="Manejo_de_errores">Manejo de errores</h2> + +<p>When a runtime error occurs in worker, its <code>onerror</code> event handler is called. It receives an event named <code>error</code> which implements the <code>ErrorEvent</code> interface. The event doesn't bubble and is cancelable; to prevent the default action from taking place, the worker can call the error event's <a class="internal" href="/en/DOM/event.preventDefault" title="En/DOM/Event.preventDefault"> <code>preventDefault()</code> </a> method.</p> + +<p>The error event has the following three fields that are of interest:</p> + +<dl> + <dt><code>message</code></dt> + <dd>A human-readable error message.</dd> + <dt><code>filename</code></dt> + <dd>The name of the script file in which the error occurred.</dd> + <dt><code>lineno</code></dt> + <dd>The line number of the script file on which the error occurred.</dd> +</dl> + +<h2 id="Accediendo_al_objeto_navigator">Accediendo al objeto navigator</h2> + +<p>Los workers pueden acceder al objeto <code>navigator</code>, el cuál está disponible dentro de su scope actual. Este contiene los siguientes strings que pueden ser usados para identificar el navegador, al igual que puede realizarse usando scripts normales:</p> + +<ul> + <li><code>appName</code></li> + <li><code>appVersion</code></li> + <li><code>platform</code></li> + <li><code>userAgent</code></li> +</ul> + +<h2 id="Importing_scripts_and_libraries">Importing scripts and libraries</h2> + +<p>Worker threads have access to a global function, <code>importScripts()</code> , which lets them import scripts or libraries into their scope. It accepts as parameters zero or more URIs to resources to import; all of the following examples are valid:</p> + +<pre class="brush: js notranslate">importScripts(); /* imports nothing */ +importScripts('foo.js'); /* imports just "foo.js" */ +importScripts('foo.js', 'bar.js'); /* imports two scripts */ +</pre> + +<p>The browser loads each listed script and executes it. Any global objects from each script may then be used by the worker. If the script can't be loaded, <code>NETWORK_ERROR</code> is thrown, and subsequent code will not be executed. Previously executed code (including code deferred using {{ domxref("window.setTimeout()") }}) will still be functional though. Function declarations <strong>after</strong> the <code>importScripts()</code> method are also kept, since these are always evaluated before the rest of the code.</p> + +<div class="note"><strong>Note:</strong> Scripts may be downloaded in any order, but will be executed in the order in which you pass the filenames into <code>importScripts()</code> . This is done synchronously; <code>importScripts()</code> does not return until all the scripts have been loaded and executed.</div> + +<h2 id="Examples">Examples</h2> + +<p>This section provides several examples of how to use DOM workers.</p> + +<h3 id="Performing_computations_in_the_background">Performing computations in the background</h3> + +<p>One way workers are useful is to allow your code to perform processor-intensive calculations without blocking the user interface thread. In this example, a worker is used to calculate Fibonacci numbers.</p> + +<h4 id="The_JavaScript_code">The JavaScript code</h4> + +<p>The following JavaScript code is stored in the "fibonacci.js" file referenced by the HTML in the next section.</p> + +<pre class="brush: js notranslate">var results = []; + +function resultReceiver(event) { + results.push(parseInt(event.data)); + if (results.length == 2) { + postMessage(results[0] + results[1]); + } +} + +function errorReceiver(event) { + throw event.data; +} + +onmessage = function(event) { + var n = parseInt(event.data); + + if (n == 0 || n == 1) { + postMessage(n); + return; + } + + for (var i = 1; i <= 2; i++) { + var worker = new Worker("fibonacci.js"); + worker.onmessage = resultReceiver; + worker.onerror = errorReceiver; + worker.postMessage(n - i); + } + };</pre> + +<p>The worker sets the property <code>onmessage</code> to a function which will receive messages sent when the worker object's <code>postMessage()</code> is called. (Note that this differs from defining a global <em>variable</em> of that name, or defining a <em>function</em> with that name. <code>var onmessage</code> and <code>function onmessage</code> will define global properties with those names, but they will not register the function to receive messages sent by the web page that created the worker.) This starts the recursion, spawning new copies of itself to handle each iteration of the calculation.</p> + +<h4 id="The_HTML_code">The HTML code</h4> + +<pre class="brush: html notranslate"><!DOCTYPE html> +<html> + <head> + <meta charset="UTF-8" /> + <title>Test threads fibonacci</title> + </head> + <body> + + <div id="result"></div> + + <script language="javascript"> + + var worker = new Worker("fibonacci.js"); + + worker.onmessage = function(event) { + document.getElementById("result").textContent = event.data; + dump("Got: " + event.data + "\n"); + }; + + worker.onerror = function(error) { + dump("Worker error: " + error.message + "\n"); + throw error; + }; + + worker.postMessage("5"); + + </script> + </body> +</html> +</pre> + +<p>The web page creates a <code>div</code> element with the ID <code>result</code> , which gets used to display the result, then spawns the worker. After spawning the worker, the <code>onmessage</code> handler is configured to display the results by setting the contents of the <code>div</code> element, and the <code>onerror</code> handler is set to <a class="external" href="/en/Debugging_JavaScript#dump()" title="https://developer.mozilla.org/editor/fckeditor/core/editor/en/Debugging_JavaScript#dump()">dump</a> the error message.</p> + +<p>Finally, a message is sent to the worker to start it.</p> + +<p><a class="external" href="/samples/workers/fibonacci" title="https://developer.mozilla.org/samples/workers/fibonacci/">Try this example</a> .</p> + +<h3 id="Performing_web_IO_in_the_background">Performing web I/O in the background</h3> + +<p>You can find an example of this in the article <a class="internal" href="/En/Using_workers_in_extensions" title="En/Using workers in extensions">Using workers in extensions</a> .</p> + +<h3 id="Dividing_tasks_among_multiple_workers">Dividing tasks among multiple workers</h3> + +<p>As multi-core computers become increasingly common, it's often useful to divide computationally complex tasks among multiple workers, which may then perform those tasks on multiple-processor cores.</p> + +<p>example coming soon</p> + +<h3 id="Creating_workers_from_within_workers">Creating workers from within workers</h3> + +<p>The Fibonacci example shown previously demonstrates that workers can in fact <a href="#Spawning_subworkers">spawn additional workers</a>. This makes it easy to create recursive routines.</p> + +<h2 id="Browser_Compatibility" name="Browser_Compatibility">Browser compatibility</h2> + +<p>{{ CompatibilityTable() }}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Dedicated workers</td> + <td>{{CompatChrome(3)}}</td> + <td>{{CompatGeckoDesktop(1.9.1)}}</td> + <td>{{CompatIE(10)}}</td> + <td>{{CompatOpera(10.60)}}</td> + <td>{{CompatSafari(4)}}</td> + </tr> + <tr> + <td>Shared workers</td> + <td>{{CompatChrome(3)}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatOpera(10.60)}}</td> + <td>{{CompatSafari(5)}}</td> + </tr> + <tr> + <td>Passing data using <a href="/en/DOM/The_structured_clone_algorithm" title="The structured clone algorithm">structured cloning</a> . </td> + <td>{{CompatChrome(13)}}</td> + <td>{{CompatGeckoDesktop(8)}}</td> + <td>{{CompatIE(10)}}</td> + <td>{{CompatOpera(11.50)}}</td> + <td>{{CompatSafari(5.1)}}</td> + </tr> + <tr> + <td>Passing data using <a class="external" href="http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#transferable-objects" title="http://dev.w3.org/html5/spec/common-dom-interfaces.html#transferable-objects">transferable objects</a></td> + <td>17 {{ property_prefix("webkit") }}<br> + {{CompatChrome(21)}}</td> + <td>{{CompatGeckoDesktop(18)}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatOpera(15)}}</td> + <td>{{CompatSafari(6)}}</td> + </tr> + <tr> + <td>Global {{ domxref("window.URL", "URL") }}</td> + <td>10 as <code>webkitURL</code><br> + {{CompatChrome(23)}}</td> + <td>{{CompatGeckoDesktop(21)}}</td> + <td>{{CompatIE(11)}}</td> + <td>{{CompatOpera(15)}}</td> + <td>6 as <code>webkitURL</code></td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Dedicated workers</td> + <td>---</td> + <td>0.16</td> + <td>3.5 (1.9.1)</td> + <td>---</td> + <td>11</td> + <td>5</td> + </tr> + <tr> + <td>Shared workers</td> + <td>---</td> + <td>{{ CompatNo() }}</td> + <td>---</td> + <td>---</td> + <td>---</td> + <td>---</td> + </tr> + <tr> + <td>Passing data using <a href="/en/DOM/The_structured_clone_algorithm" title="The structured clone algorithm">structured cloning</a> . </td> + <td>---</td> + <td>0.16</td> + <td>8</td> + <td>---</td> + <td>---</td> + <td>---</td> + </tr> + <tr> + <td>Passing data using <a class="external" href="http://www.w3.org/html/wg/drafts/html/master/infrastructure.html#transferable-objectshtml#transferable-objects" title="http://dev.w3.org/html5/spec/common-dom-interfaces.html#transferable-objects">transferable objects</a></td> + <td>---</td> + <td></td> + <td>18</td> + <td>---</td> + <td>---</td> + <td>---</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{ spec("http://dev.w3.org/html5/workers/", "File API Specification: Web Workers", "ED") }}</li> + <li><code><a class="internal" href="/en/DOM/Worker" title="En/DOM/Worker">Worker</a></code> interface</li> + <li><code><a class="internal" href="/en/DOM/SharedWorker" title="En/DOM/SharedWorker">SharedWorker</a></code> interface</li> + <li><a href="/en/DOM/Worker/Functions_available_to_workers" title="En/DOM/Worker/Functions available to workers">Functions available to workers</a></li> + <li><a class="external" href="http://www.html5rocks.com/en/tutorials/workers/basics/#toc-enviornment-subworkers" title="http://www.html5rocks.com/en/tutorials/workers/basics/#toc-enviornment-subworkers">HTML5Rocks - The Basics of Web Workers</a></li> + <li><a class="external" href="http://code.google.com/p/chromium/issues/detail?id=127990" title="Chrome has Problems with many workers">Chrome has problems when using too many worker</a></li> +</ul> diff --git a/files/es/web/api/webgl_api/tutorial/objetos_3d_utilizando_webgl/index.html b/files/es/web/api/webgl_api/tutorial/creating_3d_objects_using_webgl/index.html index 91e6bf3d37..91e6bf3d37 100644 --- a/files/es/web/api/webgl_api/tutorial/objetos_3d_utilizando_webgl/index.html +++ b/files/es/web/api/webgl_api/tutorial/creating_3d_objects_using_webgl/index.html diff --git a/files/es/web/api/webgl_api/tutorial/wtilizando_texturas_en_webgl/index.html b/files/es/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html index 9d2be2d61b..9d2be2d61b 100644 --- a/files/es/web/api/webgl_api/tutorial/wtilizando_texturas_en_webgl/index.html +++ b/files/es/web/api/webgl_api/tutorial/using_textures_in_webgl/index.html diff --git a/files/es/web/api/webrtc_api/session_lifetime/index.html b/files/es/web/api/webrtc_api/session_lifetime/index.html new file mode 100644 index 0000000000..2529f32085 --- /dev/null +++ b/files/es/web/api/webrtc_api/session_lifetime/index.html @@ -0,0 +1,21 @@ +--- +title: WebRTC Introduction +slug: WebRTC/Introduction +translation_of: Web/API/WebRTC_API/Session_lifetime +--- +<div class="note"> + <p>WebRTC te permite establecer una comunicación par-a-par en una aplicación del navegador.</p> +</div> +<h2 id="Estableciendo_la_conexión">Estableciendo la conexión</h2> +<p>La conexión inicial entre pares debe ser establecida a través de un servidor de aplicaciones que proporcione descubrimiento de usuarios, comunicación y traducción de direcciones de red (NAT) con transmisión de datos.</p> +<h3 id="Señalización">Señalización</h3> +<p>Señalización es el mecanismo por el cual los pares se envían mensajes de control entre sí con el propósito de establecer el protocolo, canal, y método de comunicación. Estos no están especifiados en el standar WebRTC. En su lugar, el desarrollador puede elegir cualquier protocolo de mensajería (como SIP o XMPP), y cualquier canal de comunicación bidirecional (como WebSocket o XMLHttpRequest) en conjunción con un servidor con un API de conexión permanente (como el <a href="https://developers.google.com/appengine/docs/python/channel/overview" title="https://developers.google.com/appengine/docs/python/channel/overview">Google Channel API</a>) para AppEngine.</p> +<h2 id="Transmisión">Transmisión</h2> +<h3 id="getUserMedia">getUserMedia</h3> +<p>LocalMediaStream object</p> +<h2 id="Recepción">Recepción</h2> +<p>El soporte para WebRTC en Firefox está escondido detrás de un selector de preferencias. Ve a <a href="/about:config" title="/about:config">about:config</a> y establce 'media.navigator.enabled' a 'true'.</p> +<div class="note"> + <p>Hay algunos archivos de prueba en el repositorio de código para darte una idea de cómo funciona. Ve: <a href="http://hg.mozilla.org/projects/alder/file/tip/dom/media/tests/local_video_test.html">dom/media/tests/local_video_test.html</a>. Por favor, prueba también la<a href="http://webrtc-demo.herokuapp.com/mozdemo">demo de servicio de llamadas</a>, la página de su código, y <a href="https://github.com/anantn/webrtc-demo/">el código de su servidor</a>.</p> +</div> +<p> </p> diff --git a/files/es/web/api/webrtc_api/taking_still_photos/index.html b/files/es/web/api/webrtc_api/taking_still_photos/index.html new file mode 100644 index 0000000000..143b2ee72f --- /dev/null +++ b/files/es/web/api/webrtc_api/taking_still_photos/index.html @@ -0,0 +1,159 @@ +--- +title: Capturar fotografías con la cámara web +slug: WebRTC/Taking_webcam_photos +tags: + - Canvas + - WebRTC + - cámara web + - getusermedia +translation_of: Web/API/WebRTC_API/Taking_still_photos +--- +<h2 id="Introducción_y_demostración">Introducción y demostración</h2> +<p>Este es un tutorial rápido de cómo acceder a la cámara de tu laptop y capturar una foto con ella. Puedes observar el <a href="http://jsfiddle.net/codepo8/agaRe/4/" title="http://jsfiddle.net/codepo8/agaRe/4/">código final en acción en este JSFiddle</a>. También existe una versión más avanzada en JavaScript para cargar fotos a <strong>imgur</strong> disponible como <a href="https://github.com/codepo8/interaction-cam/" title="https://github.com/codepo8/interaction-cam/">código en GitHub</a> o <a href="http://codepo8.github.com/interaction-cam/" title="http://codepo8.github.com/interaction-cam/">como demo</a>.</p> +<h2 id="El_formato_HTML">El formato HTML</h2> +<p>Lo primero que necesitas para acceder a la cámara web utilizando WebRTC es un elemento {{HTMLElement("video")}} y un elemento {{HTMLElement("canvas")}} en la página. El elemento de video recibe la secuencia desde WebRTC y el elemento canvas es utilizado para agarrar la imagen desde el video. También añadimos una imagen de relleno que luego será reemplazada con la toma capturada por la cámara web.</p> +<pre class="brush:html;"><video id="video"></video> +<button id="startbutton">Take photo</button> +<canvas id="canvas"></canvas> +<img src="http://placekitten.com/g/320/261" id="photo" alt="photo"> +</pre> +<h2 id="El_script_completo">El script completo</h2> +<p>Aquí se muestra completamente el código JavaScript. Más abajo, explicaremos gradualmente cada sección con más detalle.</p> +<pre class="brush:js;">(function() { + + var streaming = false, + video = document.querySelector('#video'), + canvas = document.querySelector('#canvas'), + photo = document.querySelector('#photo'), + startbutton = document.querySelector('#startbutton'), + width = 320, + height = 0; + + navigator.getMedia = ( navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia); + + navigator.getMedia( + { + video: true, + audio: false + }, + function(stream) { + if (navigator.mozGetUserMedia) { + video.mozSrcObject = stream; + } else { + var vendorURL = window.URL || window.webkitURL; + video.src = vendorURL.createObjectURL(stream); + } + video.play(); + }, + function(err) { + console.log("An error occured! " + err); + } + ); + + video.addEventListener('canplay', function(ev){ + if (!streaming) { + height = video.videoHeight / (video.videoWidth/width); + video.setAttribute('width', width); + video.setAttribute('height', height); + canvas.setAttribute('width', width); + canvas.setAttribute('height', height); + streaming = true; + } + }, false); + + function takepicture() { + canvas.width = width; + canvas.height = height; + canvas.getContext('2d').drawImage(video, 0, 0, width, height); + var data = canvas.toDataURL('image/png'); + photo.setAttribute('src', data); + } + + startbutton.addEventListener('click', function(ev){ + takepicture(); + ev.preventDefault(); + }, false); + +})();</pre> +<h2 id="Explicando_paso_a_paso">Explicando paso a paso</h2> +<p>Entonces, ¿Qué es lo que sucede aquí? Lo analizaremos paso por paso.</p> +<h3 id="Función_Anónima">Función Anónima</h3> +<pre class="brush:js;">(function() { + + var streaming = false, + video = document.querySelector('#video'), + canvas = document.querySelector('#canvas'), + photo = document.querySelector('#photo'), + startbutton = document.querySelector('#startbutton'), + width = 320, + height = 0;</pre> +<p>Empezamos por encerrar el script entero en una función anónima para evitar las variables globales. Tomamos los elementos HTML que necesitamos y definimos el ancho (width) del video a 320 y la altura (height) a 0, ya que calcularemos la altura apropiada posteriormente.</p> +<div class="warning"> + <p>En estos momentos existe una diferencia entre los tamaños de video proporcionados por getUserMedia. Firefox Nightly utiliza una resolución de 352x288 y Opera y Chrome utiliza una resolución de 640x400. Esto cambiará en el futuro, pero cambiando el tamaño con la proporción que usaremos más abajo, nos aseguraremos de no obtener sorpresas desagradables.</p> +</div> +<h3 id="Obtener_el_video">Obtener el video</h3> +<p>Ahora necesitamos obtener el video desde la cámara web. Actualmente esto está predeterminado para los diferentes navegadores, así que necesitamos comprobar cuál es compatible:</p> +<pre class="brush:js;"> navigator.getMedia = ( navigator.getUserMedia || + navigator.webkitGetUserMedia || + navigator.mozGetUserMedia || + navigator.msGetUserMedia);</pre> +<p>Le solicitamos al navegador que nos dé un video sin audio y obtenemos una secuencia (stream) en la función de retrollamada:</p> +<pre class="brush:js;"> navigator.getMedia( + { + video: true, + audio: false + }, + function(stream) { + if (navigator.mozGetUserMedia) { + video.mozSrcObject = stream; + } else { + var vendorURL = window.URL || window.webkitURL; + video.src = vendorURL.createObjectURL(stream); + } + video.play(); + }, + function(err) { + console.log("An error occured! " + err); + } + );</pre> +<p>En estos momentos Firefox Nightly necesita que tu configures la propiedad de <code>mozSrcObject</code> del elemento del video con el fin de reproducirlo; para otros navegadores, configura el atributo <code>src</code>. Mientras que Firefox puede utilizar la secuencia de video directamente, Webkit y Opera necesitan crear un objeto URL desde ella. Todo esto será estandarizado en un futuro cercano.</p> +<h3 id="Redefinir_el_tamaño_del_video">Redefinir el tamaño del video</h3> +<p>Luego necesitamos configurar el tamaño del video a las dimensiones deseadas.</p> +<pre class="brush:js;"> video.addEventListener('canplay', function(ev){ + if (!streaming) { + height = video.videoHeight / (video.videoWidth/width); + video.setAttribute('width', width); + video.setAttribute('height', height); + canvas.setAttribute('width', width); + canvas.setAttribute('height', height); + streaming = true; + } + }, false);</pre> +<p>Nos subscribimos al evento <code>canplay </code>del video y leemos sus dimensiones utilizando <code>videoHeight</code> y <code>videoWidth</code>. Estas no están disponible realmente hasta que el evento sea iniciado. Establecemos <code>streaming</code> a verdadero (true) para que compruebe esto solo una vez, mientras que el evento <code>canplay</code> siga en actividad.</p> +<p>Esto es todo lo que se necesita para que inicie el video.</p> +<h3 id="Capturar_una_imagen">Capturar una imagen</h3> +<p>Ahora necesitamos capturar una imagen utilizando un lienzo (canvas). Asignamos un manejador de eventos al botón de inicio para llamar a la función de <code>takepicture</code>.</p> +<pre class="brush:js;"> startbutton.addEventListener('click', function(ev){ + takepicture(); + ev.preventDefault(); + }, false);</pre> +<p>En esta función, reestablecemos el tamaño del lienzo (canvas) a las dimensiones del video, el cual lo sustituye y tenemos un marco del video, el cual se copia al canvas. Luego necesitamos convertir los datos del canvas en datos tipo URL con un encabezado PNG, y establecer el src de la fotografía a este mismo url.</p> +<pre class="brush:js;"> function takepicture() { + canvas.width = width; + canvas.height = height; + canvas.getContext('2d').drawImage(video, 0, 0, width, height); + var data = canvas.toDataURL('image/png'); + photo.setAttribute('src', data); + } + +})();</pre> +<p>Eso es todo lo que se necesita para mostrar la secuencia de la cámara web y capturar una imagen fija de ella, a través de Chrome, Opera y Firefox.</p> +<h2 id="Compatibilidad">Compatibilidad</h2> +<p>Actualmente utilizar WebRTC para acceder a la cámara es compatible en Chrome, Opera y Firefox Nightly 18. Para habilitar WebRTC en Firefox Nightly requiere que establezcas un indicador en la configuración:</p> +<ul> + <li>Teclea "about:config" en la barra de direcciones y afirma que quieres realizar algunos cambios.</li> + <li>Encuentra la entrada "media.navigator.enabled" y establécelo a verdadero (true).</li> +</ul> diff --git a/files/es/web/api/websockets_api/escribiendo_servidor_websocket/index.html b/files/es/web/api/websockets_api/writing_websocket_server/index.html index 333e8e8830..333e8e8830 100644 --- a/files/es/web/api/websockets_api/escribiendo_servidor_websocket/index.html +++ b/files/es/web/api/websockets_api/writing_websocket_server/index.html diff --git a/files/es/web/api/websockets_api/escribiendo_servidores_con_websocket/index.html b/files/es/web/api/websockets_api/writing_websocket_servers/index.html index 1261f75bec..1261f75bec 100644 --- a/files/es/web/api/websockets_api/escribiendo_servidores_con_websocket/index.html +++ b/files/es/web/api/websockets_api/writing_websocket_servers/index.html diff --git a/files/es/web/api/window/beforeunload_event/index.html b/files/es/web/api/window/beforeunload_event/index.html new file mode 100644 index 0000000000..98fb747ae9 --- /dev/null +++ b/files/es/web/api/window/beforeunload_event/index.html @@ -0,0 +1,215 @@ +--- +title: beforeunload +slug: Web/Events/beforeunload +translation_of: Web/API/Window/beforeunload_event +--- +<div>El evento <strong>beforeunload</strong> es disparado cuando la ventana, el documento y sus recursos estan a punto de ser descargados. El documento todavia es visible y el evento todavia es cancelable en este punto.</div> + +<div> </div> + +<p>Si es asignado un string a la propiedad del objeto Evento returnValue, una caja de dialogo aparece, preguntando al usuario que confirme que dejara la pagina(mirar el ejemplo de abajo). Algunos navegadores muestran el string devuelto en una caja de dialogos, otros muestran un mensaje fijo. Si no se provee ningun valor, el evento procede silenciosamente.</p> + +<div class="note"> +<p><strong>Nota:</strong>Para combatir pop-ups indeseados, los navegadores pueden no mostrar mensajes creados en manejadores del evento beforeunload a menos que se haya interactuado con la pagina, o incluso sin que se haya interactuado en nada con esta.</p> +</div> + +<table class="properties"> + <tbody> + <tr> + <td>Burbujas</td> + <td>No</td> + </tr> + <tr> + <td>Cancelable</td> + <td>Si</td> + </tr> + <tr> + <td>Objetos de destino</td> + <td>defaultView</td> + </tr> + <tr> + <td>Interfaz</td> + <td>{{domxref("Event")}}</td> + </tr> + </tbody> +</table> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Propiedad</th> + <th scope="col">Tipo</th> + <th scope="col">Descripcion</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readOnlyInline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>El evento objetivo(el objetivo superior en el arbol del DOM).</td> + </tr> + <tr> + <td><code>type</code> {{readOnlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>El tipo de evento.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readOnlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>El evento normalmente burbujea?</td> + </tr> + <tr> + <td><code>cancelable</code> {{readOnlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Es posible cancelar el evento?</td> + </tr> + <tr> + <td><code>returnValue</code></td> + <td>{{domxref("DOMString")}}</td> + <td>El valor actual devuelto por el evento (el mensaje que se le mostrara al usuario).</td> + </tr> + </tbody> +</table> + +<h2 id="Ejemplos">Ejemplos</h2> + +<pre class="brush:js;">window.addEventListener("beforeunload", function (event) { + event.returnValue = "\o/"; +}); + +// es equivalente a +window.addEventListener("beforeunload", function (event) { + event.preventDefault(); +});</pre> + +<p>Navegadores basados en WebKit no siguen las especificaciones para la caja de dialogos. Un ejemplo que funcione con distintos navegadores seria similar al siguiente:</p> + +<pre class="brush: js">window.addEventListener("beforeunload", function (e) { + var confirmationMessage = "\o/"; + + e.returnValue = confirmationMessage; // Gecko, Trident, Chrome 34+ + return confirmationMessage; // Gecko, WebKit, Chrome <34 +});</pre> + +<h2 id="Notas">Notas</h2> + +<p>A partir del 25 de Mayo del 2011, la especificion HTML5 establece que llamadas a los metodos {{domxref("window.alert()")}}, {{domxref("window.confirm()")}}, y {{domxref("window.prompt()")}}pueden ser ignoradas durante este evento.Mire las <a href="http://www.w3.org/TR/html5/webappapis.html#user-prompts">especificaciones de HTML5</a> para mas detalles.</p> + +<p>Varios navegadores ignoran el resultado del evento y no le preguntan al usuario por confirmacion en absoluto. El documento siempre se descargara automaticamente. Firefox tiene un switch llamado dom.disable_beforeunload en <a>about:config</a> para habilitar este comportamiento.</p> + +<p>Usando este manejador de evento tu pagina previene que Firefox cambie el cache de la pagina a uno en memoria bfcache. Mire <a href="en/Using_Firefox_1.5_caching">Usando el almacenamiento en cache Firefox 1.5</a> para detalles.</p> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Especificacion</th> + <th scope="col">Estado</th> + <th scope="col">Comentario</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{SpecName("HTML WHATWG", "indices.html#event-beforeunload", "beforeunload")}}</td> + <td>{{Spec2("HTML WHATWG")}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName("HTML5 W3C", "browsers.html#unloading-documents", "beforeunload")}}</td> + <td>{{Spec2("HTML5 W3C")}}</td> + <td>Definicion inicial</td> + </tr> + </tbody> +</table> + +<h2 id="Compatibilidad_con_navegadores">Compatibilidad con navegadores</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Caracteristica</th> + <th>Chrome</th> + <th>Edge</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari (WebKit)</th> + </tr> + <tr> + <td>Soporte basico</td> + <td>{{CompatChrome(1.0)}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>1</td> + <td>4</td> + <td>12</td> + <td>3</td> + </tr> + <tr> + <td>Texto personalizado soporte removido</td> + <td>{{CompatChrome(51.0)}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatGeckoMobile("44.0")}}</td> + <td> </td> + <td>38</td> + <td><a href="https://developer.apple.com/library/mac/releasenotes/General/WhatsNewInSafari/Articles/Safari_9_1.html">9.1</a></td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Caracteristica</th> + <th>Android</th> + <th>Android Webview</th> + <th>Edge</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Phone</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + <th>Chrome for Android</th> + </tr> + <tr> + <td>Soporte basico</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>(no) <a href="https://bugs.webkit.org/show_bug.cgi?id=19324">defect</a></td> + <td>{{CompatVersionUnknown}}</td> + </tr> + <tr> + <td>Texto personalizado soporte removido</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatChrome(51.0)}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatGeckoMobile("44.0")}}</td> + <td> </td> + <td> </td> + <td> </td> + <td>{{CompatChrome(51.0)}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="Mire_tambien">Mire tambien</h2> + +<ul> + <li>{{Event("DOMContentLoaded")}}</li> + <li>{{Event("readystatechange")}}</li> + <li>{{Event("load")}}</li> + <li>{{Event("unload")}}</li> + <li><a href="http://www.whatwg.org/specs/web-apps/current-work/#prompt-to-unload-a-document" title="http://www.whatwg.org/specs/web-apps/current-work/#prompt-to-unload-a-document">Unloading Documents — Confirmacion para descargar un documento</a></li> + <li><a href="https://developers.google.com/web/updates/2016/04/chrome-51-deprecations?hl=en#remove_custom_messages_in_onbeforeload_dialogs">Remover mensajes personalizados en dialogos onbeforeload despues de Chrome 51</a> </li> +</ul> diff --git a/files/es/web/api/window/domcontentloaded_event/index.html b/files/es/web/api/window/domcontentloaded_event/index.html new file mode 100644 index 0000000000..ffbf3accbc --- /dev/null +++ b/files/es/web/api/window/domcontentloaded_event/index.html @@ -0,0 +1,148 @@ +--- +title: DOMContentLoaded +slug: Web/Events/DOMContentLoaded +translation_of: Web/API/Window/DOMContentLoaded_event +--- +<p>El evento <code>DOMContentLoaded</code> es disparado cuando el documento HTML ha sido completamente cargado y parseado, sin esperar hojas de estilo, images y subframes para finalizar la carga. Un evento muy diferente - <a href="/en-US/docs/Mozilla_event_reference/load"><code>load</code></a> - debería ser usado solo para detectar una carga completa de la página. Es un error increíblemente popular usar <a href="/en-US/docs/Mozilla_event_reference/load"><code>load</code></a> cuando <code>DOMContentLoaded</code> sería mucho más apropiado, así que úsalo con cuidado.</p> + +<p>JavaScript síncrono pausa el parseo del DOM.</p> + +<p>También hay mucho propósito general y bibliotecas autónomas que ofrecen métodos de navegador cruzado para detectar que el DOM está preparado.</p> + +<h2 id="Speeding_up">Speeding up</h2> + +<p>If you want DOM to get parsed as fast as possible after the user had requested the page, some things you could do is turn your <a href="https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests">JavaScript asynchronous</a> and to <a href="https://developers.google.com/speed/docs/insights/OptimizeCSSDelivery">optimize loading of stylesheets</a> which if used as usual, slow down page load due to being loaded in parallel, "stealing" traffic from the main html document.</p> + +<h2 id="General_info">General info</h2> + +<dl> + <dt style="width: 120px; text-align: right; float: left;">Specification</dt> + <dd style="margin: 0px 0px 0px 120px;"><a class="external" href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#the-end">HTML5</a></dd> + <dt style="width: 120px; text-align: right; float: left;">Interface</dt> + <dd style="margin: 0px 0px 0px 120px;">Event</dd> + <dt style="width: 120px; text-align: right; float: left;">Bubbles</dt> + <dd style="margin: 0px 0px 0px 120px;">Yes</dd> + <dt style="width: 120px; text-align: right; float: left;">Cancelable</dt> + <dd style="margin: 0px 0px 0px 120px;">Yes (although specified as a simple event that isn't cancelable)</dd> + <dt style="width: 120px; text-align: right; float: left;">Target</dt> + <dd style="margin: 0px 0px 0px 120px;">Document</dd> + <dt style="width: 120px; text-align: right; float: left;">Default Action</dt> + <dd style="margin: 0px 0px 0px 120px;">None.</dd> +</dl> + +<h2 id="Properties">Properties</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col">Type</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyInline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>The event target (the topmost target in the DOM tree).</td> + </tr> + <tr> + <td><code>type</code> {{readonlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The type of event.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Whether the event normally bubbles or not.</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Whether the event is cancellable or not.</td> + </tr> + </tbody> +</table> + +<h2 id="Example">Example</h2> + +<pre class="brush: html"><script> + document.addEventListener("DOMContentLoaded", function(event) { + console.log("DOM fully loaded and parsed"); + }); +</script> +</pre> + +<pre class="brush: html"><script> + document.addEventListener("DOMContentLoaded", function(event) { + console.log("DOM fully loaded and parsed"); + }); + +for(var i=0; i<1000000000; i++) +{} // this synchronous script is going to delay parsing of the DOM. So the DOMContentLoaded event is going to launch later. +</script> +</pre> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + +<p>{{CompatibilityTable}}</p> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>1.0<sup>[1]</sup></td> + <td>{{CompatGeckoDesktop("1")}}<sup>[1]</sup></td> + <td>9.0<sup>[2]</sup></td> + <td>9.0</td> + <td>3.1<sup>[1]</sup></td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}<sup>[1]</sup></td> + <td>{{CompatGeckoMobile("1")}}<sup>[1]</sup></td> + <td>{{CompatUnknown}}<sup>[2]</sup></td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}<sup>[1]</sup></td> + </tr> + </tbody> +</table> +</div> + +<p>[1] Bubbling for this event is supported by at least Gecko 1.9.2, Chrome 6, and Safari 4.</p> + +<p>[2] Internet Explorer 8 supports the <code>readystatechange</code> event, which can be used to detect when the DOM is ready. In earlier versions of Internet Explorer, this state can be detected by repeatedly trying to execute <code>document.documentElement.doScroll("left");</code>, as this snippet will throw an error until the DOM is ready.</p> + +<h2 id="Related_Events">Related Events</h2> + +<ul> + <li>{{event("DOMContentLoaded")}}</li> + <li>{{event("readystatechange")}}</li> + <li>{{event("load")}}</li> + <li>{{event("beforeunload")}}</li> + <li>{{event("unload")}}</li> +</ul> diff --git a/files/es/web/api/window/load_event/index.html b/files/es/web/api/window/load_event/index.html new file mode 100644 index 0000000000..f38e214839 --- /dev/null +++ b/files/es/web/api/window/load_event/index.html @@ -0,0 +1,125 @@ +--- +title: load +slug: Web/Events/load +tags: + - Evento +translation_of: Web/API/Window/load_event +--- +<p>El evento <code>load</code> se dispara cuando un recurso y sus recursos dependientes han terminado de cargar.</p> + +<p> </p> + +<h2 id="Ejemplos">Ejemplos</h2> + +<h3 class="brush: html" id="Window">Window</h3> + +<pre class="brush: html"><script> + window.addEventListener("load", function(event) { + console.log("'Todos los recursos terminaron de cargar!"); + }); +</script></pre> + +<h3 id="Elemento_script">Elemento <code>script</code></h3> + +<pre class="brush: html"><script> + var script = document.createElement("script"); + script.addEventListener("load", function(event) { + console.log("Script terminó de cargarse y ejecutarse"); + }); + script.src = "http://example.com/example.js"; + script.async = true; + document.getElementsByTagName("script")[0].parentNode.appendChild(script); +</script></pre> + +<h2 id="Información_general">Información general</h2> + +<dl> + <dt style="float: left; text-align: right; width: 120px;">Especificación</dt> + <dd style="margin: 0 0 0 120px;"><a class="external" href="http://www.w3.org/TR/DOM-Level-3-Events/#event-type-load">DOM L3</a></dd> + <dt style="float: left; text-align: right; width: 120px;">Interfaz</dt> + <dd style="margin: 0 0 0 120px;">UIEvent</dd> + <dt style="float: left; text-align: right; width: 120px;">Propagación</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Cancelable</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Objetivo</dt> + <dd style="margin: 0 0 0 120px;">Window,Document,Element</dd> + <dt style="float: left; text-align: right; width: 120px;">Por defecto Acción</dt> + <dd style="margin: 0 0 0 120px;">None.</dd> +</dl> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Propiedad</th> + <th scope="col">Tipo</th> + <th scope="col">Descripción</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyInline}}</td> + <td><code>{{domxref("EventTarget")}}</code></td> + <td>El objetivo del evento (el objetivo superior en el árbol DOM).</td> + </tr> + <tr> + <td><code>type</code> {{readonlyInline}}</td> + <td><code>{{domxref("DOMString")}}</code></td> + <td>El tipo de evento.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyInline}}</td> + <td><code>{{domxref("Boolean")}}</code></td> + <td>Si el elemento normalmente se propaga (bubbles) o no.</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyInline}}</td> + <td><code>{{domxref("Boolean")}}</code></td> + <td>Si el evento es cancelable o no.</td> + </tr> + <tr> + <td><code>view</code> {{readonlyInline}}</td> + <td><code>{{domxref("WindowProxy")}}</code></td> + <td><code>{{domxref("Document.defaultView", "document.defaultView")}}</code> (<code>window</code> del documento)</td> + </tr> + <tr> + <td><code>detail</code> {{readonlyInline}}</td> + <td><code>long</code> (<code>float</code>)</td> + <td>0.</td> + </tr> + </tbody> +</table> + +<h2 id="Especificaciones">Especificaciones</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Especificación</th> + <th scope="col">Estado</th> + <th scope="col">Comentario</th> + </tr> + <tr> + <td>{{SpecName('UI Events', '#event-type-load', 'load')}}</td> + <td>{{Spec2('UI Events')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('HTML WHATWG', 'parsing.html#the-end:event-load', 'Load event')}}</td> + <td>{{Spec2('HTML WHATWG')}}</td> + <td>Esto enlaza con la sección en los pasos que se llevan a cabo al final de cargar un documento. Los eventos 'load' también se disparan a muchos elementos. Y tenga en cuenta que hay muchos lugares en la especificación que hacen referencia a cosas que pueden "<a href="https://html.spec.whatwg.org/multipage/parsing.html#delay-the-load-event">retrasar el evento de carga</a>".</td> + </tr> + </tbody> +</table> + +<h2 id="Eventos_relacionados">Eventos relacionados</h2> + +<ul> + <li>{{event("DOMContentLoaded")}}</li> + <li>{{event("readystatechange")}}</li> + <li>{{event("load")}}</li> + <li>{{event("beforeunload")}}</li> + <li>{{event("unload")}}</li> +</ul> diff --git a/files/es/web/api/window/url/index.html b/files/es/web/api/window/url/index.html deleted file mode 100644 index 6ca15914a4..0000000000 --- a/files/es/web/api/window/url/index.html +++ /dev/null @@ -1,102 +0,0 @@ ---- -title: Window.URL -slug: Web/API/Window/URL -tags: - - API - - DOM - - Propiedad - - Referencia - - Referência DOM - - WebAPI -translation_of: Web/API/URL -translation_of_original: Web/API/Window/URL ---- -<p>{{ApiRef("Window")}}{{SeeCompatTable}}</p> - -<p>La propiedad <strong><code>Window.URL</code></strong> devuelve un objeto que proporciona métodos estáticos usados para crear y gestionar objetos de URLs. Además puede ser llamado como un constructor para construir objetos {{domxref("URL")}}.</p> - -<p>{{AvailableInWorkers}}</p> - -<h2 id="Sintaxis">Sintaxis</h2> - -<p>Llamando a un método estático:</p> - -<pre class="syntaxbox"><code><var>img</var>.src = URL.{{domxref("URL.createObjectURL", "createObjectURL")}}(<var>blob</var>);</code></pre> - -<p>Construyendo un nuevo objeto:</p> - -<pre class="syntaxbox"><code>var <var>url</var> = new {{domxref("URL.URL", "URL")}}("../cats/", "https://www.example.com/dogs/");</code></pre> - -<h2 id="Especificación">Especificación</h2> - -<table class="standard-table"> - <tbody> - <tr> - <th scope="col">Especificación</th> - <th scope="col">Estado</th> - <th scope="col">Comentario</th> - </tr> - <tr> - <td>{{SpecName('URL', '#dom-url', 'URL')}}</td> - <td>{{Spec2('URL')}}</td> - <td>Definición inicial</td> - </tr> - </tbody> -</table> - -<h2 id="Compatibilidad_con_navegadores">Compatibilidad con navegadores</h2> - -<p>{{CompatibilityTable}}</p> - -<div id="compat-desktop"> -<table class="compat-table"> - <tbody> - <tr> - <th>Característica</th> - <th>Chrome</th> - <th>Firefox (Gecko)</th> - <th>Internet Explorer</th> - <th>Opera</th> - <th>Safari</th> - </tr> - <tr> - <td>Soporte básico</td> - <td>8.0<sup>[2]</sup></td> - <td>{{CompatGeckoDesktop("2.0")}}<sup>[1]</sup><br> - {{CompatGeckoDesktop("19.0")}}</td> - <td>10.0</td> - <td>15.0<sup>[2]</sup></td> - <td>6.0<sup>[2]</sup><br> - 7.0</td> - </tr> - </tbody> -</table> -</div> - -<div id="compat-mobile"> -<table class="compat-table"> - <tbody> - <tr> - <th>Característica</th> - <th>Android</th> - <th>Firefox Mobile (Gecko)</th> - <th>IE Mobile</th> - <th>Opera Mobile</th> - <th>Safari Mobile</th> - </tr> - <tr> - <td>Soporte básico</td> - <td>{{CompatVersionUnknown}}<sup>[2]</sup></td> - <td>{{CompatGeckoMobile("14.0")}}<sup>[1]</sup><br> - {{CompatGeckoMobile("19.0")}}</td> - <td>{{CompatVersionUnknown}}</td> - <td>15.0<sup>[2]</sup></td> - <td>6.0<sup>[2]</sup></td> - </tr> - </tbody> -</table> -</div> - -<p>[1] Desde Gecko 2 (Firefox 4) hasta Gecko 18 incluidos, Gecko devuelve un objeto con el tipo interno no estandar <code>nsIDOMMozURLProperty</code>. En la práctica, esto no hace ninguna diferencia.</p> - -<p>[2] Implementado bajo el nombre no estandar <code>webkitURL</code>.</p> diff --git a/files/es/web/api/windowbase64/base64_codificando_y_decodificando/index.html b/files/es/web/api/windowbase64/base64_codificando_y_decodificando/index.html deleted file mode 100644 index c8747777cd..0000000000 --- a/files/es/web/api/windowbase64/base64_codificando_y_decodificando/index.html +++ /dev/null @@ -1,345 +0,0 @@ ---- -title: Base64 codificando y decodificando -slug: Web/API/WindowBase64/Base64_codificando_y_decodificando -translation_of: Glossary/Base64 ---- -<p><strong>Base64</strong> es un grupo de esquemas de <a href="https://es.wikipedia.org/wiki/Codificaci%C3%B3n_de_binario_a_texto">codificación de binario a texto</a> que representa los datos binarios mediante una cadena ASCII, traduciéndolos en una representación radix-64. El término <em>Base64</em> se origina de un <a href="https://es.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions#Content-Transfer-Encoding">sistema de codificación de transmisión de contenido MIME</a> específico.</p> - -<p>Los esquemas de codificación Base64 son comúnmente usados cuando se necesita codificar datos binarios para que sean almacenados y transferidos sobre un medio diseñado para tratar con datos textuales. Esto es para asegurar que los datos se mantienen intactos y sin modificaciones durante la transmisión. Base64 es comúnmente usado en muchas aplicaciones, incluyendo la escritura de emails vía <a href="https://es.wikipedia.org/wiki/Multipurpose_Internet_Mail_Extensions">MIME</a> y el almacenamiento de datos complejos en <a href="/es/docs/XML">XML</a>.</p> - -<p>En JavaScript hay dos funciones para decodificar y codificar cadenas base64, respectivamente:</p> - -<ul> - <li>{{domxref("WindowBase64.atob","atob()")}}</li> - <li>{{domxref("WindowBase64.btoa","btoa()")}}</li> -</ul> - -<p>La función <code>atob()</code> decodifica una cadena de datos que ha sido codificada usando la codificación en base 64. Por el contrario, la función <code>btoa()</code> crea una cadena ASCII codificada en base 64 a partir de una "cadena" de datos binarios.</p> - -<p>Ambas funciones trabajan sobre cadenas de texto. Si desea trabajar con <a href="/es/docs/Web/JavaScript/Referencia/Objetos_globales/ArrayBuffer">ArrayBuffers</a>, lea <a href="/es/docs/Web/API/WindowBase64/Base64_codificando_y_decodificando$edit#Solution_.232_.E2.80.93_rewriting_atob%28%29_and_btoa%28%29_using_TypedArrays_and_UTF-8">este párrafo</a>.</p> - - - -<table class="topicpage-table"> - <tbody> - <tr> - <td> - <h2 class="Documentation" id="Documentation" name="Documentation">Documentación</h2> - - <dl> - <dt><a href="https://developer.mozilla.org/en-US/docs/data_URIs" title="https://developer.mozilla.org/en-US/docs/data_URIs"><code>data</code> URIs</a></dt> - <dd><small><code>Los URIs de</code> datos, definidos por <a class="external" href="http://tools.ietf.org/html/rfc2397" title="http://tools.ietf.org/html/rfc2397">RFC 2397</a>, permiten a los creadores de contenido introducir pequeños ficheros en línea en documentos.</small></dd> - <dt><a href="https://es.wikipedia.org/wiki/Base64" title="https://en.wikipedia.org/wiki/Base64">Base64</a></dt> - <dd><small>Artículo en Wikipedia sobre el sistema de codificación Base64.</small></dd> - <dt>{{domxref("WindowBase64.atob","atob()")}}</dt> - <dd><small>Decodifica una cadena de datos que ha sido codificada utilizando base-64.</small></dd> - <dt>{{domxref("WindowBase64.btoa","btoa()")}}</dt> - <dd><small>Crea una cadena ASCII codificada en base 64 a partir de una "cadena" de datos binarios.</small></dd> - <dt><a href="#The_.22Unicode_Problem.22">The "Unicode Problem"</a></dt> - <dd><small>En la mayoría de navegadores, llamar a <code>btoa()</code> con una cadena Unicode causará una excepción <code>Character Out Of Range</code>. Este párrafo muestra algunas soluciones.</small></dd> - <dt><a href="/en-US/docs/URIScheme" title="/en-US/docs/URIScheme">URIScheme</a></dt> - <dd><small>Lista de esquemas URI soportados por Mozilla.</small></dd> - <dt><a href="/en-US/docs/Web/JavaScript/Typed_arrays/StringView" title="/en-US/docs/Web/JavaScript/Typed_arrays/StringView"><code>StringView</code></a></dt> - <dd>En este artículo está publicada una librería hecha por nosotros con los siguientes objetivos:</dd> - <dd> - <ul> - <li>crear una interfaz al estilo de <a class="external" href="http://en.wikipedia.org/wiki/C_%28programming_language%29" title="http://en.wikipedia.org/wiki/C_%28programming_language%29">C</a> para cadenas (es decir, arrays de códigos de caracteres —<a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView" title="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView"> <code>ArrayBufferView</code></a> en JavaScript) basada en la interfaz <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer" title="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>ArrayBuffer</code></a> de JavaScript.</li> - <li>crear una colección de métodos para los que los objetos parecidos a cadenas (de ahora en adelante, <code>stringView</code>s) funcionen estrictamente en arrays de números más que en cadenas JavaScript inmutables.</li> - <li>trabajar con otras codificaciones Unicode diferentes de las <a href="/en-US/docs/Web/API/DOMString" title="/en-US/docs/Web/API/DOMString"><code>DOMString</code></a>s UTF-16 por defecto de JavaScript.</li> - </ul> - </dd> - </dl> - - <p><span class="alllinks"><a href="/en-US/docs/tag/Base64">Ver todo...</a></span></p> - </td> - <td> - <h2 class="Tools" id="Tools" name="Tools">Herramientas</h2> - - <ul> - <li><a href="#Solution_.232_.E2.80.93_rewriting_atob()_and_btoa()_using_TypedArrays_and_UTF-8">Reescribir atob() y btoa() usando TypedArrays y UTF-8</a></li> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/StringView" title="/en-US/docs/Web/JavaScript/Typed_arrays/StringView"><code>StringView</code>, una representación parecida a C de cadenas basadas en arrays tipados</a><span class="alllinks"><a href="/en-US/docs/tag/Base64">View All...</a></span></li> - </ul> - - <h2 class="Related_Topics" id="Related_Topics" name="Related_Topics">Temas relacionados</h2> - - <ul> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer"><code>ArrayBuffer</code></a></li> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays">Vectores o arrays tipados</a></li> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView">ArrayBufferView</a></li> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array"><code>Uint8Array</code></a></li> - <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView" title="/en-US/docs/Web/JavaScript/Typed_arrays/StringView"><code>StringView</code></a><a href="/en-US/docs/Web/JavaScript/Typed_arrays/StringView" title="/en-US/docs/Web/JavaScript/Typed_arrays/StringView">, una representación parecida a C de cadenas basadas en arrays tipados</a></li> - <li><a href="/en-US/docs/Web/API/DOMString" title="/en-US/docs/Web/API/DOMString"><code>DOMString</code></a></li> - <li><a href="/en-US/docs/URI" title="/en-US/docs/URI"><code>URI</code></a></li> - <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI"><code>encodeURI()</code></a></li> - </ul> - </td> - </tr> - </tbody> -</table> - - - -<h2 id="El_Problema_Unicode">El "Problema Unicode"</h2> - -<p>Como las <a href="/en-US/docs/Web/API/DOMString" title="/en-US/docs/Web/API/DOMString"><code>DOMString</code></a>s son cadenas codificadas en 16 bits, en la mayoría de navegadores llamar a <code>window.btoa</code> sobre una cadena Unicode resultará en una excepción <code>Character Out Of Range </code>si un carácter excede el rango de los caracteres ASCII de 8 bits. Hay dos posibles métodos para resolver este problema:</p> - -<ul> - <li>el primero es escapar la cadena completa y, entonces, codificarla;</li> - <li>el segundo es convertir la <a href="/en-US/docs/Web/API/DOMString" title="/en-US/docs/Web/API/DOMString"><code>DOMString</code></a> UTF-16 en un array de caracteres UTF-8 y codificarla.</li> -</ul> - -<p>Aquí están los dos posibles métodos:</p> - -<h3 id="Solución_1_–_escapar_la_cadena_antes_de_codificarla">Solución #1 – escapar la cadena antes de codificarla</h3> - -<pre class="brush:js notranslate">function utf8_to_b64( str ) { - return window.btoa(unescape(encodeURIComponent( str ))); -} - -function b64_to_utf8( str ) { - return decodeURIComponent(escape(window.atob( str ))); -} - -// Uso: -utf8_to_b64('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU=" -b64_to_utf8('4pyTIMOgIGxhIG1vZGU='); // "✓ à la mode"</pre> - -<p>Esta solución ha sido propuesta por <a href="http://ecmanaut.blogspot.com/2006/07/encoding-decoding-utf8-in-javascript.html">Johan Sundström</a>.</p> - -<p>Otra posible solución sin utilizar las funciones 'unscape' y 'escape', ya obsoletas.</p> - -<pre class="brush:js notranslate">function b64EncodeUnicode(str) { - return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { - return String.fromCharCode('0x' + p1); - })); -} - b64EncodeUnicode('✓ à la mode'); // "4pyTIMOgIGxhIG1vZGU=" -</pre> - -<h3 id="Solución_2_–_reescribir_atob_y_btoa_usando_TypedArrays_y_UTF-8">Solución #2 – reescribir <code>atob()</code> y <code>btoa()</code> usando <code>TypedArray</code>s y UTF-8</h3> - -<div class="note"><strong>Nota:</strong> El siguiente código también es útil para obtener un <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer">ArrayBuffer</a> a partir de una cadena <em>Base64</em> y/o viceversa (<a href="#Appendix.3A_Decode_a_Base64_string_to_Uint8Array_or_ArrayBuffer" title="#Appendix.3A_Decode_a_Base64_string_to_Uint8Array_or_ArrayBuffer">véase abajo</a>). <strong>Para una librería completa de arrays tipados, vea <a href="/en-US/docs/Web/JavaScript/Typed_arrays/StringView" title="/en-US/docs/Web/JavaScript/Typed_arrays/StringView">este artículo</a></strong>.</div> - -<pre class="brush: js notranslate">"use strict"; - -/*\ -|*| -|*| Base64 / binary data / UTF-8 strings utilities -|*| -|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding -|*| -\*/ - -/* Decodificación de cadena base64 en array de bytes */ - -function b64ToUint6 (nChr) { - - return nChr > 64 && nChr < 91 ? - nChr - 65 - : nChr > 96 && nChr < 123 ? - nChr - 71 - : nChr > 47 && nChr < 58 ? - nChr + 4 - : nChr === 43 ? - 62 - : nChr === 47 ? - 63 - : - 0; - -} - -function base64DecToArr (sBase64, nBlocksSize) { - - var - sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length, - nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen); - - for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) { - nMod4 = nInIdx & 3; - nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4; - if (nMod4 === 3 || nInLen - nInIdx === 1) { - for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) { - taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255; - } - nUint24 = 0; - - } - } - - return taBytes; -} - -/* Codificación de array en una cadena Base64 */ - -function uint6ToB64 (nUint6) { - - return nUint6 < 26 ? - nUint6 + 65 - : nUint6 < 52 ? - nUint6 + 71 - : nUint6 < 62 ? - nUint6 - 4 - : nUint6 === 62 ? - 43 - : nUint6 === 63 ? - 47 - : - 65; - -} - -function base64EncArr (aBytes) { - - var nMod3 = 2, sB64Enc = ""; - - for (var nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) { - nMod3 = nIdx % 3; - if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; } - nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24); - if (nMod3 === 2 || aBytes.length - nIdx === 1) { - sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63)); - nUint24 = 0; - } - } - - return sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + (nMod3 === 2 ? '' : nMod3 === 1 ? '=' : '=='); - -} - -/* De array UTF-8 a DOMString y viceversa */ - -function UTF8ArrToStr (aBytes) { - - var sView = ""; - - for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) { - nPart = aBytes[nIdx]; - sView += String.fromCharCode( - nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */ - /* (nPart - 252 << 30) may be not so safe in ECMAScript! So...: */ - (nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 - : nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */ - (nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 - : nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */ - (nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 - : nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */ - (nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128 - : nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */ - (nPart - 192 << 6) + aBytes[++nIdx] - 128 - : /* nPart < 127 ? */ /* one byte */ - nPart - ); - } - - return sView; - -} - -function strToUTF8Arr (sDOMStr) { - - var aBytes, nChr, nStrLen = sDOMStr.length, nArrLen = 0; - - /* mapeando... */ - - for (var nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) { - nChr = sDOMStr.charCodeAt(nMapIdx); - nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6; - } - - aBytes = new Uint8Array(nArrLen); - - /* transcripción... */ - - for (var nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) { - nChr = sDOMStr.charCodeAt(nChrIdx); - if (nChr < 128) { - /* un byte */ - aBytes[nIdx++] = nChr; - } else if (nChr < 0x800) { - /* dos bytes */ - aBytes[nIdx++] = 192 + (nChr >>> 6); - aBytes[nIdx++] = 128 + (nChr & 63); - } else if (nChr < 0x10000) { - /* tres bytes */ - aBytes[nIdx++] = 224 + (nChr >>> 12); - aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); - aBytes[nIdx++] = 128 + (nChr & 63); - } else if (nChr < 0x200000) { - /* cuatro bytes */ - aBytes[nIdx++] = 240 + (nChr >>> 18); - aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); - aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); - aBytes[nIdx++] = 128 + (nChr & 63); - } else if (nChr < 0x4000000) { - /* cinco bytes */ - aBytes[nIdx++] = 248 + (nChr >>> 24); - aBytes[nIdx++] = 128 + (nChr >>> 18 & 63); - aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); - aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); - aBytes[nIdx++] = 128 + (nChr & 63); - } else /* if (nChr <= 0x7fffffff) */ { - /* seis bytes */ - aBytes[nIdx++] = 252 + (nChr >>> 30); - aBytes[nIdx++] = 128 + (nChr >>> 24 & 63); - aBytes[nIdx++] = 128 + (nChr >>> 18 & 63); - aBytes[nIdx++] = 128 + (nChr >>> 12 & 63); - aBytes[nIdx++] = 128 + (nChr >>> 6 & 63); - aBytes[nIdx++] = 128 + (nChr & 63); - } - } - - return aBytes; - -} -</pre> - -<h4 id="Tests">Tests</h4> - -<pre class="brush: js notranslate">/* Tests */ - -var sMyInput = "Base 64 \u2014 Mozilla Developer Network"; - -var aMyUTF8Input = strToUTF8Arr(sMyInput); - -var sMyBase64 = base64EncArr(aMyUTF8Input); - -alert(sMyBase64); - -var aMyUTF8Output = base64DecToArr(sMyBase64); - -var sMyOutput = UTF8ArrToStr(aMyUTF8Output); - -alert(sMyOutput);</pre> - -<h4 id="Apéndice_Decodificar_una_cadena_Base64_en_Uint8Array_o_ArrayBuffer">Apéndice: Decodificar una cadena <em>Base64</em> en <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array">Uint8Array</a> o <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer">ArrayBuffer</a></h4> - -<p>Estas funciones nos permiten crear también <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array">uint8Arrays</a> o <a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer">arrayBuffers</a> a partir de cadenas codificadas en base 64:</p> - -<pre class="brush: js notranslate">var myArray = base64DecToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw=="); // "Base 64 \u2014 Mozilla Developer Network" - -var myBuffer = base64DecToArr("QmFzZSA2NCDigJQgTW96aWxsYSBEZXZlbG9wZXIgTmV0d29yaw==").buffer; // "Base 64 \u2014 Mozilla Developer Network" - -alert(myBuffer.byteLength);</pre> - -<div class="note"><strong>Nota:</strong> La función <code>base64DecToArr(sBase64[, <em>nBlocksSize</em>])</code> devuelve un <a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array"><code>uint8Array</code></a> de bytes. Si tu objetivo es construir un búfer de datos crudos de 16, 32 o 64 bits, usa el argumento <code>nBlocksSize</code>, que es el número de bytes de los que la propiedad <code>uint8Array.buffer.bytesLength</code> debe devolver un múltiplo (1 u omitido para ASCII, <a href="/en-US/docs/Web/API/DOMString/Binary">cadenas binarias</a> o cadenas UTF-8 codificacas, 2 para cadenas UTF-16, 4 para cadenas UTF-32).</div> - -<p>Para una librería más completa, véase <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView" title="/en-US/docs/Web/JavaScript/Typed_arrays/StringView"><code>StringView</code></a><a href="/en-US/docs/Web/JavaScript/Typed_arrays/StringView" title="/en-US/docs/Web/JavaScript/Typed_arrays/StringView">, una representación parecida a C de cadenas basadas en arrays tipados</a>.</p> - -<h2 id="Véase_también">Véase también</h2> - -<ul> - <li>{{domxref("WindowBase64.atob","atob()")}}</li> - <li>{{domxref("WindowBase64.btoa","btoa()")}}</li> - <li><a href="/en-US/docs/data_URIs" title="/en-US/docs/data_URIs"><code>data</code> URIs</a></li> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBuffer">ArrayBuffer</a></li> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays">TypedArrays</a></li> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/ArrayBufferView">ArrayBufferView</a></li> - <li><a href="/en-US/docs/Web/JavaScript/Typed_arrays/Uint8Array">Uint8Array</a></li> - <li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Typed_arrays/StringView" title="/en-US/docs/Web/JavaScript/Typed_arrays/StringView"><code>StringView</code> – a C-like representation of strings based on typed arrays</a></li> - <li><a href="/en-US/docs/Web/API/DOMString" title="/en-US/docs/Web/API/DOMString">DOMString</a></li> - <li><a href="/en-US/docs/URI" title="/en-US/docs/URI"><code>URI</code></a></li> - <li><a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI" title="/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURI"><code>encodeURI()</code></a></li> - <li><a href="/en-US/docs/XPCOM_Interface_Reference/nsIURIFixup" title="/en-US/docs/XPCOM_Interface_Reference/nsIURIFixup"><code>nsIURIFixup()</code></a></li> - <li><a href="https://en.wikipedia.org/wiki/Base64" title="https://en.wikipedia.org/wiki/Base64"><code>Base64 on Wikipedia</code></a></li> -</ul> diff --git a/files/es/web/api/windowbase64/index.html b/files/es/web/api/windowbase64/index.html deleted file mode 100644 index 2607e635fa..0000000000 --- a/files/es/web/api/windowbase64/index.html +++ /dev/null @@ -1,109 +0,0 @@ ---- -title: WindowBase64 -slug: Web/API/WindowBase64 -tags: - - API - - HTML-DOM - - Helper - - NeedsTranslation - - TopicStub - - WindowBase64 -translation_of: Web/API/WindowOrWorkerGlobalScope -translation_of_original: Web/API/WindowBase64 ---- -<p>{{APIRef}}</p> -<p>The <code><strong>WindowBase64</strong></code> helper contains utility methods to convert data to and from base64, a binary-to-text encoding scheme. For example it is used in <a href="/en-US/docs/data_URIs">data URIs</a>.</p> -<p>There is no object of this type, though the context object, either the {{domxref("Window")}} for regular browsing scope, or the {{domxref("WorkerGlobalScope")}} for workers, implements it.</p> -<h2 id="Properties">Properties</h2> -<p><em>This helper neither defines nor inherits any properties.</em></p> -<h2 id="Methods">Methods</h2> -<p><em>This helper does not inherit any methods.</em></p> -<dl> - <dt> - {{domxref("WindowBase64.atob()")}}</dt> - <dd> - Decodes a string of data which has been encoded using base-64 encoding.</dd> - <dt> - {{domxref("WindowBase64.btoa()")}}</dt> - <dd> - Creates a base-64 encoded ASCII string from a string of binary data.</dd> -</dl> -<h2 id="Specifications">Specifications</h2> -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Specification</th> - <th scope="col">Status</th> - <th scope="col">Comment</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('HTML WHATWG', '#windowbase64', 'WindowBase64')}}</td> - <td>{{Spec2('HTML WHATWG')}}</td> - <td>No change since the latest snapshot, {{SpecName("HTML5.1")}}.</td> - </tr> - <tr> - <td>{{SpecName('HTML5.1', '#windowbase64', 'WindowBase64')}}</td> - <td>{{Spec2('HTML5.1')}}</td> - <td>Snapshot of {{SpecName("HTML WHATWG")}}. No change.</td> - </tr> - <tr> - <td>{{SpecName("HTML5 W3C", "#windowbase64", "WindowBase64")}}</td> - <td>{{Spec2('HTML5 W3C')}}</td> - <td>Snapshot of {{SpecName("HTML WHATWG")}}. Creation of <code>WindowBase64</code> (properties where on the target before it).</td> - </tr> - </tbody> -</table> -<h2 id="Browser_compatibility">Browser compatibility</h2> -<p>{{CompatibilityTable}}</p> -<div id="compat-desktop"> - <table class="compat-table"> - <tbody> - <tr> - <th>Feature</th> - <th>Firefox (Gecko)</th> - <th>Chrome</th> - <th>Internet Explorer</th> - <th>Opera</th> - <th>Safari</th> - </tr> - <tr> - <td>Basic support</td> - <td>{{CompatGeckoDesktop(1)}} [1]</td> - <td>{{CompatVersionUnknown}}</td> - <td>10.0</td> - <td>{{CompatVersionUnknown}}</td> - <td>{{CompatVersionUnknown}}</td> - </tr> - </tbody> - </table> -</div> -<div id="compat-mobile"> - <table class="compat-table"> - <tbody> - <tr> - <th>Feature</th> - <th>Firefox Mobile (Gecko)</th> - <th>Android</th> - <th>IE Mobile</th> - <th>Opera Mobile</th> - <th>Safari Mobile</th> - </tr> - <tr> - <td>Basic support</td> - <td>{{CompatGeckoMobile(1)}}</td> - <td rowspan="1">{{CompatVersionUnknown}}</td> - <td rowspan="1">{{CompatVersionUnknown}}</td> - <td rowspan="1">{{CompatVersionUnknown}}</td> - <td rowspan="1">{{CompatVersionUnknown}}</td> - </tr> - </tbody> - </table> -</div> -<p>[1] <code>atob()</code> is also available to XPCOM components implemented in JavaScript, even though {{domxref("Window")}} is not the global object in components.</p> -<h2 id="See_also">See also</h2> -<ul> - <li><a href="/Web/API/WindowBase64/Base64_encoding_and_decoding">Base64 encoding and decoding</a></li> - <li>{{domxref("Window")}}, {{domxref("WorkerGlobalScope")}}, {{domxref("DedicatedWorkerGlobalScope")}}, {{domxref("SharedWorkerGlobalScope")}}, and {{domxref("ServiceWorkerGlobalScope")}}</li> -</ul> diff --git a/files/es/web/api/globaleventhandlers/onunload/index.html b/files/es/web/api/windoweventhandlers/onunload/index.html index a665fc2027..a665fc2027 100644 --- a/files/es/web/api/globaleventhandlers/onunload/index.html +++ b/files/es/web/api/windoweventhandlers/onunload/index.html diff --git a/files/es/web/api/windowbase64/atob/index.html b/files/es/web/api/windoworworkerglobalscope/atob/index.html index aa9eeead07..aa9eeead07 100644 --- a/files/es/web/api/windowbase64/atob/index.html +++ b/files/es/web/api/windoworworkerglobalscope/atob/index.html diff --git a/files/es/web/api/windowtimers/clearinterval/index.html b/files/es/web/api/windoworworkerglobalscope/clearinterval/index.html index 14a1b0d1b8..14a1b0d1b8 100644 --- a/files/es/web/api/windowtimers/clearinterval/index.html +++ b/files/es/web/api/windoworworkerglobalscope/clearinterval/index.html diff --git a/files/es/web/api/windowtimers/cleartimeout/index.html b/files/es/web/api/windoworworkerglobalscope/cleartimeout/index.html index 0df5242672..0df5242672 100644 --- a/files/es/web/api/windowtimers/cleartimeout/index.html +++ b/files/es/web/api/windoworworkerglobalscope/cleartimeout/index.html diff --git a/files/es/web/api/windowtimers/setinterval/index.html b/files/es/web/api/windoworworkerglobalscope/setinterval/index.html index fe41612dd6..fe41612dd6 100644 --- a/files/es/web/api/windowtimers/setinterval/index.html +++ b/files/es/web/api/windoworworkerglobalscope/setinterval/index.html diff --git a/files/es/web/api/windowtimers/settimeout/index.html b/files/es/web/api/windoworworkerglobalscope/settimeout/index.html index 1180d9f8af..1180d9f8af 100644 --- a/files/es/web/api/windowtimers/settimeout/index.html +++ b/files/es/web/api/windoworworkerglobalscope/settimeout/index.html diff --git a/files/es/web/api/windowtimers/index.html b/files/es/web/api/windowtimers/index.html deleted file mode 100644 index 549969232f..0000000000 --- a/files/es/web/api/windowtimers/index.html +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: WindowTimers -slug: Web/API/WindowTimers -tags: - - API -translation_of: Web/API/WindowOrWorkerGlobalScope -translation_of_original: Web/API/WindowTimers ---- -<div>{{APIRef("HTML DOM")}}</div> - -<p><code><strong>WindowTimers</strong></code> contains utility methods to set and clear timers.</p> - -<p>There is no object of this type, though the context object, either the {{domxref("Window")}} for regular browsing scope, or the {{domxref("WorkerGlobalScope")}} for workers, implements it.</p> - -<h2 id="Properties">Properties</h2> - -<p><em>This interface do not define any property, nor inherit any.</em></p> - -<h2 id="Methods">Methods</h2> - -<p><em>This interface do not inherit any method.</em></p> - -<dl> - <dt>{{domxref("WindowTimers.clearInterval()")}}</dt> - <dd>Cancels the repeated execution set using {{domxref("WindowTimers.setInterval()")}}.</dd> - <dt>{{domxref("WindowTimers.clearTimeout()")}}</dt> - <dd>Cancels the repeated execution set using {{domxref("WindowTimers.setTimeout()")}}.</dd> - <dt>{{domxref("WindowTimers.setInterval()")}}</dt> - <dd>Schedules the execution of a function each X milliseconds.</dd> - <dt>{{domxref("WindowTimers.setTimeout()")}}</dt> - <dd>Sets a delay for executing a function.</dd> -</dl> - -<h2 id="Specifications">Specifications</h2> - -<table class="standard-table"> - <thead> - <tr> - <th scope="col">Specification</th> - <th scope="col">Status</th> - <th scope="col">Comment</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{SpecName('HTML WHATWG', '#windowtimers', 'WindowTimers')}}</td> - <td>{{Spec2('HTML WHATWG')}}</td> - <td>No change since the latest snapshot, {{SpecName("HTML5.1")}}.</td> - </tr> - <tr> - <td>{{SpecName('HTML5.1', '#windowtimers', 'WindowTimers')}}</td> - <td>{{Spec2('HTML5.1')}}</td> - <td>Snapshot of {{SpecName("HTML WHATWG")}}. No change.</td> - </tr> - <tr> - <td>{{SpecName("HTML5 W3C", "#windowtimers", "WindowTimers")}}</td> - <td>{{Spec2('HTML5 W3C')}}</td> - <td>Snapshot of {{SpecName("HTML WHATWG")}}. Creation of <code>WindowBase64</code> (properties where on the target before it).</td> - </tr> - </tbody> -</table> - -<h2 id="Browser_compatibility">Browser compatibility</h2> - -<p>{{CompatibilityTable}}</p> - -<div id="compat-desktop"> -<table class="compat-table"> - <tbody> - <tr> - <th>Feature</th> - <th>Firefox (Gecko)</th> - <th>Chrome</th> - <th>Internet Explorer</th> - <th>Opera</th> - <th>Safari</th> - </tr> - <tr> - <td>Basic support</td> - <td>{{CompatGeckoDesktop(1)}}</td> - <td>1.0</td> - <td>4.0</td> - <td>4.0</td> - <td>1.0</td> - </tr> - </tbody> -</table> -</div> - -<div id="compat-mobile"> -<table class="compat-table"> - <tbody> - <tr> - <th>Feature</th> - <th>Firefox Mobile (Gecko)</th> - <th>Android</th> - <th>IE Mobile</th> - <th>Opera Mobile</th> - <th>Safari Mobile</th> - </tr> - <tr> - <td>Basic support</td> - <td>{{CompatGeckoMobile(1)}}</td> - <td rowspan="1">{{CompatVersionUnknown}}</td> - <td rowspan="1">{{CompatVersionUnknown}}</td> - <td rowspan="1">{{CompatVersionUnknown}}</td> - <td rowspan="1">{{CompatVersionUnknown}}</td> - </tr> - </tbody> -</table> -</div> - -<p> </p> - -<h2 id="See_also">See also</h2> - -<ul> - <li>{{domxref("Window")}}, {{domxref("WorkerGlobalScope")}}, {{domxref("DedicatedWorkerGlobalScope")}}, {{domxref("SharedWorkerGlobalScope")}}, and {{domxref("ServiceWorkerGlobalScope")}}</li> -</ul> diff --git a/files/es/web/api/document/async/index.html b/files/es/web/api/xmldocument/async/index.html index 132fd106e1..132fd106e1 100644 --- a/files/es/web/api/document/async/index.html +++ b/files/es/web/api/xmldocument/async/index.html diff --git a/files/es/web/api/xmlhttprequest/loadend_event/index.html b/files/es/web/api/xmlhttprequest/loadend_event/index.html new file mode 100644 index 0000000000..39e528634d --- /dev/null +++ b/files/es/web/api/xmlhttprequest/loadend_event/index.html @@ -0,0 +1,91 @@ +--- +title: loadend +slug: Web/Events/loadend +tags: + - eventos +translation_of: Web/API/XMLHttpRequest/loadend_event +--- +<p>El evento <code>loadend</code> es emitido cuando el progreso de la carga de un recurso se ha detenido (e.g. despues que "error", "abort", o "load" han sido emitidos). Por ejemplo, esto aplica a las llamadas de {{domxref("XMLHttpRequest")}}, y al contenido de un elemento {{htmlelement("img")}} o {{htmlelement("video")}}.</p> + +<h2 id="Información_General">Información General</h2> + +<dl> + <dt style="float: left; text-align: right; width: 120px;">Especificación</dt> + <dd style="margin: 0 0 0 120px;"><a class="external" href="http://www.w3.org/TR/progress-events/">Progress</a></dd> + <dt style="float: left; text-align: right; width: 120px;">Interfaz</dt> + <dd style="margin: 0 0 0 120px;">ProgressEvent</dd> + <dt style="float: left; text-align: right; width: 120px;">Bubbles</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Cancelable</dt> + <dd style="margin: 0 0 0 120px;">No</dd> + <dt style="float: left; text-align: right; width: 120px;">Target</dt> + <dd style="margin: 0 0 0 120px;">{{domxref("HTMLImageElement")}}, Por Ejemplo</dd> + <dt style="float: left; text-align: right; width: 120px;">Acción por Defecto</dt> + <dd style="margin: 0 0 0 120px;">None</dd> +</dl> + +<h2 id="Propiedades">Propiedades</h2> + +<table class="standard-table"> + <thead> + <tr> + <th scope="col">Property</th> + <th scope="col">Type</th> + <th scope="col">Description</th> + </tr> + </thead> + <tbody> + <tr> + <td><code>target</code> {{readonlyInline}}</td> + <td>{{domxref("EventTarget")}}</td> + <td>The event target (the topmost target in the DOM tree).</td> + </tr> + <tr> + <td><code>type</code> {{readonlyInline}}</td> + <td>{{domxref("DOMString")}}</td> + <td>The type of event.</td> + </tr> + <tr> + <td><code>bubbles</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Whether the event normally bubbles or not.</td> + </tr> + <tr> + <td><code>cancelable</code> {{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Whether the event is cancellable or not.</td> + </tr> + <tr> + <td><code>lengthComputable </code>{{readonlyInline}}</td> + <td>{{jsxref("Boolean")}}</td> + <td>Specifies whether or not the total size of the transfer is known. Read only.</td> + </tr> + <tr> + <td><code>loaded</code> {{readonlyInline}}</td> + <td>unsigned long (long)</td> + <td>The number of bytes transferred since the beginning of the operation. This doesn't include headers and other overhead, but only the content itself. Read only.</td> + </tr> + <tr> + <td><code>total</code> {{readonlyInline}}</td> + <td>unsigned long (long)</td> + <td>The total number of bytes of content that will be transferred during the operation. If the total size is unknown, this value is zero. Read only.</td> + </tr> + </tbody> +</table> + +<h2 id="Eventos_Relacionados">Eventos Relacionados</h2> + +<ul> + <li>{{event("loadstart")}}</li> + <li>{{event("progress")}}</li> + <li>{{event("error")}}</li> + <li>{{event("abort")}}</li> + <li>{{event("load")}}</li> + <li>{{event("loadend")}}</li> +</ul> + +<h2 id="Ver_También">Ver También</h2> + +<ul> + <li><a href="/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Monitoring_progress" title="/en-US/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest">Monitoreando progreso</a></li> +</ul> |