Categorías
Desarrollo y Programación

Patrón de Diseño: Fábrica Abstracta (Abstract Factory)

Este patrón es parte de los patrones de diseño creacionales.

Estos patrones se tratan de instancias clases. Los patrones de diseño creacionales pueden ser divididos en 2 tipos, por creación de clase (que utiliza la magia de la herencia) y por creación de objetos (que delega las responsabilidades como un profesional).

Fábrica Abstracta (Abstract Factory)

  • Brinda una interface para la creación de familias relacionadas u objetos dependientes sin especificar una clase concreta.
  • Una jerarquía que encapsula: las posibles plataformas, y la construcción de un conjunto de productos.
  • El operador new es nocivo para este tipo de patrón.

Problemática

Cuando una aplicación necesita portabilidad, es necesario encapsular las dependencias por plataforma. Estas plataformas pueden incluir, Sistema de ventanas, el sistema operativo, el tipo de dispositivo, las bases de datos, etc.

Por lo general si esta encapsulación no es pensada a futuro, llegarán a existir muchos condicionales (if, elseif) que le dan soporte a los distintos tipos de plataformas, que se van multiplicando a lo largo del proyecto cada vez que se necesita una nueva plataforma.

Estructura

El patrón de Fábrica Abstracta define un método (factory) por producto. Cada método encapsula el operador “new” y las clases de los productos por plataforma. Cada plataforma debe ser modelada con una clase derivada de la Factory.

Ejemplo

El propósito de la Fábrica Abstracta es proveer una interface para la creación de familias de objetos relacionados, sin especificar clases concretas.

Este patrón se encuentra en una fábrica de moldeado de autopartes. El equipo de corte y moldeo es la Fábrica Abstracta la cual crea las autopartes. La misma maquinaria es utilizada para cortar las puertas, los cofres, las cajuelas, etc. Para diferentes modelos de coches. A través del uso de rodillos que cambian el tipo de acabado, las clases concretas son producidas por la maquinaria que puede ser cambiada en menos de 3 minutos.

Consideraciones para elegir la fábrica abstracta

  • Decidir si la independencia de la plataforma y los servicios de creación son el principal problema.
  • Crear una matriz de plataformas contra productos.
  • Definir una interface factory que consista de  un método factory por producto.
  • Definir una clase factory derivada por cada plataforma que encapsule todas las referencias al operador new.
  • El cliente debería quitar todas las referencias a new, y utilizar los métodos factory para crear los productos.

Reglas

Algunas veces los patrones creacionales con competencia, y en toros casos con complementarios. Una Fábrica Abstracta puede tener un conjunto de Prototipos de los cuales clonar y retornar objetos de productos.

Los constructores pueden utilizar otros patrones para implementar los componentes a construir. Fabrica Abstracta, Constructor y Prototipo pueden utilizarse como Singleton en sus implementaciones.

Los tres definen un objeto factory que es el responsable de crear las clases para los objetos de producto.

  • Fábrica Abstracta; se encarga de la creación de objetos produciéndolos desde distintas clases.
  • Builder (Construsctor): es un objeto Factory que construye un producto complejo utilizando un protocolo definido.
  • Prototipo: es un objeto factory que construye el producto copiando un objeto prototipo.

El builder se enfoca en construir un objeto complejo paso a paso. La Fábrica Abstracta se enfatiza en una familia de productos. Al final el Builder retorna ese producto.

A menudo los diseños empiezan utilizados un Método Factory (poca complejidad, personalizable, lleno de subclases) y evoluciona en torno a Prototype, o Builder (a veces mas flexible, a veces más complejo) según como el diseñador infiera donde esa flexibilidad es necesaria.

Fábrica Abstracta en Typescript

El código de ejemplo esta en: https://github.com/elporfirio/design-patterns-typescript/tree/master/abstract_factor

Supongamos que tengo una fábrica de productos de videojuegos, donde grabo los discos e imprimo portadas. Para ello tengo una serie de clases definidas para los productos:

/**
 * Game Products Classes
 */
