Menú

Mostrar Mensajes

Esta sección te permite ver todos los mensajes escritos por este usuario. Ten en cuenta que sólo puedes ver los mensajes escritos en zonas a las que tienes acceso en este momento.

Mostrar Mensajes Menú

Mensajes - Gus Garsaky

#21
Front-end / [CSS3|JS] Menú dropdown
Junio 25, 2015, 04:36:31 PM
En éste post, vamos a crear un menú dropdown, lo que en HTML se llama select, y aplicarle los estilos que deseemos, lo que no podemos hacer con select (puedes customizarlo, pero de forma bastante limitada).


Marcado HTML

Código: html5

<section class="dropdown" tabindex="1">
<span>Choose one skill</span>
<ul>
<li><a href="#">Fullstack developer</a></li>
<li><a href="#">Frontend developer</a></li>
<li><a href="#">Backend developer</a></li>
</ul>
</section>


CSS

El dropdown será un section, y las opciones una lista. El primer hijo, el elemento span, será el texto que se le muestre al usuario antes de que éste escoja un valor. Ahora, veamos que estilos le damos.

Código: css

.dropdown {
    background-color: #fff;
    align-items: center;
    border: 1px solid #c5c5c5;
    border-radius: 3px;
    box-shadow: 0 2px 4px rgba(0,0,0,.15);
    display: flex;
    height: 35px;
    margin: 0;
    outline: none;
    position: relative;
}


El fondo será blanco, tendrá un borde color gris y un redondeado de 3 px. También tiene un alto de 35 px y una sobra ligera inclinada un poco hacia abajo. Tiene una posición relative que nos permitirá ubicar la lista de opciones de acuerdo a él; tiene además un display: inline-flex que hace que los elementos se muestren en forma horizontal y un align-items, que hará que los hijos se centren de acuerdo a su eje vertical.

Por el momento tenemos un rectángulo nada más, no hay indicios que ésto sea un dropdown, así que será necesario ponerle una flecha para que el usuario lo identifique. Para esto usaremos la pseudo clase :after.

Código: css

.dropdown:after {
    align-items: center;
    border-left: 1px solid #d8d8d8;
    color: #555;
    content: "▼";
    display: flex;
    font-family: 'segoe ui';
    font-size: .8rem;
    height: 100%;
    justify-content: center;
    width: 30px;
}


Crearemos un elemento en :after, de tipo flex con un alto de 100% y un ancho de 35px, además un borde izquierdo gris. Como contenido, tendrá una flecha mirando hacia abajo. Ahora, para centrar esa flecha, tendremos que usar align-items y justify-content con el valor center, logrando así un centrado perfecto.

Citar
El mismo centrado lo podemos lograr con las propiedades: line-height, que debe tener el mismo valor que el height y con text-align para centrar el texto en el eje horizontal.

Para el texto por defecto, será muy simple la cosa:

Código: css

.dropdown > span {
color: #777;
       display: block;
font-family: 'segoe ui';
margin: 0;
       padding: 0 .7rem;
}


Un color gris oscuro y un padding horizontal de .7rem.

LA LISTA

La lista es también sencilla. Veamos:

Código: css

.dropdown > ul {
        background-color: #fff;
border: 1px solid #c5c5c5;
border-radius: 3px;
box-shadow: 0 2px 4px rgba(0,0,0,.15);
        display: block;
left: 0;
list-style: none;
margin: 0;
        opacity: 0;
        padding: .45rem 0;
position: absolute;
top: 140%;
        transition: all .2s linear;
        visibility: hidden;
        z-index: 1;
}


Solo algunas pequeñas cosas que rescatar. Tiene un position absolute y un top de 140%, lo que hace que la lista se ubique un poco hacia bajo. También tiene una sombra y una opacidad 0 y visibility hidden, lo que hace que no esté visible la lista. Por último, tiene un z-index de 1, lo que hace que la lista esté sobre el resto de elementos en caso 'detrás' de la lista haya algún otro elemento.

Por cuestiones de estética, le creamos una flecha que indique que el pertenece al dropdown:

Código: css

.dropdown > ul:after {
    background-color: #fff;
    border: 1px solid #c5c5c5;
    border-right-width: 0;
    border-bottom-width: 0;
    content: "";
    display: block;
    height: 10px;
    position: absolute;
    top: -6px;
    right: 10px;
    transform: rotate(45deg) skew(5deg, 5deg);
    width: 10px;
}


Lo hacemos gracias a transform. Simplemente lo rotamos 45 grados y nos da la forma de un rombo, le borramos el borde derecho e inferior y ya tenemos nuestro triángulo. ¿fácil no?

Ahora simplemente vamos a estilizar los list items y los elementos a:

Código: css

.dropdown > ul > li, .dropdown > ul > li > a {
    display: block;
}
.dropdown > ul > li:not(:last-of-type) {
    border-bottom: 1px dashed #ddd;
}
.dropdown > ul > li:hover {
    background-color: #f5f5f5;
}
.dropdown > ul > li > a {
color: #777;
font-family: 'segoe ui';
padding: .5rem .8rem;
        text-align: center;
text-decoration: none;
}


La instrucción .dropdown > ul > li:not(:last-of-type) se traduce a: afecta a todos los elementos li hijos de ul menos el último hijo. Es decir, el borde inferior se lo daremos al primero y al rango entre él y el último (excluido).

Por último, haremos la lista visible cuando se haga click en el menú (y se añadirá la clase active mediante JavaScript):

Código: css

.dropdown.active > ul {
    opacity: 1;
    visibility: visible;
}


JAVASCRIPT

Ya tenemos la parte visual, ahora nos queda darle funcionalidad. Veamos el código JavaScript:

Código: javascript

'use strict';
class Dropdown {
constructor(el) {
this.dropdown = el;
this.display = el.querySelector('span');
this.list = el.querySelector('ul');
this.opts = this.list.querySelectorAll('li');
this.index = -1;
this.value = '';
this.initEvents();
}
initEvents() {
let self = this;
this.dropdown.addEventListener('click', function() {
self.dropdown.classList.toggle('active');
});
[].forEach.call(self.opts, function(cur) {
cur.addEventListener('click', function(e) {
e.preventDefault();
self.value = cur.textContent;
self.display.innerText = self.value;
self.index = Array.prototype.indexOf.call(self.list, cur);
});
});
},
       getValue() {
           return this.value;
       }
       getIndex() {
          return this.index;
       }
}


Primero le pasamos por el constructor nuestro dropdown. En el constructor, guarda el span, la lista y las opciones (li) como variables. También crea dos variables: value e index, las cuales contendrán el texto del valor escogido y el índice del mismo respectivamente. Cuando se escoja una opción, se guarda el texto de la opción escogida y el índice del mismo y se actualiza el texto del span con el texto de la opción que se ha escogido.

Tan solo basta con:

Código: javascript

document.addEventListener('DOMContentLoaded', function() {
let dropdown = new Dropdown(document.querySelector('.dropdown'));
});


Y ya tendremos nuestro dropdown funcional. Si quieremos saber en algún momento en valor o el índice actual, basa con:

Código: javascript
var value = dropdown.getValue();
var index = dropdown.getIndex();



You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login