export abstract class AbstractDisc {
    abstract getTitle();

    abstract getGenre();
}

export abstract class AbstractCover {
    abstract getSize();

    abstract getPaperType();
}

abstract class AbstractCallOfDuty {
    private gameSeries = 'Call of Duty';

    getGameSeries() {
        return this.gameSeries;
    }
}

export class CallOfDutyDisc extends AbstractCallOfDuty implements AbstractDisc {
    private title = 'Modern Warfare';
    private genre = 'FPS';

    getTitle() {
        return this.title;
    }

    getGenre() {
        return this.genre;
    }
}

export class CallOfDutyCover extends AbstractCallOfDuty implements AbstractCover {
    private size = '4x6';
    private paperType = 'couche';

    getSize() {
        return this.size;
    }

    getPaperType() {
        return this.paperType;
    }
}

Esos productos son producidos para 2 plataformas, PlayStation y Xbox para lo cual defino mis clases fabrica:

import { CallOfDutyCover, CallOfDutyDisc} from "./product_classes";

/**
 * Game Factory Classes
 */
export abstract class AbstractGameFactory {
    abstract makeDisc();

    abstract makeCover();
}

export class PS4GameFactory extends AbstractGameFactory {
    private brand = 'Sony';

    makeDisc() {
        return new CallOfDutyDisc();
    }

    makeCover() {
        return new CallOfDutyCover();
    }
}

export class XBOXGameFactory extends AbstractGameFactory {
    private brand = 'Microsoft';

    makeDisc() {
        return new CallOfDutyDisc;
    }

    makeCover() {
        return new CallOfDutyCover;
    }
}

Por último lo que tengo que hacer es echar a andar mi fábrica, tan fácil como solo correr mis distintos tipos:

import {PS4GameFactory, XBOXGameFactory} from "./factory_clases";

export class GameMaker {
    public constructor() {
        const ps4Game = new PS4GameFactory();
        this.tester(ps4Game);

        const xboxGame = new XBOXGameFactory();
        this.tester(xboxGame);
    }

    tester(game) {
        const cover = game.makeCover();
        const disc = game.makeDisc();

        console.log('==============');

        console.log(cover.getPaperType());
        console.log(cover.getSize());

        console.log(disc.getGenre());
        console.log(disc.getTitle());

        console.log('==============');
    }
}

Por cierto si quieres correrlo no uno que se haría es un new GameMaker();

Y eso es todo, ¿qué pasaría si necesito otro juego, como el Dragon Ball FighterZ?, simplemente tendríamos que agregar ese nuevo producto a nuestra clase producto.

¿Y si ahora queremos Nintendo Switch?, 🤯 bueno pues hay que agregarlo a nuestras fabricas. Y así se logra la combinación de fábrica abstracta con sus productos, por supuesto al inicio parece no tener mucha utilidad.

Sin embargo imaginen hacer una fábrica en base a módulos nuevos o simples archivos .json. Agregar y quitar fábricas en desuso sería tan fácil como agregar y eliminar archivos.
Y ya está, felices arquitecturas 😬

Categorías
Desarrollo y Programación

Solución al ERROR 1698 (28000): Access denied for user

Este problema me ocurrió en un sistema Raspberry Pi con Ubuntu Server y MySQL, a continuación las versiones que utilizo:

  • Ubuntu 20.04 LTS
  • mysql  Server version: 8.0.20-0ubuntu0.20.04.1 (Ubuntu)

Procedimiento para replicar el error

Después de configurar el server MySQL y hacer mysql_secure_installation mi usuario queda configurado, pero al intentar conectarse con el comando:

 mysql -u root -p

Nos muestra el error:

ERROR 1698 (28000): Access denied for user 'root'@'localhost'

Soluciones Alternativas:

La mayoría de las soluciones te piden deshabilitar las funciones que vienen en MySQL 8.0 habilitadas por defecto ¿que beneficio tiene quitar las opciones de seguridad por utilizar un sistema obsoleto?

Solución:

Ingresar a MySQL con el comando sudo

 sudo mysql -u root

Listar todos los usuarios que se tienen para validar el tipo de autenticación.

SELECT User, Host, plugin FROM mysql.user;

Lo que nos muestra una lista de usuarios como:

+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| debian-sys-maint | localhost | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | auth_socket           |
+------------------+-----------+-----------------------+
5 rows in set (0.00 sec)

El usuario que creamos con el asistente de mysql_secure_installation tiene un tipo de autenticación auth_socket lo que no nos permite iniciar sesión.

Crear usuario con el SHA-2

Recuerden otorgar los permisos correspondientes de acceso.

CREATE USER 'elporfirio'@'localhost'
IDENTIFIED WITH caching_sha2_password BY 'MyPassword2020*';

Editar usuario para cambiar a SHA-2

ALTER USER 'root'@'localhost' IDENTIFIED WITH caching_sha2_password BY 'MyPassword2020*';

¿Problemas con un password poco seguro? Revisa la información más abajo.

Nuestro usuario ya debería aparecer abajo el ejemplo con el creado y el editado, notar que root tiene ahora el nuevo plugin:

mysql> SELECT User, Host, plugin FROM mysql.user;
+------------------+-----------+-----------------------+
| User             | Host      | plugin                |
+------------------+-----------+-----------------------+
| debian-sys-maint | localhost | caching_sha2_password |
| elporfirio       | localhost | caching_sha2_password |
| mysql.infoschema | localhost | caching_sha2_password |
| mysql.session    | localhost | caching_sha2_password |
| mysql.sys        | localhost | caching_sha2_password |
| root             | localhost | caching_sha2_password |
+------------------+-----------+-----------------------+
6 rows in set (0.00 sec)

Ahora que el usuario ya tiene el plugin: caching_sha2_password ya puedes iniciar sesión normalmente con el usuario que decidas:

mysql -u elporfirio -p

Solucionado y listo para utilizar tu base de datos MySQL en su última versión.

Problemas con la seguridad de la contraseña

Puedes revisar el medium de micheleberardi para tener mas informción de las politicas de seguridad.

Referencias:

Categorías
Desarrollo y Programación

Importar y Exportar con Javascript ES6

Bienvenidos a otra valiosa información en internet totalmente en español, en esta ocasión vamos a ver cómo importar y exportar variables, funciones, expresiones y clases con JavaScript.

Actualizaciones:
– Elimine paréntesis de la declaración de clases

Exports Default

Cuando se utiliza un default para exportar, se puede utilizar cualquier nombre para importar.

Función Anónima

// helpers.js
export default function() {
  // Do something
}

// index.js
import Awesomeness from './helpers'

console.log(Awesomeness); // ƒ(){}

Función

// helpers.js
export default function hiDude() {
  // Do something
}

// index.js
import Awesomeness from './helpers'

console.log(Awesomeness); // ƒ hiDude(){}

No es posible tener más de un “export default” en un archivo, así que no lo intentes en casa.

– La comunidad PRO de JavaScript

Clase Anónima

Recordar que las clases son un tipo de objeto con superpoderes.

// classes.js
export default class {
  // rest of class
}

// index.js
import ImportantClass from './classes'

console.log(ImportantClass); // ƒ _default(){}

Clase

// classes.js
export default class Person {
  // rest of class
}

// index.js
import ImportantClass from './classes'

console.log(ImportantClass); // ƒ Person(){}

Variables

// constants.js
const PI = 3.1416;
export default PI;

// index.js
import PIValue from './constants'

console.log(PIValue); // 3.1416

Otro método para exportar variables:

// constants.js
const PI = 3.1416;
export {PI as default};

// index.js
import PIValue from './constants'

console.log(PIValue); // 3.1416

Este último también sirve para las funciones:

// constants.js
function getPI(){
  return 3.1416
}
export {getPI as default};

// index.js
import PIValue from './constants'

console.log(PIValue); // ƒ getPI(){}

Named Exports

A diferencia de los default, en este tipo si es necesario dar un nombre a nuestra variable, método, etc.