Saludos.
#22
Front-end / Re:[CSS3] Login + Page preload
Junio 24, 2015, 06:37:27 PM
Jaja, el login sí es un estilo Plasma. El preloader y el navbar es un estilo flat moderno, en fin, una mezcla xD.

Gracias por comentar compañero. Saludos.
#23
Front-end / [CSS3] Login + Page preload
Junio 24, 2015, 05:37:41 PM
Con el avance de las tecnologías de la web, se pueden hacer cada vez cosas mas bonitas, cosas que sin duda pueden dar una buena UX al usuario de nuestra web o aplicación web.

En el presente texto, haremos un login con algunas animaciones y un preloader que seguramente habrás visto en algunas webs cuando te logueas y aparece algo que demuestra que la web está cargando (animaciones por lo general).

You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
(Click en la imagen para ir al demo)

CitarUsuario: You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
Contraseña: abc123



1. INDEX



  • Necesitaremos importar fontawesome y nornalize.

    La estructura HTML para nuestro login es sencilla:

    Código: html5

    <!DOCTYPE html>
    <html lang="es">
    <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="css/vendor/normalize.css"/>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"/>
    <link rel="stylesheet" href="css/main.css"/>
    <title>Login</title>
    </head>
    <body>
    <section class="main">
    <form id="loginFrm" class="form">
    <figure class="tooltip"></figure>
    <section class="form-head">
    <span>Login</span>
    <figure class="logo"></figure>
    </section>
    <section class="form-body">
    <div class="group">
    <label for="user">Email:</label>
    <input type="text" id="user" class="txt">
    </div>
    <div class="group">
    <label for="pass">Password:</label>
    <input type="password" id="pass" class="txt">
    </div>
    <div class="group flex-end">
    <button type="submit" id="login" class="btn btn-radical">login</button>
    </div>
    </section>
    </form>
    </section>
    <script>
    'use strict';
    window.addEventListener('load', function() {
    let main = document.querySelector('.main');
    main.classList.add('visible');
    });
    </script>
    <script src="js/auth.js"></script>
    </body>
    </html>


    La estructura es muy simple. Consta de un formulario con dos partes:


    • form-head: Aquí tendremos el título del form y el pin (el círculo con el ícono de un usuario).
    • form-body: Aquí tendremos todos los grupos (label/inputs) y botones.

    Vemos que hay un elemento con la clase 'tooltip'. Bien, éste elemento es como su nombre lo dice, un tooltip en cual nos servirá para mostrar los errores de autenticación.

    Ahora veamos el CSS. Lo primero que haremos será aplicar la propiedad box-sizing: border-box a HTML y hacer que todos los elementos hereden de él esa propiedad. La razón de ésto es porque así obligamos a mantener las mismas dimensiones; el padding forma parte de las dimensiones. Con el modelo no, puedes especificar 300px de ancho y con el padding se haría más grande.

    Código: css

    html {
    box-sizing: border-box;
    }
    *, *:before, *:after {
    box-sizing: inherit;
    }


    Luego, aplicamos estilos al container general, es decir, main:

    Código: css

    .main {
    align-items: center;
    background: rgba(136,211,124,1);
    background: linear-gradient(to bottom, rgba(136,211,124,1) 0%,
    rgba(136,211,124,1) 50%,
    rgba(190,144,212,1) 51%,
    rgba(190,144,212,1) 71%,
    rgba(190,144,212,1) 100%);
    background-repeat: repeat;
    display: flex;
    height: 100vh;
    justify-content: center;
    opacity: 0;
    transition: all .2s linear;
    visibility: hidden;
    }
    .main.visible {
    opacity: 1;
    visibility: visible;
    }


    Aplicamos display: flex, align-items: center y justify-content: center para centrar el formulario, un centrado perfecto. Para ésto, .main debe de tener un alto, el cual se lo especificamos en 100vh (100 view height).

    También, le damos una opacidad de 0 y una visibilidad oculta (hidden), además un transition: all .2s ease-in para que al cambiar opacity a 1 y visibility a visible, el efecto sea suave y bonito. Aquí es donde toma importancia .visible, que solamente cambia la opacidad y la visibilidad de .main.

    Ahora vayamos con el formulario:

    Código: css

    .form {
    background-color: #f7f7f7;
    border: none;
    border-radius: 2px;
    box-shadow: 0 2px 5px rgba(0,0,0,.25),
    0 -1px 5px rgba(0,0,0,.1);
    position: relative;
    width: 350px;
    }


    Nada relevante. Solo tiene un color blanco humo, sin bordes, un redondeado de 2px, una sombra, un ancho y lo importante, una posición relative. Esta propiedad nos permitirá situar el pin y el tooltip con relación al formulario.

    Código: css

    .form-head {
    align-items: center;
    border-radius: 2px 2px 0 0;
    border-bottom: 2px solid #9B59B6;
    display: flex;
    height: 45px;
    }
    .form-head > span {
    color: #555;
    font-family: 'segoe ui';
    font-size: 17pt;
    font-weight: lighter;
    margin-left: 12px;
    }


    La cabecera del formulario no tiene nada que explicar. Vayamos con el pin:

    Código: css

    .form-head .logo {
    background-position: center;
    background-repeat: no-repeat;
    background-image: url('http://urbita.com/img/default/default_user_256.png');
    background-size: cover;
    border-radius: 100%;
    box-shadow: 0px 2px 5px rgba(0,0,0,.25);
    height: 85px;
    left: calc(50% - 38.5px);
    margin: 0px;
    position: absolute;
    top: calc(0% - 38.5px);
    width: 85px;
    }


    El pin tiene un ancho y alto de 85px, además un border-radius de 100%, lo que le dará la forma de un círculo. Tiene una pequeña sombra con un offset Y de 2px, lo que hará que la sombra se despligue hacia abajo. Las propiedades de background permiten que la imagen se centre y que cubra el tamaño del círculo.

    La parte más importante es la propiedad position: absolute. Esta instrucción nos permite posicionar el pin de acuerdo al padre. Ahora, podemos centrarlo horizontalmente con solo left: calc(50% - 38.5px) y verticalmente con top: calc(0% - 38.5px) (por cuestión de entendimiento, si preguntas porqué no hice -38px xD). Ahora tenemos en pin centrado en la cabecera. ¿Fácil no?

    Ahora, hagamos algo de magia. Hagamos al pin animado, para ésto, usaremos keyframes:

    Código: css

    @keyframes spin {
    from { transform: rotate(0deg); }
    to { transform: rotate(1800deg); }
    }


    La animación se llamará spin, y el elemento que la use empezará con una rotación de 0 grados y terminará con una rotación de 1800 grados (5 vueltas completas). Ahora, el pin la usará cuando tenga la clase 'auth', que informa que se ha hecho una autenticación en el formulario:

    Código: css

    .form-head .logo.auth {
    animation-name: spin;
    animation-duration: 3000ms;
    animation-iteration-count: 1;
    animation-timing-function: linear;
    animation-play-state: running;
    animation-fill-mode: forwards;
    animation-delay: 0s;
    }


    La duración será de 3 segundos. Solo iterará una vez, será a una velocidad plana (linear) y sin tardanza antes de empezar la animación.

    Ahora vayamos con el cuerpo del formulario:

    Código: css

    .form-body {
    padding: 40px 25px 10px 25px;
    }
    .group {
    align-items: center;
    display: flex;
    margin-bottom: 10px;
    }
    .group > label {
    color: #777;
    display: block;
    flex-grow: 1;
    font-family: 'segoe ui';
    }


    El cuerpo de formulario tendrá un padding de 40px hacia arriba, 25px hacia los lados y 10px hacia abajo (lo último para contrarrestrar el margin-bottom de los grupos, que contiene los label y los input. Los labels serán en forma de bloque y con un flex-grow: 1 que hará que el label tenga un tamaño definido.

    Pondremos éstas 2 clases como apoyo, la primera para alinear los elementos hacia el final del bloque, y el otro para un centrado absoluto:

    Código: css

    .flex-end {
    justify-content: flex-end;
    }
    .flex-abs-center {
    align-items: center;
    justify-content: center;
    }


    Ahora vayamos con los textboxes:

    Código: css

    .txt {
    border: 1px solid #ddd;
    border-radius: 2px;
    color: #777;
    font-family: 'segoe ui';
    font-size: .9rem;
    outline: none;
    padding: .35rem .5rem;
    transition: all .2s ease;
    }
    .txt.invalid {
    border-color: rgba(231,76,60,.7);
    }
    .txt:hover {
    border-color: #ccc;
    }
    .txt:focus {
    border-color: #bbb;
    }


    Nada del otro mundo. La clase invalid solo pintará el borde del textbox de rojo. Ahora los botones:

    Código: css

    .btn {
    border: none;
    border-radius: 2px;
    box-shadow: 0 2px 5px rgba(0,0,0,.2);
    font-family: 'segoe ui';
    font-size: .9rem;
    outline: none;
    padding: .45rem 1.25rem;
    text-transform: uppercase;
    transition: all .3s ease;
    }
    .btn-radical {
    background-color: #F62459;
    color: rgba(255,255,255,.9);
    margin-top: 15px;
    }
    .btn-radical:hover {
    background-color: #DC1F4E;
    }


    Tampoco nada que destacar. Un redondeado de 2px, fuente segoe ui, una ligera sombra y un padding. btn-radical solo le da color (radical) y un margin-top de 15px.

    Por último, finalizaremos con el tooltip:

    Código: css

    .form .tooltip {
    background-color: rgba(0,0,0,.5);
    border-radius: 5px;
    box-shadow: 0px 2px 5px rgba(0,0,0,.25);
    color: rgba(255,255,255,.8);
    font-family: 'segoe ui';
    font-size: .9rem;
    height: 100px;
    left: calc(100% - 35px);
    margin: 0;
    padding: .7rem .6rem;
    opacity: 0;
    position: absolute;
    text-align: center;
    top: -140%;
    transition: all .4s ease-in;
    visibility: hidden;
    width: 200px;
    }


    El tooltip tiene un alto de 200px y un ancho de 100px. Tiene una posición absoluta, lo cual nos hace ubicarlo fácilmente de acuerdo a su padre (formulario). Le damos un left para que quede tirado más a la derecha y un top negativo muy grande para desplazarlo muy arriba, además una opacidad de 1.  Le damos un top muy alto porque en la transición, lo bajaremos y así da la impresión que viene aparece de la nada (por la opacidad también).

    Para hacer el efecto de la flecha, jugaremos un poco con las pseudoclases :before:

    Código: css

    .form .tooltip:before {
    border-color: rgba(0,0,0,.5) transparent;
    border-style: solid;
    border-width: 10px 10px 0px 10px;
    content: "";
    left: 10px;
    position: absolute;
    bottom: -10px;
    }


    Por último, para hacerlo visible, aplicaremos una clase:

    Código: css

    .form .tooltip.visible {
    opacity: 1;
    top: -50%;
    visibility: visible;
    }


    La clase visible, cambia la opacidad del tooltip, visiblidad y le da un top de -50%. Ésto lo que genera, es un efecto que el tooltip viene de arriba y en el camino se hace visible.

    Código JS

    Código: javascript

    'use strict';
    document.addEventListener('DOMContentLoaded', function() {
    let loginFrm = document.querySelector('#loginFrm');

    loginFrm.addEventListener('submit', function(e) {
    e.preventDefault();

    const ANIMATION_TIMEOUT = 3000; // duration of logo animation
    let logo = document.querySelector('.logo');
    let user = document.querySelector('#user').value.toLowerCase();
    let pass = document.querySelector('#pass').value;

    // if logo already is animated, the info is already processing
    if(logo.classList.contains('auth')) {
    return false;
    }

    logo.classList.add('auth'); // start animation

    // check credentials
    if(user == '[email protected]' && pass == 'abc123') {
    window.setTimeout(function() {
    sessionStorage.setItem('full_access', false);
    window.location.href = 'views/home.html';
    }, ANIMATION_TIMEOUT);
    } else {
    window.setTimeout(function() {
    logo.classList.remove('auth'); // remove animation of logo
    showTooltip();
    }, ANIMATION_TIMEOUT);
    }
    });

    // show and hide tooltip
    function showTooltip() {
    let tooltip = loginFrm.querySelector('.tooltip');
    tooltip.textContent = 'El email o contraseña ingresados no son correctos. Verifique e inténtelo nuevamente.';
    tooltip.classList.add('visible');
    // after 4 seconds, the tooltip disappear
    window.setTimeout(function() {
    tooltip.classList.remove('visible');
    }, 4000);
    }
    }); // end script


    El script es muy simple. Escuchamos por evento submit del formulario y obtenemos lo que se ha ingresado en las cajas de texto; también añadimos una constante llamada ANIMATION_TIMEOUT que especifica el tiempo que durará la animación del pin.

    Añadimos la clase 'auth' al pin para empezar la animación. Comprueba las credenciales y si coinciden crear una sessión para el usuario (HTML5 WebStorage) y redirige hacia home, todo ésto con un delay del mismo tiempo que dura la animación, esto es, que una vez que acaba la animación, se redigirá hacia home.

    Si las credenciales no coindicen, quitamos la clase 'auth' del pin para poder volver a iniciar la animación las veces que se requiera. Además, mostramos el tooltip informando de los errores de credenciales. El mismo tooltip desaparecerá al cabo de 4 segundos.

    El script embebido lo único que hace es hacer visible el index para darle el efecto de 'aparición':

    Código: javascript

    'use strict';
    window.addEventListener('load', function() {
    let main = document.querySelector('.main');
    main.classList.add('visible');
    });




    2. HOME



    HTML

  • Normalize.css requerido
  • Prefixfree requerido

    Código: html5

    <!DOCTYPE html>
    <html lang="es">
    <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="../css/vendor/normalize.css"/>
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css"/>
    <link rel="stylesheet" href="../css/home.css"/>
    <script src="js/vendor/prefixfree.min.js"></script>
    <title>Home page</title>
    </head>
    <body>
    <section class="preload"><i class="fa fa-4x fa-circle-o-notch fa-spin"></i></section>
    <section class="main">
    <header>
    <nav class="navbar">
    <!-- brand -->
    <a href="#" class="brand">Oh yeah!<i class="fa fa-2x fa-hand-o-right"></i></a>
    <!-- menu -->
    <ul class="menu">
    <li><a href="#">Messages<i class="fa fa-envelope"></i></a></li>
    <li>
    <a href="#">John doe<i class="fa fa-caret-down"></i></a>
    <ul>
    <li><a href="#" id="profile-img">
    <img src="http://i.imgur.com/IxWfQy2.jpg"/></a>
    </li>
    <li><a href="#">Profile<i class="fa fa-user"></i></a></li>
    <li><a href="#">Settings<i class="fa fa-cog"></i></a></li>
    <li><a href="#" id="logout">Logout<i class="fa fa-sign-out"></i></a></li>
    </ul>
    </li>
    </ul>
    </nav>
    </header>
    </section>
    <script src="js/homeui.js"></script>
    </body>
    </html>


    El marcado es simple. Consta de un header y un nav, con una lista incluída con dos elementos: Messages y un dropdown. El dropdown contiene una lista que son las opciones del usuario logueado.

    CSS

    Primero hacemos todos los elementos border-box:

    Código: css

    html { box-sizing: border-box; }
    *, *:before, *:after { box-sizing: inherit; }


    Preload:

    El preload es un simple etiqueta section con un elemento i dentro, el cual será la animación. Veamos que elementos tiene:

    Código: css

    .preload {
    align-items: center;
    background-color: #F22613;
    display: flex;
    height: 100vh;
    justify-content: center;
    left: 0;
    opacity: 0;
    position: absolute;
    top: 0;
    transition: all .5s ease;
    visibility: hidden;
    width: 100%;
    z-index: 1;
    }
    .preload.visible {
    opacity: 1;
    visibility: visible;
    }
    .preload i {
    color: rgba(255,255,255,.9);
    }


    Como vemos, preload ocupa el 100%(100vh) de alto y ancho, además es de posición absoluta y se posiciona en el vértice izquierdo, lo que junto con sus medidas hace que cubra toda la pantalla. Tiene una opcidad de 0 y una visibilidad oculta (hidden) por defecto, además se comporta como flexbox y tiene un centrado absoluto (flex-align: center y justify-content: center).

    El color del ícono animado es de color blanco con una opacidad de .9 (hace que se note apenas el fondo). La clase que activa la animación, se llama visible y lo único que hace es cambiar la opacidad a 1 y la visibilidad a visible.

    El elemento i es animado con la ayuda de font awesome, pero se puede hacer manualmente, quizás lo veamos en otro tutorial.

    Main

    El main es donde están todos nuestros elementos. Es el container general. Tiene las siguientes propiedades:

    Código: css

    .main {
    opacity: 0;
    transition: all .6s ease;
    visibility: hidden;
    }
    .main.visible {
    opacity: 1;
    visibility: visible;
    }


    Creo que en este punto ya sabemos que significa... Oculto por defecto y cuando se aplica la clase visible, se hace visible con animación. Ahora veamos el header y el nav:

    Código: css

    header {
    background-color: #22A7F0;
    color: rgba(255,255,255,.9);
    display: block;
    }
    .navbar {
    align-items: center;
    color: inherit;
    display: flex;
    justify-content: space-between;
    margin: 0px;
    padding: 0 .5rem;
    width: 100%;
    }


    Ambos tienen un ancho de 100%. El header es block y nav es flex. El nav tiene la propiedad justify-content: space-between, que hace que los hijos de alineen hacia los lados dejando todo el espacio restante del padre entre ellos. ¿Cuáles son los hijos? Son el logo de la empresa y la lista.

    El logo de la empresa tiene la clase brand y tiene los siguientes estilos:

    Código: css

    .brand {
    align-self: stretch;
    align-items: center;
    color: inherit;
    display: flex;
    font-family: 'segoe ui';
    margin: 0px;
    padding: 0 .25rem;
    }
    .brand > i {
    margin-left: .8rem;
    }


    De entrada, podemos ver que el brand tiene la propiedd align-self: stretch. Ésta propiedad sobreescribe el comportamiento por defecto de un hijo flex en fila (por defecto display: flex) en el eje Y. Es decir, si el padre especifica un align-items: center y el hijo especifica align-self, stretch, predomina el comportamiento del hijo. El valor stretch hace que el hijo se estire ocupando todo el alto del padre.

    Veamos la lista y sus elementos:

    Código: css

    .navbar ul {
    display: block;
    list-style: none;
    margin: 0px;
    padding: 0px;
    }
    .navbar > .menu {
    display: block;
    }
    .menu > li {
    display: inline-block;
    transition: all .1s ease-in;
    }
    .menu > li:hover {
    background-color: #1C99DD;
    }


    La lista es un bloque y sus elementos son bloque en línea, lo que hace que se muestre en forma horizontal dentro de la lista. Además, tienen una transición que anima el cambio de fondo cuando se hace hover sobre ellos. Además, ellos tendrán un margen a la derecha de 55px siempre y cuando no sea el último elemento de la lista y sus hijos (elementos a) serán elementos de bloque y tendrán cierto padding:

    Código: css

    .menu > li > a {
    display: block;
    padding: 1rem .5rem;
    }
    .menu > li > a > i {
    margin-left: 10px;
    }
    .menu > li:not(:last-of-type) {
    margin: 0 55px 0 0;
    }


    Veamos ahora, el dropdwon que serán las opciones del usuario.

    Código: css

    /* last li (profile dropdown) */
    .menu > li:last-of-type {
    position: relative;
    }
    /* dropdown */
    .menu > li:last-of-type > ul {
    background-color: #22A7F0;
    border-radius: .1725rem;
    left: -50%;
    opcity: 0;
    padding: .5rem 0;
    position: absolute;
    top: 170%;
    visibility: hidden;
    transition: all .14s ease-in;
    }
    /* arrow of menu */
    .menu > li:last-of-type > ul:after {
    border-color: #22A7F0 transparent;
    border-style: solid;
    border-width: 0 8px 8px 8px;
    content: "";
    position: absolute;
    right: 8px;
    top: -7px;
    }
    .menu > li:last-of-type:hover > ul {
    opacity: 1;
    top: 130%;
    visibility: visible;
    }


    El menú de usuario (dropdown), tendrá una posición relative, lo que permitirá aplicar a su lista interna, una posición absoluta y posicionarla debajo. La lista como ya dijimos tiene posición absoluta, una opacidad de 0, visibilidad oculta (hidden), un left de -50% lo que hará que la lista se desplace a la izquierda y un top de 170% que posiciona la lista muy abajo.

    Cuando se haga hover en el menú de usuario, la lista interna se hace visible (opacidad, visibility) y el top se reduce a 130%, lo que da el efecto de desplazamiento hacia arriba mientras se hace visible.

    Los li y a de la lista interna, ambos son block lo que hace que se muestre en forma de columna. Además, los li tienen se animan en cuanto se haga hover sobre ellos y se cambie el color.

    Código: css

    /* dropdown list items*/
    .menu > li:last-of-type > ul > li, .menu > li:last-of-type > ul a {
    display: block;
    font-size: .9rem;
    transition: transform .1s ease-in;
    }
    /* dropdown options */
    .menu > li:last-of-type > ul a {
    padding: .5rem .9rem;
    width: 8rem;
    }
    /* a elements of dropdown options */
    .menu > li:last-of-type > ul li:hover {
    background-color: #1998DC;
    }
    /* margin left to dropdown icon */
    .menu > li:last-of-type > a > i {
    margin-left: .8rem;
    }
    /* dropdown options icons */
    .menu li:last-of-type > ul a > i {
    float: right;
    margin-top: .3125rem;
    }


    Por último, la sección donde irá el avatar del usuario:

    Código: css

    /* profile image */
    #profile-img {
    display: flex;
    justify-content: center;
    margin-bottom: 5px;
    pointer-events: none;
    width: 100%;
    }
    #profile-img > img {
    background-position: center;
    background-size: cover;
    border-radius: 50%;
    display: block;
    height: 5rem;
    width: 5rem;
    }


    La sección que contiene la imagen del usuario es un bloque tipo flex que ocupa el 100% y que alinea la imagen al centro horizontal (justify-content: center). La imagen tiene un ancho y alto de 5rem (80px) y la imagen estará centrada y ocupara todos los 80px.

    El resultado:


    Código JS:

    Código: javascript

    'use strict';
    window.addEventListener('load', function() {
    let full_access = sessionStorage.getItem('full_access');
    let preload = document.querySelector('.preload');
    let main = document.querySelector('.main');
    // full_access is gived when user enter for first time
    if(full_access == "false") {
    // show preload animation
    preload.classList.add('visible');
    // animation delay 3s. After that, the main content appear
    window.setTimeout(function() {
    preload.classList.remove('visible');
    main.classList.add('visible');
    },3000);
    // change the flag. Now, the user has full access
    sessionStorage.setItem('full_access', true);
    }
    // if user has full_access, just show the page
    else {
    main.classList.add('visible');
    }
    });
    document.addEventListener('DOMContentLoaded', function() {
    document.querySelector('#logout').addEventListener('click', function(e) {
    e.preventDefault();
    // remove user's session
    sessionStorage.removeItem('full_access');
    // redirect to login
    window.location.href = '/PreloadCSS';
    });
    });


    Primero obtenemos el item 'full_access' de la sesión. Como sabemos, en el login, lo inicializamos en false cuando se ha logueado el usuario por primera vez.Seleccionamos el preload y el main y los guardamos en variables locales.

    Verificamos, si full_access es false (lo será la primera vez que se loguee) se le aplica la clase 'visible' al preload, que como recordamos, al aplicarle visible se muestra el preload y su animación.

    Creamos un delay de 3 segundos (el tiempo que tarda la animación) y cuando termine removemos la clase active del preload, haciendo que se oculte y agregamos la clase visible al main, haciendo que éste se haga visible. Al final, cambiamos el valor full_access por true.

    Si ya se tiene acceso total, simplemente se agrega la clase visible al main, haciendolo visible (sin mostrar el preload). Lo anterior lo aplicamos en el evento load de window.

    Por último, cuando el dom esté cargado, escuchamos por evento click en la opción logout del menú de usuario, removiendo la sesión y redirigiendo al login (fíjense que éste tbn tiene un efecto).


    You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