Exportar por separado

export function add(){
  // add something
}

export class Person {
  // class definition
}

export const PI = 3.1416;

export let car = {
  paintColor: 'red'
}

Exportar todo en una sentencia

function add(){
  // add something
}

class Person {
  // class definition
}

const PI = 3.1416;

let car = {
  paintColor: 'red'
}

export { add, Person, PI, car };

Para importar estos elementos (cualquiera de las 2 formas anteriores) es necesario utilizar el nombre que se les dio al momento de exportar:

import { add, Person, PI, car } from './helpers'

console.log(add); // ƒ add(){}
console.log(Person); // ƒ Person(){}
console.log(PI); // 3.1416
console.log(car); // { paintColor: 'red' }

Exportar named y default

En el caso de las named, deben importarse entre los corchetes y el default queda fuera de los corchetes.

// important.js
export add() {
  // do add
}

export const maxValue = 999;

export default class Calculator {
  // Calculator class
}
// index.js
import Calc, { maxValue, add } from './important'

// Recordar que el default no importa el nombre
console.log(Calc); // ƒ Calculator() {}
console.log(maxValue); // 999
console.log(add); // ƒ add() {}

No es posible hacer un “named export” con una función anónima o una expresión. Siempre es necesario que tenga un nombre.

– La comunidad PRO de JavaScript

Exportar con un nombre diferente (alias)

En algunos casos nos puede ayudar darle un nombre diferente a nuestros exports.

function add(){
  // add something
}

function divide(){
  // divide something
}

export { add as plus, divide as split };

Al momento de importar es necesario importar con ese nuevo nombre que le asignamos, sin embargo nuestros métodos conservaran la referencia a su nombre original.

import { plus, split } from './calculator.js'

console.log(plus); // ƒ add() {} <-- add en vez de plus
console.log(split); // ƒ divide() {}

Exportar desde otros archivos

Si aunque el uso de este tipo no es muy común, es posible hacerlo. Supongamos que tenmos un archivo pruncipal:

export default add() {
  // add something
}

export multiply() {
  // multiply something
}

ahora podemos tener un exportador que agrupe de uno o diferentes archivos:

export {
  default,
  multiply
} from './calculator'

Ahora podemos importar del nuevo archivo:

import add, { multiply } from './operations'

console.log(add); // ƒ add() {}
console.log(multiply): // ƒ multiply {}

Exportar desde otros archivos con alias

De igual forma que antes podemos utilizar alias para exportar y renombrar.

export {
  default as plus,
  multiply
} from './calculator'

Ahora que nuestros default pasaron a ser named, es necesario importarlos con ese nuevo nombre:

import { plus, multiply } from './operations-alias'

console.log(plus); // ƒ add() {}
console.log(multiply): // ƒ multiply {}

Importar con alias

Es posible también agregar un alias al momento de importar.

import { plus as suma, multiply as multiplicar } from './operations-alias'

Esto es útil cuando importamos métodos con el mismo nombre que vengan de distintos archivos. A continuación 2 métodos con el mismo nombre pero en distintos archivos:

export getAge() {}
export getAge() {}

Ahora si queremos utilizarlos podemos asignarles un alias:

import { getAge as grandFatherAge } from './grandfather';
import { getAge as fatherAge } from './father';

console.log(grandFatherAge);
console.log(fatherAge);

Exportar todo

Es posible utilizar el comodín “*” para exportar todos los elementos, tomemos como ejemplo el siguiente archivo.

export function add(){
  // add something
}

export class Person {
  // class definition
}

export const PI = 3.1416;

export let car = {
  paintColor: 'red'
}

export default helloWorld(){
  // say hello
}

Y al momento de exportar solo necesitamos lo siguiente:

export * from './examples';

Al hacer un export con * , el método default no se exporta por lo que debe exportarse por separado.

– La comunidad PRO de JavaScript

Para exportar además el método default necesitamos lo siguiente:

export { default } from './examples';
export * from './examples';

En caso de existir más de un default es necesario utilizar los alias.

Importar todo