#24
Aquí muestran 5 formas de rootear un android. A mí me sirvió hace algún tiempo la forma #2.

You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login
#25
1. El método checkExt, verifica si la extensión es válida (.txt).
2. El método exists verifica si el archivo existe en el folder src.
3. El método checkMatches recorre el archivo en busca de las líneas con la extensión especificada.

El flujo es el siguiente:

1. Pide el nombre del archivo.
    1.2 Verifica si tiene extensión .txt
2. Comprueba que el archivo exista.
3. Si punto 2 retorna true, pide extensión a buscar.
4. Recorre el archivo en busca de líneas que terminen con dicha extensión.

Código: java

CharsFinder cf = new CharsFinder();
final Scanner reader;
List<String> matches = new ArrayList<>();
String fileName;
reader = new Scanner(System.in);
do {
System.out.println("Ingrese el fichero a buscar");
fileName = reader.next();
// si la extensión es correcta
if (cf.checkExt(fileName)) {
// si el archivo existe
if(cf.exists(fileName)) {
System.out.println("Ingrese la terminación que desea buscar");
String suffix = reader.next();
matches = cf.checkMatches(fileName, suffix);
}
// caso contrario salimos del programa
else {
System.out.println("El archivo no existe");
System.exit(-1);
}
}
// la extension no es .txt
else {
System.out.println("El fichero debe tener extensión .txt");
}
} while (!fileName.endsWith(".txt"));
reader.close();

if (!matches.isEmpty()) {
for (String coincidence : matches) {
System.out.println(coincidence);
}
} else {
System.out.println("No se encontraron coincidencias");
}


En caso quieras buscar palabras, solo debes hacer:

Código: java
String[] words = line.split(" ");
for(String word : words) {
    if(word.endsWith(".txt")) { matches.add(word); }
}
#26
Dudas y pedidos generales / Re:Duda sobre Icefaces
Junio 17, 2015, 06:40:26 PM
Con mucho gusto amigo. Suerte en tu aprendizaje.
#27

Código: java
package org.underc0de.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class CharsFinder {
public boolean checkExt(String fileName) {
if (fileName.endsWith(".txt")) {
return true;
}
return false;
}

public boolean exists(String fileName) {
try {
InputStream is = CharsFinder.class.getClassLoader()
.getResourceAsStream(fileName);
is.available();
return true;
} catch (IOException | NullPointerException e) {
return false;
}
}

public List<String> checkMatches(String fileName, String suffix)
throws IOException {
List<String> matches = new ArrayList<>();

InputStream is = CharsFinder.class.getClassLoader()
.getResourceAsStream(fileName);
BufferedReader bf = new BufferedReader(new InputStreamReader(is));
String line = "";
while ((line = bf.readLine()) != null) {
if (line.endsWith(suffix)) {
matches.add(line);
}
}

return matches;
}

public static void main(String[] args) throws IOException {
CharsFinder cf = new CharsFinder();
final Scanner reader;
List<String> matches = new ArrayList<>();
String fileName;
reader = new Scanner(System.in);
do {
System.out.println("Ingrese el fichero a buscar");
fileName = reader.next();
if (cf.checkExt(fileName)) {
System.out.println("Ingrese la terminación que desea buscar");
String suffix = reader.next();
matches = cf.checkMatches(fileName, suffix);
} else {
System.out.println("El fichero debe tener extensión .txt");
}
} while (!fileName.endsWith(".txt"));
reader.close();

if (!matches.isEmpty()) {
for (String coincidence : matches) {
System.out.println(coincidence);
}
} else {
System.out.println("No se encontraron coincidencias");
}
}
}
#28
Java / Re:Cifrado en JAVA
Junio 12, 2015, 10:13:07 AM
Gracias por el source, DeBobi. Como pequeña recomendación, trata de documentar los métodos para que sea mas easy to read.