Al importar con * es necesario asignar un alias, este alias ahora será un objeto con todo lo importado (incluido el default):

import * as exampleMethods from './examples';

console.log(exampleMethods.add); // ƒ add(){}
console.log(exampleMethods.Person); // ƒ Person(){}
console.log(exampleMethods.PI); // 3.1416
console.log(exampleMethods.car); // { paintColor: 'red' }
console.log(exampleMethods.default); // ƒ helloWorld() {}

Es posible importar el default por separado, aunque de igual forma existirá en nuestro objeto:

import exampleDefault, * as exampleMethods from './examples';

console.log(exampleMethods.default); // ƒ helloWorld() {}
console.log(exampleDefault); // ƒ helloWorld() {}

Ahora si a andar desnudos por la casa

Ahora que sabes todas las formas de importar y exportar modulos, variables, etc. es hora de mostrarle al mundo que estas a punto de ser un ninja del Javascript o que ya eres un ninja avanzado.

Si te gusto el post o tienes alguna duda deja tu comentario y no olvides seguirme por el resto de redes sociales.

Un saludo 😀 y nos vemos en la siguiente publicación.

Categorías
Desarrollo y Programación

Mis herramientas de desarrollo en Mac

De nuevo le hice una instalación de sistema operativo a mi iMac (19D76) para actualizar a la versión 10.15 MacOS Catalina.

Así que en esta ocasión les compartiré todas las aplicaciones que instalo al año 2020 para mi trabajo como desarrollador web y aplicaciones.

Instalar MacOS Catalina desde un USB

Se requiere tener una USB de 16Gb para crear el instalador, para crear la usb mágica seguir el tutorial oficial de Apple aquí.

La instalación es un proceso sencillo, pero el resto toma tiempo de descarga, de buscar y personalizar herramientas.

Instalar XCode Mandatorio

Para herramientas de desarrollo como Git y comandos como CURL o WGET necesitamos una extensión para la terminal, además de otras librerías. Instalar Xcode es la opción más sencilla y más pesada, así que mientras instala sugiero ver o leer algo que no consuma internet.

Necesitamos abrir Xcode al menos una vez para aceptar los términos y generar la licencia.

Habilitar la instalación de cualquier aplicación en Mac

Aplicaciones de terceros no son permitidas en Mac desde la versión 10.13, para habilitarlas necesitamos un comando en la terminal

sudo spctl --master-disable

La terminal definitiva

La terminal que viene con el Mac tiene muchas cualidades pero si queremos sacarle jugo debemos optar por la iTerm Terminal

Esteroides adicionales a la terminal

Ahora que tenemos iTerm Terminal, podemos trabajar libremente con bash, o meterle más potencia y trabajar con zsh, para más placer vamos a instalar OhMyzsh.

Gestor de Paquetes

Si has desarrollado ultimamente conocerás cosas como NPM, Yarn, Maven, Composer, etc. Bueno pues para Mac existe Brew: un gestor de paquetes que hace lo mismo pero para utilidades de desarrollo, desde Git hasta MySQL.

Este paquete además instala los Command Line Tools de Xcode

Un IDE para controlarlos a todos

Aquí todo depende de tus gustos, así que cualquier IDE que te acomode es el mejor para instalar, en mi caso utilizo los de Jetbrains, con su herramienta Toolbox, solo es elegir la aplicación requerida e instalar.

Control de versiones con Git + Sourcetree

El control de versiones lo hago con línea de comandos, pero cuando tenemos prisa podemos cometer errores que no se pueden ver tan fácilmente, para verlos recomiendo Sourcetree que nos facilita algunas tareas.

Chrome el mejor Navegador para Mac

Por supuesto google chrome es el navegador definitivo para Mac, Safari tiene unas herramientas de desarrollo complicadas, Firefox tiene errores con atajos de teclado y otros tienen una pésima compatibilidad

Y es todo por ahora

A partir de aquí depende en que tecnología vas a desarrollar pues las aplicaciones varían para un Nativo iOS, Android, o un react-native, PHP, angular, etc.