Salu2.
#29
Presentaciones y cumpleaños / Re:Por aquí ando :)
Junio 10, 2015, 10:57:45 PM
Bienvenido Sphere y gracias por tus futuros aportes. Espero la pases bien aquí.
#30
Dudas y pedidos generales / Re:Duda sobre Icefaces
Junio 10, 2015, 10:30:32 PM
Buenas colega. Ciertamente hay muy poco material sobre IceFaces, y es debido a que PrimeFaces se ha convertido casi en un estándar como extensión para JSF, por ende, todos lo usan para extender la funcionalidad de JSF.

La mejor documentación que puedes ver es su showcase, lo puedes consultar You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login. En cada control, hay un acordeón que dice Source code, expándelo y verás el código HTML y Java usado para dicho demo. Por ejemplo para el datatable:


Puedes aprender también, PrimeFaces. Trae muchos controles y temas buenos. Puedes ver su showcase You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login.

Ahora, te recomiendo utilizar Java para el backend y utilizar HTML5 puro con AngularJS en el cliente. Ésto, lo combinas con microservices y te queda una aplicación cliente fully HTML5 y un backend en Java EE. Al usar JSF sin soporte para HTML5 te ahorra trabajo, pero también te quita libertad. Debes tenerlo en cuenta. Si no quieres que te quite libertad, prueba HTML5 + AngularJS en la vista y Java solo para backend, apoyándote en RESTfuls, o puedes usar Spring MVC.