Y ustedes ¿Qué herramientas utilizan? dejenla en los comentarios.

Categorías
Desarrollo y Programación

React dar formato a números

Hola, bienvenidos a otro tutorial en esta ocasión con React a dar formato a un número para mostrarlo en pantalla.

Vamos a trabajar en el aspecto visual deseado sin necesidad de cambiar el dato original, es decir meramente vamos a trabajar con la estética del número.

Este material está basado en la información que encontré en este hilo de Stackoverflow.

Para esto dejo el siguiente videotutorial, espero que les sea útil como material de apoyo.

Además dejo el código final en la parte de abajo para que revisen si algo no funciona como debe.

import React from "react";
import "./App.css";
function FormatNumber({ number }) {
return (
<span style={{ color: "red" }}>
{new Intl.NumberFormat("ES-MX", {
style: "currency",
currency: "MXN"
}).format(number)}
</span>
);
}
class App extends React.Component {
state = {
number: 0
};
handleChange = event => {
this.setState({
number: event.target.value > 999999999 ? 999999999 : event.target.value,
});
};
render() {
const { number } = this.state;
return (
<div className="App">
<h1>
Hola dinero <FormatNumber number={number} />
</h1>
<input type="number" onChange={this.handleChange} />
</div>
);
}
}
export default App;

Pueden dejar sus dudas o comentarios en está publicación o en el video, nos leemos en el siguiente tutorial.

Feliz día a todos 😄

Referencias

Categorías
Desarrollo y Programación

Como hacer peticiones http en PHP sin CURL

Vamos a hacer peticiones a servicios http o APIs con PHP sin CURL, este último muchas veces está bloqueado por el hosting y no es posible hacer peticiones a enlaces externos.

Vamos a utilizar la librería Requests for PHP en nuestro entorno de desarrollo local, así que es importante tener el manejador de dependencias: composer.

Instalación de Requests

Para instalar la librería es necesario ejecutar el siguiente comando:

composer require "rmccue/requests"

Nuestro composer.json debería verse como la siguiente imagen

composer.json (ejemplo)

Así debería lucir el árbol de dependencias y archivos:

Dependencias

Peticiones HTTP Get con PHP

Y listo a partir de ahora podemos solicitar datos a servicios y APIs externos, yo tuve esta necesidad pues algunos servicios de los que consumo no permiten solicitudes desde el browser.

<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$url = 'https://jsonplaceholder.typicode.com/posts';
$response = Requests::get($url);
## $response->body es el resultado de la petición
echo(json_encode($response));
view raw httpGetRequest.php hosted with ❤ by GitHub

Peticiones HTTP Post con PHP

Si queremos enviar datos, debemos colocarlos dentro de un array. Es importante conocer el tipo de envío que debemos hacer en post, ya sea para un multipart/form-data o un application/json.

Este dato debemos revisarlo con el proveedor del servicio, si es necesario enviar llaves de autenticación u otro dato en las cabeceras, podemos agregar este dato en otro array.

<?php
include('vendor/rmccue/requests/library/Requests.php');
Requests::register_autoloader();
$url = 'https://jsonplaceholder.typicode.com/posts';
$postData = array([
'title' => 'Hola Mundo',
'body' => 'Este es un ejemplo de envio con POST',
'userId' => 1,
]);
$headers = array([
'Content-type' => 'application/json; charset=UTF-8'
]);
$responsePost = Requests::post($url, null, $postData);
echo json_encode($responsePost);
view raw httpPostRequest.php hosted with ❤ by GitHub

Peticiones HTTP PUT, PATCH y DELETE con PHP

El resto de peticiones se pueden hacer con los métodos:

Requests::put($url, $headers, $data, $options);
Requests::patch($url, $headers, $data, $options);
Requests::delete($url, $headers, $options);

Status Code y Headers de Peticiones HTTP con PHP

Para obtener el codigo de estado se obtiene de la variable de respuesta:

$response->status_code

En el caso de la cabecera es necesario agregar el nombre de la cabecera requerida. NOTA: no distingue entre mayusculas y minusculas