Saludos.
#31
Java / Re:Buscando los números primos, en Java
Junio 09, 2015, 05:37:43 PM
He hecho una solución siguiendo la Criba de Erastóstenes.

Código: java

package mathio;

import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

/**
* Math util methods and classes
* @author Gustavo Garsaky
* @version 0.0.1
*/
public class MathUtils {

public PrimeNumbers primeNumbers() {
return new PrimeNumbers();
}

private class PrimeNumbers {

public List<Integer> listPrimesUntil(int limit) {
List<Integer> naturals = new CopyOnWriteArrayList<>();
// init naturals
for(int i=2; i<=limit; i++) {
naturals.add(i);
}
for(Integer current : naturals) {
discardMultiples(naturals, getMultiplesOf(current, naturals.size()));
// if discard continue, that means the process should continue
if(discard(current, naturals.size())) {
continue;
} else {
break;
}
}
List<Integer> primes = naturals;
return primes;
}
/**
* check the first natural quad. If it's
* less tan limit, process should continue
* @param firstNatural first natural number
*/
private boolean discard(int firstNatural, int limit) {
double firstNaturalQuad = Math.pow(new Double(String.valueOf(firstNatural)), 2.0d);
if(firstNaturalQuad <= limit) {
return true;
}
return false;
}
/**
* Get new list of natural numbers. The new list have all numbers
* that not in multiples of first natural number
* @param naturals Naturals numbers
* @param number Number to get multiples
*/
private void discardMultiples(List<Integer> naturals, List<Integer> multiples) {
// check if each multiple is in naturals list.
// if it isn't, append the multiple to new list
for(int i=0; i<multiples.size(); i++) {
             for(int k=0; k<naturals.size(); k++) {
                           if(multiples.get(i) == naturals.get(k)) {
                     naturals.remove(k);
                                  }
             }   
}   
}
} // end private class


/**
* Get the multiples of a number with some limit
* @param number Number to get multiples
* @param limit of multiples to get
*/
public static List<Integer> getMultiplesOf(int number, int limit) {
List<Integer> multiples = new ArrayList<>();
for(int i=number; i<limit; i++ ) {
if(i < limit) {
multiples.add(number * i);
}
}
return multiples;
}
public static void main(String[] args) {
PrimeNumbers primeNumbers = new MathUtils().primeNumbers();
List<Integer> primes = primeNumbers.listPrimesUntil(100);
    System.out.println("[+] Listando numeros primos...\n");
for(Integer prime : primes) {
System.out.println(prime);
}
}
}
#32
Te recomiendo Spring Social de Spring framework. Puedes ver la referencia del Spring Social Facebook You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login. Conectarlo a un SOAP, WDSL o RESTful, no tiene mayor misterio una vez entablada la conexión con Facebook.

Saludos.
#33
Muchas gracias Hu3c0. De hecho, estoy en ello ahora; no pude realizar nada las 2 últimas semanas por problemas personales pero trataré de hacer un par de post grandes (de 5-6 temas) para poner el curso al día.

Un saludo.
#34
Front-end / Re:[HTML5] Pizarra virtual
Junio 04, 2015, 05:32:16 PM
Puedes hacer un fork y hacerle los cambios que quieras @You are not allowed to view links. You are not allowed to view links. Register or Login or You are not allowed to view links. Register or Login UnLiMiTeD.

Saludos.
#35
Java / Re:Sockets en Java
Junio 04, 2015, 05:25:55 PM
En temas de rendimiento en los benchmarks que he visto no hay diferencia notoria entre IO y NIO. Desde el punto de vista de su escalabilidad, sí es cierto que es en cierto punto más escalable. También es más productivo que IO ya que incorpora muchas funciones útiles y sobre todo que NIO es Non Blocking y orientado a Buffer, mientras que IO es orientado a Stream y Blocking.

Lo cierto es que los devs deberían actualizarse. NIO tiene ya muchos años.
#36
Código: java

package org.underc0de.regextest;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
*
* @author Gustavo
*/
public class RegexLinkEditor {

    private final String REGEX = "(https?)://";
    private final String FILE_PATH = "D://links.txt";
    private final List<String> newLines = new ArrayList<>();
    private boolean hasLinks;
   
    public void run() throws IOException {
        boolean exists = IOUtils.exists(FILE_PATH);
        if (exists) {
            evaluate();
        } else {
            System.out.println("I'm sorry. The request file was not found.");
            System.exit(-1);
        }
    }

    /*
     * Si el archivo tená links, se escriben en el archivo
     * los links con el nuevo formato: [www.xyz.com]
    */
    private void evaluate() throws IOException {
        execute();
        if (hasLinks) {
            IOUtils.writeLines(newLines, FILE_PATH);
        } else {
            System.out.println("Not links found");
        }
    }

    private List<String> execute() throws IOException {
        List<String> oldLines = IOUtils.getAllLinesOf(FILE_PATH);
        Pattern pattern = Pattern.compile(REGEX);
       
        oldLines.stream().map((current) -> {
            Matcher matcher = pattern.matcher(current);
            String newLine = current;
            if (matcher.find()) {
                if(hasLinks == false) hasLinks = true; // cambia la bandera indicando que hay links
                newLine = replace(current);
            }
            return newLine;
        }).forEach((newLine) -> {
            newLines.add(newLine);
        });

        return newLines;
    }

    private String replace(String line) {
        String newLine = line.replaceAll(REGEX, "[") + "]";
        return newLine;
    }
}


Código: java

package org.underc0de.regextest;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
*
* @author Gustavo
*/
public class IOUtils {

    public static boolean exists(String path) {
        return new File(path).exists();
    }

    public static List<String> getAllLinesOf(String path) {
        List<String> lines = new ArrayList<>();
        try {
            lines =  Files.readAllLines(Paths.get(path), Charset.forName("UTF-8"));
        } catch (IOException e) {
            ExceptionUtils.showException(e);
        }
        return lines;
    }