$response->headers['Date'];

Comentarios Finales

Esta por demás decirlo, pero siempre que importen la librería al proyecto es necesario subirla a su host para que funcione, así que la carpeta vendor ahora debería estar incluida en el servidor.

Las cabeceras de autenticación se envían en el array de $headers, pero se debe consultar con el proveedor del servicio cuales se deben enviar.

Y listo ya no es necesario preocuparse por que el servidor tenga soporte para CURL, que tengan felices proyectos y que todo vaya sin bugs, un Saludo afectuoso y nos vemos en el siguiente tutorial.

Categorías
Desarrollo y Programación

Sumar Radio button con Javascript

Este problema lo obtuve de los foros de cristalab del usuario mariassssss, el usuario busca sumar los valores de unos input radio con javascript:

Aquí el post original: http://foros.cristalab.com/javascrip-t122822/

Me tomé la libertad de corregir el codigo, quitar las funciones que no estaban en uso y hacer la operación que necesita sin moverle mucho.

<html>
<head>
<title>CAFETERIA</title>
<meta charset="utf-8" />
<style>
body {
background-color: #e1e637;
}
h1 {
color: #ff090e;
}
legend {
margin-top: 20px;
margin-bottom: 10px;
}
</style>
</head>
<body>
<h1>CAFETERIA</h1>
<form>
<legend>SELECCIONE EL PLATO PRINCIPAL</legend>
<input type="radio" id="n1" name="principal" value="12" /> Caldo de pollo
Q12.00 <br /><br />
<input type="radio" id="n2" name="principal" value="20" /> pescado frito
Q20.00<br /><br />
<input type="radio" id="n3" name="principal" value="25" /> revolcado
Q25.00<br /><br />
<legend>SELECCIONE SU BEBIDA</legend>
<input type="radio" id="n4" name="bebida" value="7" /> CocaCola Q7.OO<br /><br />
<input type="radio" id="n5" name="bebida" value="4" /> Jamaica Q4.00<br /><br />
<input type="radio" id="n6" name="bebida" value="5" /> Sprite Q5.00<br /><br />
<legend>SELECCIONE SU POSTRE</legend>
<input type="radio" id="n7" name="postre" value="7" /> Pastel de fresa
Q7.oo<br /><br />
<input type="radio" id="n8" name="postre" value="5" /> Helado de Chocolate
Q5<br /><br />
<input type="radio" id="n9" name="postre" value="9" /> Coctel de frutas
Q9.00<br /><br />
<button>Obtener TOTAL</button>
</form>
<script>
// buscar el <form> y guardarlo en una variable
const form = document.querySelector('form');
// decir que en el evento enviar se sume el total
form.addEventListener('submit', obtenerTotal);
function obtenerTotal(event) {
// evitar enviar el formulario que ocasiona que se refresque la pagina
event.preventDefault();
// obtener todos los input radio
const formData = new FormData(event.target);
// convertir los valores a String, o colocar un 0 si no elegieron algo
const principal = parseInt(formData.get('principal') || '0', 10);
const bebida = parseInt(formData.get('bebida') || '0', 10);
const postre = parseInt(formData.get('postre') || '0', 10);
const result = principal + bebida + postre;
alert("la suma es:" + result);
}
</script>
</body>
</html>

A diferencia del código original no es necesario ir a recuperar el valor por input, si no obtener todo el formulario y sacar los valores necesarios.

Es algo primitivo pero este formData estaría listo para enviar a en una request y obtener los datos a partir de este elemento y sus correspondientes names.

Entre las mejoras se puede poner un array para obtener los datos requeridos, pero como no estaba la problemática descrita, pues decidí omitir.

Categorías
Desarrollo y Programación

WebStorm Color Themes – base16 [2019]

Que tal coders, en esta ocasión voy a compartir mi tema de color para el editor WebStorm, reciente el editor entró en la versión 2019.2 cambiando ajustes.

Estos ajustes ahora permiten establecer colores para otras variables, sintaxis y palabras reservadas.