    public static void writeLines(List<String> lines, String path) {
        try (BufferedWriter bw = new BufferedWriter
            (new PrintWriter(path))) {
            for(String line : lines) {
                bw.write(line);
                bw.newLine();
                bw.flush();
            }
        } catch(IOException e) {
            ExceptionUtils.showException(e);
        }
    }
}


Código: java

package org.underc0de.regextest;

import java.io.PrintWriter;
import java.io.StringWriter;

/**
*
* @author Gustavo
*/
public class ExceptionUtils {

    public static void showException(Exception e) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        e.printStackTrace(pw);
        String exceptionText = sw.toString();
        System.out.println(exceptionText);
    }
}


Código: java

/*
* To change this license header, choose License Headers in Project Properties.
* To change this template file, choose Tools | Templates
* and open the template in the editor.
*/
package org.underc0de.regextest;

import java.io.IOException;

/**
*
* @author Gustavo
*/
public class Main {
    public static void main(String[] args) {
        try {
            RegexLinkEditor editor = new RegexLinkEditor();
            editor.run();
        } catch (IOException e) {
            ExceptionUtils.showException(e);
        }
    }
}


Éste código hace lo que quieres. Lo hice en unos minutos solamente, ya verás por qué.

Hay un problema con éste código y es que, aunque detecte un link, reescribirá todas las 52k líneas, cosa que no es óptimo. Vale la pena si tienes al menos 100. Claro que se puede optimizar, pero eso te lo dejo a ti, como que practicas.
#37
Ambos frameworks son muy buenos, te hacen hacer un código muy modularizado, limpio y mantenible. RoR con MVC por una parte y Django con MVT (Model - View - Template). Son parecidos en algunos puntos y tanto, Ruby como Python son lenguajes poderosos.

Ambos lenguajes han tenido mucho crecimiento en la última década; son interpretados, de alto nivel. Heredan muchas características de lenguajes funcionales que los hacen poderosos y ambos tienen muchas librerías, buena documentación y comunidades relativamente grandes.

Luego de Java, yo preferiero Ruby y RoR. Mira la documentación oficial de ambos lenguajes, tutoriales y ejemplos para que te decidas por uno. Ten en cuenta que ambos, son lenguajes y frameworks de calidad.

Saludos.
#38
Dudas y pedidos generales / Re:Error boot ubunt
Mayo 15, 2015, 09:44:56 PM
Si sospechas del HDD, chequea si tu BIOS tiene el menú diagnostics, allí podrás comprobar la integridad de tu HDD. En caso haya sectores defectuosos, puedes probar a hacer un formateo a bajo nivel.
#39
Java / Re:Mini curso Java [En progreso]
Mayo 15, 2015, 04:12:38 PM

#12 - Switch




Definición: Switch es una estructura de control como lo son if, else if y else; de hecho, trabajan de la misma forma que trabajan los if anidados. La razón por la cual nos decidimos a usar switch en lugar de if, else if y else es generalmente por que switch nos brinda una estructura más limpia para trabajar con múltiples condiciones.

Sintaxis

La sintaxis de la estructura switch es la siguiente:

Pseudocódigo:

Citarsegún <expresión> hacer
    caso, = <valor>
        Instrucción 1
        Instrucción 2
    caso, = <valor>
        Instrucción 1
        Instrucción 2
    caso, = <valor>
        Inscripción 1
        Inscripción 2
    caso, sino
        Instrucción 1
fin según

En Java:

Código: java
switch(<expresión>) {
case <valor>:
/* Instrucciones */
break;
case <valor>:
/* Instrucciones */
break;
case <valor>:
/* Instrucciones */
break;
default: // opcional
/* Instrucciones */
}


Switch evalúa una expresión que se la pasa entre paréntesis. Cada case es un posible valor que puede ser el resultado de la expresión que ha evaluado el switch. El funcionamiento es igual al de los if anidados y al de los if, else if y else, ésto lo determinará la sentencia break.

La sentencia break se usa para romper un bucle, una condición, por lo que, si ponemos break al final de cada case, quiere decir que cuando se cumpla dicha condición, el break romperá la estructura switch. Ésto es muy semejante al if, else if y else. Si obviamos el break en cada case, si cumple una condición seguirá evaluando las siguientes condiciones. Ésto es igual a los if anidados.

la sentencia default se ejecuta si ninguna de las condiciones se cumple, ésto vendría a ser el else. Aquí es opcional, puedes poner un bloque por defecto o no.

Una estructura switch sería equivalente a un for con if anidados dentro. Así:

Código: java
for( temporal = 50; true; break){
  if( temporal == 25) { /* accion1; */}
  if( temporal == 35 || temporal == 23) { /* accion2 ; */ }
  /* en caso no se cumpla ninguna condición se ejecuta ésto:
   * (default)
   * /
   // acción si no se cumple ninguna condición (por defecto)
}



2. EJERCICIOS



Sado un número, mostrar el nombre del día al que pertenece en la semana.

Análisis:

1. Objetivo:
    Mostrar el nombre del día correspondiente al número del día en la semana.
2. Precondiciones:
    Que exista un número. (Lo desconocemos, por lo tanto, debemos pedírselo al usuario).
3. Desarrollo:
    El usuario ingresa un número.
    La aplicación evalúa el número y si es válido (1 y 7) muestra el nombre del día. Si no, mensaje de error.

Ya tenemos nuestro análisis y el flujo que tomará nuestra aplicación. Podemos apoyarnos en un diseño para poder entenderlo "visualmente". Ahora, vayamos a nuestro IDE NetBeans y plasmar nuestra solución en código Java:

Código: java

package org.underc0de.curso;

import java.util.Scanner;

/**
*
* @author Gustavo
*/
public class Clase10 {

    public static void main(String[] args) {
        Scanner reader = new Scanner(System.in);
        int numero;
        System.out.println("Ingrese un número entre 1 y 7");
        numero = reader.nextInt();
        switch (numero) {
            case 1:
                System.out.println("El día es Lunes");
                break;
            case 2:
                System.out.println("El día es Martes");
                break;
            case 3:
                System.out.println("El día es Miércoles");
                break;
            case 4:
                System.out.println("El día es Jueves");
                break;
            case 5:
                System.out.println("El día es Viernes");
                break;
            case 6:
                System.out.println("El día es Sábado");
                break;
            case 7:
                System.out.println("El día es Domingo");
                break;
            default:
                System.out.println("Debe ingresar un número entre 1 y 7");
        }
    }
}



3. EJERCICIOS PROPUESTOS



1. Dado un número del 1 al 12, diga el nombre del mes correspondiente.
2. Dada una letra, imprimir si es vocal.
#40
Java / Re:Mini curso Java [En progreso]
Mayo 15, 2015, 11:06:16 AM

#11 - ESTRUCTURAS REPETITIVAS




Definición: Una estructura repetitiva nos permite trabajar en ciclos, es decir, en intérvalos de tiempo. Cuando trabajamos con estructuras repetitivas, podemos contrar la duración de un ciclo y definir qué hacer durante la duración de éste. Ésta estructura es muy útil cuando deseamos hacer procesos largos que del modo normal (secuencial) fueran muy largos y redundantes. El propósito de una estructura repetitiva es repetir un bloque de código mientras una condición sea verdadera.

1. TIPOS DE ESTRUCTURAS REPETITIVAS

1.1 WHILE (mientras)

En el bucle while, la condición se controla por una variable de control, que en éste caso es llamado centinela. El centinela es una variable que controlará el ciclo de vida del bucle y que puede ser una variable booleana, entera, etc.

Sintaxis:

Código: text
mientas <condición> hacer
    instrucciones
fin mientras


En Java

Código: java
while (<condición>) {
    // instrucciones
}


1.2 DO WHILE (hacer mientras)

Al igual que el bucle while, la condición se controla con un centinela; por el contrario, éste bucle primero ejecuta las instrucciones y luego evalúa la expresión. Ésto es útil cuando queremos que sí o sí primero se ejecuten unas instrucciones y luego evalúe alguna condición.

Sintaxis:

Pseudocódigo:

Código: text
hacer
    <instrucciones>
mientras  (<condición>)


Java:

Código: java
do {
    // instrucciones
} while(<condición>);


1.3 FOR

Una estructura repetitiva for se utiliza para realizar un proceso durante un ciclo del cual tenemos conocimiento de su fin. Consta de 3 partes:


  • variable de control: es la variable que controla la condición del bucle.
  • condición: es la expresión que for evaluará antes de cada iteración y que pone un límite al bucle.
  • aumento/decremento: es el aumento o decremento de la variable de control. Es importante ésta parte ya que si no fijamos un incremento o decremento, la condición nunca terminará.

Sintaxis:

Pseudocódigo:

Código: text
para i <- x hasta n hacer incremento i+1 hacer
    <instrucciones>
fin para


Java:

Código: java
for(byte indice = 0; indice < 10; indice++) {
    // instrucciones
}



2. ¿Cuándo utilizar while, do while y for?




2.1 CUÁNDO USAR WHILE

Usaremos while cuando las instrucciones que ejecutará puede que no se ejecuten ninguna vez si la condición es falsa. Por ejemplo:

Código: java
System.out.println("¿Desea ingresar datos? S/N");
char seguir = reader.next().charAt(0); // centinela
while(seguir == 'S') {
String nombre;
System.out.println("Ingrese su nombre");
nombre = reader.nextLine();
System.out.println(nombre);
System.out.println("¿Desea seguir? S/N");
char = reader.next().charAt(0);
}


En éste caso, el bucle puede nunca ejecutarse (si el usuario ingresa N).

2.2 CUÁNDO USAR DO WHILE

Usaremos do while cuando queramos que al menos una vez se ejecutarán las instrucciones. Por ejemplo:

Código: java
char seguir; // centinela
do {
String nombre;
System.out.println("Ingrese su nombre");
nombre = reader.nextLine();
System.out.println(nombre);
System.out.println("¿Desea seguir? S/N");
char = reader.next().charAt(0);
} while(seguir == 'S');


2.3 CUÁNDO USAR FOR

Usaremos for cuando sabemos de antemano cuántas veces iterará el bucle. Por ejemplo:

Código: java
System.out.println("¿Cuántos usuarios desea guardar");
byte maximoUsuarios = reader.nextByte();
for(byte indice = 0; indice < maximoUsuarios; indice++) {
// proceso
}


En el ejemplo anterior, el bucle interará las veces que el usuario ha ingresado. Si el usuario ingresa 10, el bucle iterará 10 veces.


3.EJERCICIOS EN CLASE



En una empresa se requiere calcular el salario semanal de cada uno de los n obreros que laboran en ella. El salario se obtiene de la siguiente forma:
Si el obrero trabaja 40 horas o menos se le paga $20 por hora.

Solución:

Análisis

1. Objetivo
    Se desea calcular el salario semanal de cada obrero de acuerdo a los parámetros dados:
    Si trabaja 40 horas o menos, se le paga $20/h.
    Si trabaja más de 40 horas, se le paga lo mismo por las primeras 40h y $25 por cada hora extra.
2. Precondiciones
    Que existan empleados y que hayan trabajado.
3. Desarrollo
    Pedirle al usuario los nombres de los empleados y sus horas trabajadas.
    Por cada empleado, mostrarle su salario de acuerdo a los parámetros fijados.

> Datos importantes:

Entrada:

  • Nombre del empleado.
  • Horas trabajadas.

    Proceso:

  • Tarifa por hora normal y por hora extra.
  • Salario.

    Salida:

  • Salario.

    Diagrama de flujo:



    Código:

    Código: java

    package org.underc0de.curso;

    import java.util.Scanner;

    /**
    *
    * @author Gustavo
    */
    public class Repetitivas {
        public static void main(String[] args) {
            final byte THORA_NORMAL = 20;
            final byte THORA_EXTRA = 25;
            Scanner reader = new Scanner(System.in);
           
            byte numeroEmpleados;
            System.out.println("¿Cuántos empleados desea ingresar?");
            numeroEmpleados = reader.nextByte();
            reader.nextLine(); // libera el fin de línea (enter)
           
            for(byte actual=1; actual<=numeroEmpleados; actual++) {
                String nombre;
                byte horasTrabajadas;
                short salarioNeto;
                System.out.println("Ingrese el nombre del empleado");
                nombre = reader.nextLine();
                System.out.println("Ingrese las horas trabajadas");
                horasTrabajadas = reader.nextByte();
                if(horasTrabajadas <= 40) {
                    salarioNeto = (short) (horasTrabajadas * THORA_NORMAL);
                } else {
                    byte horasExtras;
                    short horasNormales;
                    short salarioBase;
                    short salarioExtra;
                    horasExtras = (byte) (horasTrabajadas - 40);
                    horasNormales = (short) (horasTrabajadas - horasExtras);
                    salarioBase = (short) (horasNormales * THORA_NORMAL);
                    salarioExtra = (short) (horasExtras * THORA_EXTRA);
                    salarioNeto = (short) (salarioBase + salarioExtra);
                }
                System.out.println("El salario del empleado "+nombre+" es "+salarioNeto+"\n\n");
                reader.nextLine(); // libera el final de línea (enter)
            }
        }
    }


    La razón por la que hacemos (short) es porque, por defecto Java devuelve las operaciones aritméticas como int. Entonces, dado que las variables son short, hay una pérdida de precisión y debemos convertir ese int a short. Si no desean hacer ésto, simplemente declaren todo como int.

    CitarCuando ingresas un número y das enter, el enter (fín de línea) ingresado queda en memoria, es por ésta razón que cuando llamamos a nextLine() luego de leer un número, el nextLine() lee el enter ingresado anteriormente porque ha quedado en memoria y se salta. Para evitar ésto debemos liberar el enter llamando a nextLine() luego de leer un número y antes de leer un texto.


    4. EJERCICIOS PROPUESTOS



    1.   Leer 10 números e imprimir solamente los números positivos.
    2.   Leer 20 números e imprimir cuantos son positivos, cuantos negativos y cuantos neutros
    3.   Imprima la suma de todos los números pares que van del 1 al 100 y diga cuántos hay.




    Glosario

    bucle, loop: estructura repetitiva (while, do while y for).
    centinela: variable que controla el ciclo de vida de un bucle.