Javascript Class

Mi tema esta basado en los colores de Base16 que pueden encontrar aquí http://chriskempson.com/projects/base16/ y he cambiado mayormente los colores para trabajar con Javascript y react.js

ReactJS Component

Quizá no se vea tan bien como otros temas o schemes pero está listo para trabajar con pantallas muy brillantes, donde a veces el color parece que va a incendiar las pupilas

Node JS

Sin más aquí dejo el enlace al archivo:

Si por alguna razón no funciona, también lo dejo en Google drive:

https://drive.google.com/file/d/1Ef9_o5d2yXP5n7XCncKZs_u5BHs0qfUP/view?usp=sharing

Cómo importar Webstorm color themes

Para importar este o cualquier otro tema, necesitan un archivo *.icls para poder importarlo. Después ir a Archivo > Preferencias > Editor > Color Scheme

Webstorm 2019.x Preferences

Elegir la opción Import Scheme… del icono de configuración, para finalizar elegir el archivo, aplicar y aceptar los cambios. Y listo 😄

Si tienen algún ajuste para cambiar o mejorar el tema compartanlo en los comentarios. Muchas gracias y nos vemos en el siguiente post.

Categorías
Desarrollo y Programación

jQuery mostrar y ocultar div con animación

En esta ocasión vamos a mostrar y ocultar div con jQuery para practicar el funcionamiento base de la librería. vamos a asignar eventos a dos botones que nos permitan interactuar con la visualización de un componente.

En esta ocasión traigo la actualización de un código que hice hace unos siete años para este blog, el cual hice un tutorial en youtube:

El código completo y funcional está aquí:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Tutorial jQuery Remasterizado</title>
<script src="http://code.jquery.com/jquery-1.8.0.min.js"></script>
<script>
var pagina = $(document);
pagina.on("ready", animar);
function animar() {
var x = $("#mostrar_elemento");
x.on("click", mostrar);
var y = $("#ocultar_elemento");
y.on("click", ocultar);
}
function mostrar() {
var x = $("div");
x.show("slow");
}
function ocultar() {
var x = $("div");
x.hide("slow");
}
</script>
<style>
.ocultado {
display: none;
background-color: #9c0;
border-color: #063;
border-style: dotted;
border: thin;
width: 200px;
height: 200px;
}
</style>
</head>
<body>
<input id="mostrar_elemento" type="button" value="Mostrar mensaje" />
<input id="ocultar_elemento" type="button" value="Ocultar" />
<div class="ocultado">
Esta div se esta mostrando sin embargo puede ser cualquier elemento
</div>
</body>
</html>
view raw jquery01.html hosted with ❤ by GitHub

Refactorizar código Javascript

Ahora también tenemos una actualización de un refactor que pueden ver en el siguiente video:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Tutorial jQuery Remasterizado</title>
<link href="style.css" rel="stylesheet">
</head>
<body>
<button id="showContainer" type="button">Mostrar mensaje</button>
<button id="hideContainer" type="button">Ocultar mensaje</button>
<div class="container hidden">
Esta div se esta mostrando sin embargo puede ser cualquier elemento
</div>
<script
src="https://code.jquery.com/jquery-3.4.1.min.js"
integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
crossorigin="anonymous"
></script>
<script>
$(window).on("load", assignEvents);
function assignEvents() {
$("#showContainer").on("click", mostrar);
$("#hideContainer").on("click", ocultar);
}
function mostrar() {
$("div").show("slow");
}
function ocultar() {
$("div").hide("slow");
}
</script>
</body>
</html>
view raw index.html hosted with ❤ by GitHub
.container {
background-color: #9c0;
border-color: #063;
border-style: dotted;
border: thin;
width: 200px;
height: 200px;
}
.hidden {
display: none;
}
view raw style.css hosted with ❤ by GitHub

Este último video trata de seguir buenas prácticas para evitar el uso innecesario de variables y agregar nombres legibles a las clases e identificadores de HTML y Javascript.

Si tienen alguna duda ponganla en los comentarios 😎