Diego  Elizondo

Diego Elizondo

1657183140

Triple CCC: Curry, Cierre, Devolución De Llamada En JavaScript

JavaScript es un lenguaje de programación que se utiliza tanto en FrontEnd como en BackEnd para crear aplicaciones web interactivas. Es el único lenguaje escrito que el navegador puede entender. Hasta el momento, casi el 98% de los sitios web usan este lenguaje en el lado del cliente para el comportamiento de la página web. Es el lenguaje de programación más popular del mundo.

Pero el viaje de este idioma no fue tan fácil. Este lenguaje fue diseñado Brendan Eichy apareció por primera vez el 4 de diciembre de 1995. En un momento inicial, solo se usaba para brindar interactividad a las páginas web, mientras que HTML y CSS se usan para estructurar y diseñar la página web.

El momento de cambio de juego ocurre cuando Ryan Dahlse presenta NodeJS por primera vez en 2010. No es más que un entorno de tiempo de ejecución JavaScript back-end, multiplataforma y de código abierto que se ejecuta en el motor V8 y ejecuta el código JavaScript fuera de un navegador web.

Desde ese momento este lenguaje ha sido ampliamente utilizado. En 2022, vale la pena aprender este increíble idioma para construir una sólida carrera en el sector del desarrollo web. Para que su viaje de aprendizaje sea fluido y también para que su base sea sólida, hoy discutiré los conceptos de JavaScript, que son Currying, Closure y Callback (CCC).

¡No importa en qué posición estés ahora! Si desea convertirse en un buen desarrollador de JavaScript, debe tener una comprensión sólida de estos temas. Además, te ayudará a dividir las preguntas de la entrevista porque la mayoría de las veces hay una pregunta común que los entrevistadores hacen sobre estos temas. Al final de este tutorial, obtendrá una comprensión clara de Currying, Closure y Callback en JavaScript.

Cosas que aprenderás de este tutorial

Cubriremos los siguientes temas en este tutorial:

  • Funcionar como ciudadano de primera clase
  • Zurra
  • Cierre
  • Llamar de vuelta

Funcionar como ciudadano de primera clase

Antes de conocer los conceptos de la CCC, debe comprender el concepto de ciudadano de primera clase. En JavaScript, se dice que una función es un ciudadano de primera clase por las siguientes tres razones

  • Una función se puede asignar como valor a una variable
  • Una función se puede pasar como argumento a otras funciones
  • Una función puede ser devuelta por otra función

Echemos un vistazo a algunos fragmentos de código que muestran cómo una función en JavaScript puede satisfacer las tres razones anteriores.

Una función se puede asignar como valor a una variable

const myFunc = name => `Hello, ${name}! `;
const result = myFunc("Rahul");

console.log(result);
// Output: Hello, Rahul!

Aquí puede ver que hemos declarado una función de flecha y luego la hemos almacenado en una variable llamada myFunc.

Una función se puede pasar como argumento a otras funciones


const myFunc = (greetings,name) => `${greetings()}, ${name}! `;
const hello = () => "Hello"
const bonjour = () => "Bonjour"
const salut = () => "Salut"

const result_1 = myFunc(hello,"Rahul");
const result_2 = myFunc(bonjour,"Rahul");
const result_3 = myFunc(salut,"Rahul");

console.log(result_1);
console.log(result_2);
console.log(result_3);
// Output: 
// Hello, Rahul! 
// Bonjour, Rahul! 
// Salut, Rahul!

En lugar de codificar "Hola" en nuestra función myFunc, ahora aceptamos un parámetro que es una función. Como puede ver, hay tres funciones diferentes hello, bonjoury salutcada una de ellas se pasa como argumento amyFunc

Una función puede ser devuelta por otra función


const outerFunc = () => {
  console.log("Outer Function")
  const innerFunc = () =>{
    console.log("Inner Function")
  }
  return innerFunc
}

outerFunc()()
// OUTPUT
// Outer Function
// Inner Function

const myFunc = outerFunc()
myFunc()
myFunc()
// OUTPUT
// Outer Function
// Inner Function
// Inner Function

Tenemos una función llamada outerFunc. No hace mucho, simplemente imprime una declaración en la consola. innerFuncDentro se crea otra función llamada . El innerFunctampoco hace mucho, simplemente imprime una declaración en la consola. El outerFuncdevuelve el innerFunc.

Hay un par de maneras en que esto se puede usar. La primera forma es usar dos llaves juntas. El primer par de corchetes invoca outerFuncy el segundo par de corchetes invoca el objeto devuelto por outerFunc, es decir, la función innerFunc.

En la segunda forma, almacenamos la función devuelta en una variable y la invocamos como una función normal.

Zurra

En términos simples, Currying es una técnica de encadenar múltiples funciones. Es una función de programación funcional. Entendamos este concepto resolviendo una pregunta común de una entrevista:

La pregunta

Mire el fragmento de código a continuación.

function sum(x, y, z){
    return x + y + z
}

console.log(sum(10, 20, 30))
// Output: 60

La tarea que debe realizar es llamar a la función sum como sum(10)(20)(30) en lugar de sum(10, 20, 30) this.

// Current way of Invoking function
sum(10, 20, 30)// Desired way of Invoking function
sum(10)(20)(30)

¿Cómo puedes realizar esta acción? La respuesta es simple, el término que debe usar es Currying. Vea el siguiente ejemplo de código


function sum(x){
    return function(y){
        return function(z){
            return x + y + z
        }
    }
}

console.log(sum(10)(20)(30))
// Output: 60

Aquí puedes ver que hemos declarado una función dentro de otra y estas han creado un encadenamiento de funciones. También puede ver que estamos obteniendo exactamente el mismo resultado y este proceso se conoce como Currying en JavaScript.

Currying se usa en bibliotecas javascript populares como Lodash y Rambda

Cierre

Un cierre en JavaScript no es más que una función que hace referencia a variables en el ámbito externo desde su ámbito interno. Veamos el problema que resuelve el cierre en la siguiente sección y, al hacerlo, podrá saber por qué necesitamos

function sayHello(){
    let name = 'Rahul'
    function inner(){
        console.log(`Hello ${name}`)
    }
    return inner
}

let abc = sayHello()
console.log(abc)
// Output: 
// [Function: inner]
// Hello Rahul

Aquí, puede ver que estamos obteniendo el resultado esperado. Pero la pregunta principal es ¿cómo estamos consiguiendo esto? Vamos a desglosarlo en la siguiente sección:

Al principio, declaramos una función nombrada sayHello()y almacenamos una cadena dentro de la namevariable. Más tarde, declaramos otra función e imprimimos el nombre con un Hellomensaje, y devolvimos la inner()función. Finalmente, hemos almacenado la función devuelta en la abcvariable.

Ahora, cuando JavaScript ejecute el código, no encontrará la namevariable ya que la sayHello()memoria de la función ha sido destruida. Pero, ¿cómo estamos obteniendo el resultado esperado?

La razón principal detrás de esto es que Closure. Aquí, es cierto que la sayHello()memoria de la función ha sido destruida pero crea una referencia de esa función y como resultado, mientras ejecuta inner()puede acceder a la variable desde la referencia de la sayHello()función. Para realizar esta acción, no necesita escribir una línea de código adicional. Porque el motor de JavaScript es lo suficientemente inteligente como para realizar esta acción. Todo lo que necesita hacer es comprender el concepto de cierre y se crea de forma predeterminada cada vez que se crea una función en JavaScript.

Llamar de vuelta

Una devolución de llamada es una función que se pasa como argumento a otra función. Veamos un caso de uso a continuación.

Supongamos que tenemos una matriz de nombres guardados en nuestra base de datos. Queremos agregar un nuevo nombre y luego, queremos imprimir los nombres con el nombre recién agregado. Para realizar esta acción hemos escrito el siguiente código:

let names = ['Rahul','Rohit','Rohan']
function addNewName(name){
    setTimeout(function(){
        names.push(name)
    },5000)
}
function printNames(){
    setTimeout(function(){
        console.log(names)
    },3000)
}

addNewName('Alex')
printNames()
// Output:
// [ 'Rahul', 'Rohit', 'Rohan' ]

Aquí puede ver que hemos agregado la funcionalidad para agregar nuevos nombres, pero en la salida, el nuevo nombre no se ha agregado. La razón principal detrás de esto es el asynchronouscomportamiento de JavaScript. Sabemos que para las tareas que toman mucho tiempo, JavaScript no las espera, sino que trabajan en otras tareas más livianas y mantienen la tarea pesada en la cola. Aquí pasan las mismas cosas.

Necesitamos usar una función de devolución de llamada para que podamos romper el asynchronouscomportamiento de JavaScript y pueda esperarnos en función de una tarea específica. Vea el siguiente ejemplo de código para entenderlo más claramente:


let names = ['Rahul','Rohit','Rohan']
function addNewName(name, cb){
    setTimeout(function(){
        names.push(name)
        cb()
    },5000)
}
function printNames(){
    setTimeout(function(){
        console.log(names)
    },3000)
}
addNewName('Alex',printNames)
// Output:
// [ 'Rahul', 'Rohit', 'Rohan', 'Alex' ]

Hemos pasado una función (printNames) como argumento a otra función (addNewName). Esta vez printNamesse ejecutará solo después de que se hayan ejecutado las funciones anteriores. Este concepto se conoce como devolución de llamada y puede ver que hemos llamado a esta función después de que la función anterior terminó sus tareas. Esa es la razón por la que hemos mencionado Devolución de llamada como Llamada más adelante.

Hay muchos conceptos avanzados que se han construido sobre Callback. Es posible que también haya oído hablar del concepto de Callback hell. Hablaré de esto en uno de los próximos artículos.

Conclusión

En este tutorial, hemos cubierto tres conceptos esenciales de JavaScript (Currying, Closure y Callback). Espero que hayas encontrado este artículo útil e informativo.

Fuente: https://betterprogramming.pub/the-concept-of-triple-ccc-currying-closure-callback-in-javascript-47da06df9bb4

#javascript 

What is GEEK

Buddha Community

Triple CCC: Curry, Cierre, Devolución De Llamada En JavaScript

Comment créer une application de traduction de langue en HTML CSS et JavaScript

Dans ce guide, vous apprendrez à créer une application de traduction de langue en HTML CSS et JavaScript.

Pour créer cette application de traduction de langue en JavaScript. Tout d'abord, vous devez créer quatre fichiers : fichiers HTML, CSS et JavaScript.

1 : Tout d'abord, créez un fichier HTML avec le nom index.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">  
    <title>Language Translator | Codequs</title>
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Font Awesome CDN Link for Icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"/>
  </head>
  <body>
    <div class="container">
      <div class="wrapper">
        <div class="text-input">
          <textarea spellcheck="false" class="from-text" placeholder="Enter text"></textarea>
          <textarea spellcheck="false" readonly disabled class="to-text" placeholder="Translation"></textarea>
        </div>
        <ul class="controls">
          <li class="row from">
            <div class="icons">
              <i id="from" class="fas fa-volume-up"></i>
              <i id="from" class="fas fa-copy"></i>
            </div>
            <select></select>
          </li>
          <li class="exchange"><i class="fas fa-exchange-alt"></i></li>
          <li class="row to">
            <select></select>
            <div class="icons">
              <i id="to" class="fas fa-volume-up"></i>
              <i id="to" class="fas fa-copy"></i>
            </div>
          </li>
        </ul>
      </div>
      <button>Translate Text</button>
    </div>
    <script src="js/countries.js"></script>
    <script src="js/script.js"></script>
  </body>
</html>

2 : Deuxièmement, créez un fichier CSS avec le nom de style.css

/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  min-height: 100vh;
  background: #5372F0;
}
.container{
  max-width: 690px;
  width: 100%;
  padding: 30px;
  background: #fff;
  border-radius: 7px;
  box-shadow: 0 10px 20px rgba(0,0,0,0.01);
}
.wrapper{
  border-radius: 5px;
  border: 1px solid #ccc;
}
.wrapper .text-input{
  display: flex;
  border-bottom: 1px solid #ccc;
}
.text-input .to-text{
  border-radius: 0px;
  border-left: 1px solid #ccc;
}
.text-input textarea{
  height: 250px;
  width: 100%;
  border: none;
  outline: none;
  resize: none;
  background: none;
  font-size: 18px;
  padding: 10px 15px;
  border-radius: 5px;
}
.text-input textarea::placeholder{
  color: #b7b6b6;
}
.controls, li, .icons, .icons i{
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.controls{
  list-style: none;
  padding: 12px 15px;
}
.controls .row .icons{
  width: 38%;
}
.controls .row .icons i{
  width: 50px;
  color: #adadad;
  font-size: 14px;
  cursor: pointer;
  transition: transform 0.2s ease;
  justify-content: center;
}
.controls .row.from .icons{
  padding-right: 15px;
  border-right: 1px solid #ccc;
}
.controls .row.to .icons{
  padding-left: 15px;
  border-left: 1px solid #ccc;
}
.controls .row select{
  color: #333;
  border: none;
  outline: none;
  font-size: 18px;
  background: none;
  padding-left: 5px;
}
.text-input textarea::-webkit-scrollbar{
  width: 4px;
}
.controls .row select::-webkit-scrollbar{
  width: 8px;
}
.text-input textarea::-webkit-scrollbar-track,
.controls .row select::-webkit-scrollbar-track{
  background: #fff;
}
.text-input textarea::-webkit-scrollbar-thumb{
  background: #ddd;
  border-radius: 8px;
}
.controls .row select::-webkit-scrollbar-thumb{
  background: #999;
  border-radius: 8px;
  border-right: 2px solid #ffffff;
}
.controls .exchange{
  color: #adadad;
  cursor: pointer;
  font-size: 16px;
  transition: transform 0.2s ease;
}
.controls i:active{
  transform: scale(0.9);
}
.container button{
  width: 100%;
  padding: 14px;
  outline: none;
  border: none;
  color: #fff;
  cursor: pointer;
  margin-top: 20px;
  font-size: 17px;
  border-radius: 5px;
  background: #5372F0;
}
@media (max-width: 660px){
  .container{
    padding: 20px;
  }
  .wrapper .text-input{
    flex-direction: column;
  }
  .text-input .to-text{
    border-left: 0px;
    border-top: 1px solid #ccc;
  }
  .text-input textarea{
    height: 200px;
  }
  .controls .row .icons{
    display: none;
  }
  .container button{
    padding: 13px;
    font-size: 16px;
  }
  .controls .row select{
    font-size: 16px;
  }
  .controls .exchange{
    font-size: 14px;
  }
}

3 : Troisièmement, créez un fichier JavaScript avec le nom de countries.js

 

const countries = {
    "am-ET": "Amharic",
    "ar-SA": "Arabic",
    "be-BY": "Bielarus",
    "bem-ZM": "Bemba",
    "bi-VU": "Bislama",
    "bjs-BB": "Bajan",
    "bn-IN": "Bengali",
    "bo-CN": "Tibetan",
    "br-FR": "Breton",
    "bs-BA": "Bosnian",
    "ca-ES": "Catalan",
    "cop-EG": "Coptic",
    "cs-CZ": "Czech",
    "cy-GB": "Welsh",
    "da-DK": "Danish",
    "dz-BT": "Dzongkha",
    "de-DE": "German",
    "dv-MV": "Maldivian",
    "el-GR": "Greek",
    "en-GB": "English",
    "es-ES": "Spanish",
    "et-EE": "Estonian",
    "eu-ES": "Basque",
    "fa-IR": "Persian",
    "fi-FI": "Finnish",
    "fn-FNG": "Fanagalo",
    "fo-FO": "Faroese",
    "fr-FR": "French",
    "gl-ES": "Galician",
    "gu-IN": "Gujarati",
    "ha-NE": "Hausa",
    "he-IL": "Hebrew",
    "hi-IN": "Hindi",
    "hr-HR": "Croatian",
    "hu-HU": "Hungarian",
    "id-ID": "Indonesian",
    "is-IS": "Icelandic",
    "it-IT": "Italian",
    "ja-JP": "Japanese",
    "kk-KZ": "Kazakh",
    "km-KM": "Khmer",
    "kn-IN": "Kannada",
    "ko-KR": "Korean",
    "ku-TR": "Kurdish",
    "ky-KG": "Kyrgyz",
    "la-VA": "Latin",
    "lo-LA": "Lao",
    "lv-LV": "Latvian",
    "men-SL": "Mende",
    "mg-MG": "Malagasy",
    "mi-NZ": "Maori",
    "ms-MY": "Malay",
    "mt-MT": "Maltese",
    "my-MM": "Burmese",
    "ne-NP": "Nepali",
    "niu-NU": "Niuean",
    "nl-NL": "Dutch",
    "no-NO": "Norwegian",
    "ny-MW": "Nyanja",
    "ur-PK": "Pakistani",
    "pau-PW": "Palauan",
    "pa-IN": "Panjabi",
    "ps-PK": "Pashto",
    "pis-SB": "Pijin",
    "pl-PL": "Polish",
    "pt-PT": "Portuguese",
    "rn-BI": "Kirundi",
    "ro-RO": "Romanian",
    "ru-RU": "Russian",
    "sg-CF": "Sango",
    "si-LK": "Sinhala",
    "sk-SK": "Slovak",
    "sm-WS": "Samoan",
    "sn-ZW": "Shona",
    "so-SO": "Somali",
    "sq-AL": "Albanian",
    "sr-RS": "Serbian",
    "sv-SE": "Swedish",
    "sw-SZ": "Swahili",
    "ta-LK": "Tamil",
    "te-IN": "Telugu",
    "tet-TL": "Tetum",
    "tg-TJ": "Tajik",
    "th-TH": "Thai",
    "ti-TI": "Tigrinya",
    "tk-TM": "Turkmen",
    "tl-PH": "Tagalog",
    "tn-BW": "Tswana",
    "to-TO": "Tongan",
    "tr-TR": "Turkish",
    "uk-UA": "Ukrainian",
    "uz-UZ": "Uzbek",
    "vi-VN": "Vietnamese",
    "wo-SN": "Wolof",
    "xh-ZA": "Xhosa",
    "yi-YD": "Yiddish",
    "zu-ZA": "Zulu"
}

4 : Enfin, créez un fichier JavaScript avec le nom de script.js

const fromText = document.querySelector(".from-text"),
toText = document.querySelector(".to-text"),
exchageIcon = document.querySelector(".exchange"),
selectTag = document.querySelectorAll("select"),
icons = document.querySelectorAll(".row i");
translateBtn = document.querySelector("button"),
selectTag.forEach((tag, id) => {
    for (let country_code in countries) {
        let selected = id == 0 ? country_code == "en-GB" ? "selected" : "" : country_code == "hi-IN" ? "selected" : "";
        let option = `<option ${selected} value="${country_code}">${countries[country_code]}</option>`;
        tag.insertAdjacentHTML("beforeend", option);
    }
});
exchageIcon.addEventListener("click", () => {
    let tempText = fromText.value,
    tempLang = selectTag[0].value;
    fromText.value = toText.value;
    toText.value = tempText;
    selectTag[0].value = selectTag[1].value;
    selectTag[1].value = tempLang;
});
fromText.addEventListener("keyup", () => {
    if(!fromText.value) {
        toText.value = "";
    }
});
translateBtn.addEventListener("click", () => {
    let text = fromText.value.trim(),
    translateFrom = selectTag[0].value,
    translateTo = selectTag[1].value;
    if(!text) return;
    toText.setAttribute("placeholder", "Translating...");
    let apiUrl = `https://api.mymemory.translated.net/get?q=${text}&langpair=${translateFrom}|${translateTo}`;
    fetch(apiUrl).then(res => res.json()).then(data => {
        toText.value = data.responseData.translatedText;
        data.matches.forEach(data => {
            if(data.id === 0) {
                toText.value = data.translation;
            }
        });
        toText.setAttribute("placeholder", "Translation");
    });
});
icons.forEach(icon => {
    icon.addEventListener("click", ({target}) => {
        if(!fromText.value || !toText.value) return;
        if(target.classList.contains("fa-copy")) {
            if(target.id == "from") {
                navigator.clipboard.writeText(fromText.value);
            } else {
                navigator.clipboard.writeText(toText.value);
            }
        } else {
            let utterance;
            if(target.id == "from") {
                utterance = new SpeechSynthesisUtterance(fromText.value);
                utterance.lang = selectTag[0].value;
            } else {
                utterance = new SpeechSynthesisUtterance(toText.value);
                utterance.lang = selectTag[1].value;
            }
            speechSynthesis.speak(utterance);
        }
    });
});

Vous avez maintenant créé avec succès un traducteur de langue en HTML CSS et JavaScript.

Cómo construir una aplicación de traducción de idiomas en HTML CSS y JavaScript

En esta guía, aprenderá a crear una aplicación de traducción de idiomas en HTML, CSS y JavaScript.

Para construir esta aplicación de traductor de idiomas en JavaScript. Primero, debe crear cuatro archivos: archivos HTML, CSS y JavaScript.

1: Primero, crea un archivo HTML con el nombre index.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">  
    <title>Language Translator | Codequs</title>
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Font Awesome CDN Link for Icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"/>
  </head>
  <body>
    <div class="container">
      <div class="wrapper">
        <div class="text-input">
          <textarea spellcheck="false" class="from-text" placeholder="Enter text"></textarea>
          <textarea spellcheck="false" readonly disabled class="to-text" placeholder="Translation"></textarea>
        </div>
        <ul class="controls">
          <li class="row from">
            <div class="icons">
              <i id="from" class="fas fa-volume-up"></i>
              <i id="from" class="fas fa-copy"></i>
            </div>
            <select></select>
          </li>
          <li class="exchange"><i class="fas fa-exchange-alt"></i></li>
          <li class="row to">
            <select></select>
            <div class="icons">
              <i id="to" class="fas fa-volume-up"></i>
              <i id="to" class="fas fa-copy"></i>
            </div>
          </li>
        </ul>
      </div>
      <button>Translate Text</button>
    </div>
    <script src="js/countries.js"></script>
    <script src="js/script.js"></script>
  </body>
</html>

2: Segundo, crea un archivo CSS con el nombre de style.css

/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  min-height: 100vh;
  background: #5372F0;
}
.container{
  max-width: 690px;
  width: 100%;
  padding: 30px;
  background: #fff;
  border-radius: 7px;
  box-shadow: 0 10px 20px rgba(0,0,0,0.01);
}
.wrapper{
  border-radius: 5px;
  border: 1px solid #ccc;
}
.wrapper .text-input{
  display: flex;
  border-bottom: 1px solid #ccc;
}
.text-input .to-text{
  border-radius: 0px;
  border-left: 1px solid #ccc;
}
.text-input textarea{
  height: 250px;
  width: 100%;
  border: none;
  outline: none;
  resize: none;
  background: none;
  font-size: 18px;
  padding: 10px 15px;
  border-radius: 5px;
}
.text-input textarea::placeholder{
  color: #b7b6b6;
}
.controls, li, .icons, .icons i{
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.controls{
  list-style: none;
  padding: 12px 15px;
}
.controls .row .icons{
  width: 38%;
}
.controls .row .icons i{
  width: 50px;
  color: #adadad;
  font-size: 14px;
  cursor: pointer;
  transition: transform 0.2s ease;
  justify-content: center;
}
.controls .row.from .icons{
  padding-right: 15px;
  border-right: 1px solid #ccc;
}
.controls .row.to .icons{
  padding-left: 15px;
  border-left: 1px solid #ccc;
}
.controls .row select{
  color: #333;
  border: none;
  outline: none;
  font-size: 18px;
  background: none;
  padding-left: 5px;
}
.text-input textarea::-webkit-scrollbar{
  width: 4px;
}
.controls .row select::-webkit-scrollbar{
  width: 8px;
}
.text-input textarea::-webkit-scrollbar-track,
.controls .row select::-webkit-scrollbar-track{
  background: #fff;
}
.text-input textarea::-webkit-scrollbar-thumb{
  background: #ddd;
  border-radius: 8px;
}
.controls .row select::-webkit-scrollbar-thumb{
  background: #999;
  border-radius: 8px;
  border-right: 2px solid #ffffff;
}
.controls .exchange{
  color: #adadad;
  cursor: pointer;
  font-size: 16px;
  transition: transform 0.2s ease;
}
.controls i:active{
  transform: scale(0.9);
}
.container button{
  width: 100%;
  padding: 14px;
  outline: none;
  border: none;
  color: #fff;
  cursor: pointer;
  margin-top: 20px;
  font-size: 17px;
  border-radius: 5px;
  background: #5372F0;
}
@media (max-width: 660px){
  .container{
    padding: 20px;
  }
  .wrapper .text-input{
    flex-direction: column;
  }
  .text-input .to-text{
    border-left: 0px;
    border-top: 1px solid #ccc;
  }
  .text-input textarea{
    height: 200px;
  }
  .controls .row .icons{
    display: none;
  }
  .container button{
    padding: 13px;
    font-size: 16px;
  }
  .controls .row select{
    font-size: 16px;
  }
  .controls .exchange{
    font-size: 14px;
  }
}

3: Tercero, crea un archivo JavaScript con el nombre de countries.js

 

const countries = {
    "am-ET": "Amharic",
    "ar-SA": "Arabic",
    "be-BY": "Bielarus",
    "bem-ZM": "Bemba",
    "bi-VU": "Bislama",
    "bjs-BB": "Bajan",
    "bn-IN": "Bengali",
    "bo-CN": "Tibetan",
    "br-FR": "Breton",
    "bs-BA": "Bosnian",
    "ca-ES": "Catalan",
    "cop-EG": "Coptic",
    "cs-CZ": "Czech",
    "cy-GB": "Welsh",
    "da-DK": "Danish",
    "dz-BT": "Dzongkha",
    "de-DE": "German",
    "dv-MV": "Maldivian",
    "el-GR": "Greek",
    "en-GB": "English",
    "es-ES": "Spanish",
    "et-EE": "Estonian",
    "eu-ES": "Basque",
    "fa-IR": "Persian",
    "fi-FI": "Finnish",
    "fn-FNG": "Fanagalo",
    "fo-FO": "Faroese",
    "fr-FR": "French",
    "gl-ES": "Galician",
    "gu-IN": "Gujarati",
    "ha-NE": "Hausa",
    "he-IL": "Hebrew",
    "hi-IN": "Hindi",
    "hr-HR": "Croatian",
    "hu-HU": "Hungarian",
    "id-ID": "Indonesian",
    "is-IS": "Icelandic",
    "it-IT": "Italian",
    "ja-JP": "Japanese",
    "kk-KZ": "Kazakh",
    "km-KM": "Khmer",
    "kn-IN": "Kannada",
    "ko-KR": "Korean",
    "ku-TR": "Kurdish",
    "ky-KG": "Kyrgyz",
    "la-VA": "Latin",
    "lo-LA": "Lao",
    "lv-LV": "Latvian",
    "men-SL": "Mende",
    "mg-MG": "Malagasy",
    "mi-NZ": "Maori",
    "ms-MY": "Malay",
    "mt-MT": "Maltese",
    "my-MM": "Burmese",
    "ne-NP": "Nepali",
    "niu-NU": "Niuean",
    "nl-NL": "Dutch",
    "no-NO": "Norwegian",
    "ny-MW": "Nyanja",
    "ur-PK": "Pakistani",
    "pau-PW": "Palauan",
    "pa-IN": "Panjabi",
    "ps-PK": "Pashto",
    "pis-SB": "Pijin",
    "pl-PL": "Polish",
    "pt-PT": "Portuguese",
    "rn-BI": "Kirundi",
    "ro-RO": "Romanian",
    "ru-RU": "Russian",
    "sg-CF": "Sango",
    "si-LK": "Sinhala",
    "sk-SK": "Slovak",
    "sm-WS": "Samoan",
    "sn-ZW": "Shona",
    "so-SO": "Somali",
    "sq-AL": "Albanian",
    "sr-RS": "Serbian",
    "sv-SE": "Swedish",
    "sw-SZ": "Swahili",
    "ta-LK": "Tamil",
    "te-IN": "Telugu",
    "tet-TL": "Tetum",
    "tg-TJ": "Tajik",
    "th-TH": "Thai",
    "ti-TI": "Tigrinya",
    "tk-TM": "Turkmen",
    "tl-PH": "Tagalog",
    "tn-BW": "Tswana",
    "to-TO": "Tongan",
    "tr-TR": "Turkish",
    "uk-UA": "Ukrainian",
    "uz-UZ": "Uzbek",
    "vi-VN": "Vietnamese",
    "wo-SN": "Wolof",
    "xh-ZA": "Xhosa",
    "yi-YD": "Yiddish",
    "zu-ZA": "Zulu"
}

4: Por último, cree un archivo JavaScript con el nombre de script.js

const fromText = document.querySelector(".from-text"),
toText = document.querySelector(".to-text"),
exchageIcon = document.querySelector(".exchange"),
selectTag = document.querySelectorAll("select"),
icons = document.querySelectorAll(".row i");
translateBtn = document.querySelector("button"),
selectTag.forEach((tag, id) => {
    for (let country_code in countries) {
        let selected = id == 0 ? country_code == "en-GB" ? "selected" : "" : country_code == "hi-IN" ? "selected" : "";
        let option = `<option ${selected} value="${country_code}">${countries[country_code]}</option>`;
        tag.insertAdjacentHTML("beforeend", option);
    }
});
exchageIcon.addEventListener("click", () => {
    let tempText = fromText.value,
    tempLang = selectTag[0].value;
    fromText.value = toText.value;
    toText.value = tempText;
    selectTag[0].value = selectTag[1].value;
    selectTag[1].value = tempLang;
});
fromText.addEventListener("keyup", () => {
    if(!fromText.value) {
        toText.value = "";
    }
});
translateBtn.addEventListener("click", () => {
    let text = fromText.value.trim(),
    translateFrom = selectTag[0].value,
    translateTo = selectTag[1].value;
    if(!text) return;
    toText.setAttribute("placeholder", "Translating...");
    let apiUrl = `https://api.mymemory.translated.net/get?q=${text}&langpair=${translateFrom}|${translateTo}`;
    fetch(apiUrl).then(res => res.json()).then(data => {
        toText.value = data.responseData.translatedText;
        data.matches.forEach(data => {
            if(data.id === 0) {
                toText.value = data.translation;
            }
        });
        toText.setAttribute("placeholder", "Translation");
    });
});
icons.forEach(icon => {
    icon.addEventListener("click", ({target}) => {
        if(!fromText.value || !toText.value) return;
        if(target.classList.contains("fa-copy")) {
            if(target.id == "from") {
                navigator.clipboard.writeText(fromText.value);
            } else {
                navigator.clipboard.writeText(toText.value);
            }
        } else {
            let utterance;
            if(target.id == "from") {
                utterance = new SpeechSynthesisUtterance(fromText.value);
                utterance.lang = selectTag[0].value;
            } else {
                utterance = new SpeechSynthesisUtterance(toText.value);
                utterance.lang = selectTag[1].value;
            }
            speechSynthesis.speak(utterance);
        }
    });
});

Ahora ha creado con éxito un traductor de idiomas en HTML CSS y JavaScript.

Cree Una Aplicación Meteorológica En HTML, CSS Y JavaScript

Hola amigos, hoy en este blog aprenderán a crear una aplicación meteorológica en HTML, CSS y JavaScript. En el blog anterior, compartí cómo obtener la ubicación de un usuario en JavaScript , y ahora es el momento de crear una aplicación meteorológica en JavaScript.

En esta aplicación meteorológica, puede obtener los detalles meteorológicos de una ciudad en particular ingresando el nombre de la ciudad o también puede obtener los detalles meteorológicos de su ubicación actual haciendo clic en el botón "Obtener ubicación del dispositivo". Si ingresó un nombre de ciudad no válido, se muestra un mensaje de error.

Obtendrá muchos detalles del clima en esta aplicación, como la temperatura en grados centígrados, las condiciones climáticas, la ubicación, la sensación y la humedad. Si tiene dificultades para entender lo que estoy diciendo, puede ver un video de demostración o un video tutorial completo de este proyecto (Aplicación del tiempo en JavaScript).

Espero que te haya gustado esta aplicación meteorológica y quieras obtener códigos fuente o archivos de la misma, pero no te preocupes, he proporcionado códigos y archivos al final de esta página y puedes copiar y pegar los códigos o descargar los archivos de codificación de forma gratuita. Antes de copiar los códigos, comprendamos los principales códigos y conceptos de esta aplicación meteorológica.

Ya les dije que usé JavaScript vainilla para crear esta aplicación meteorológica. En el archivo JavaScript, obtuve que el usuario ingresara el nombre de la ciudad y envié una solicitud de obtención a una API de OpenWeatherMap con el paso del nombre de la ciudad. Si el usuario hizo clic en el botón "Obtener ubicación del dispositivo", primero verifiqué que el navegador del usuario sea compatible con la API de geolocalización o no.

Si es compatible, obtuve la latitud y longitud actuales del dispositivo y envié estas coordenadas a la API de OpenWeatherMap. Después de obtener un objeto como respuesta de la API, mostré el valor de la propiedad en un elemento HTML en particular. Por último, utilizando el valor de identificación que nos proporciona la API, mostré el icono / imagen meteorológica personalizada de acuerdo con las condiciones meteorológicas.

Cree una aplicación meteorológica en JavaScript [códigos fuente]

Para crear este proyecto (Aplicación del tiempo en JavaScript). Primero, debe crear tres archivos: HTML, CSS y JavaScript. Después de crear estos archivos, simplemente pegue los siguientes códigos en su archivo. También puede descargar los archivos de código fuente de esta aplicación meteorológica desde el botón de descarga proporcionado.

Primero, cree un archivo HTML con el nombre de index.html y pegue los códigos dados en su archivo HTML. Debe crear un archivo con extensión .html y recordar que las imágenes que se utilizan en esta aplicación meteorológica no aparecerán. Así que descargue los archivos fuente para usar imágenes también.

<!DOCTYPE html>
<!-- Coding By CodingNepal - youtube.com/codingnepal -->
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">
    <title>Weather App in JavaScript | CodingNepal</title>
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Linking BoxIcon for Icon -->
    <link href='https://unpkg.com/boxicons@2.0.9/css/boxicons.min.css' rel='stylesheet'>
  </head>
  <body>
    <div class="wrapper">
      <header><i class='bx bx-left-arrow-alt'></i>Weather App</header>
      <section class="input-part">
        <p class="info-txt"></p>
        <div class="content">
          <input type="text" spellcheck="false" placeholder="Enter city name" required>
          <div class="separator"></div>
          <button>Get Device Location</button>
        </div>
      </section>
      <section class="weather-part">
        <img src="" alt="Weather Icon">
        <div class="temp">
          <span class="numb">_</span>
          <span class="deg">°</span>C
        </div>
        <div class="weather">_ _</div>
        <div class="location">
          <i class='bx bx-map'></i>
          <span>_, _</span>
        </div>
        <div class="bottom-details">
          <div class="column feels">
            <i class='bx bxs-thermometer'></i>
            <div class="details">
              <div class="temp">
                <span class="numb-2">_</span>
                <span class="deg">°</span>C
              </div>
              <p>Feels like</p>
            </div>
          </div>
          <div class="column humidity">
            <i class='bx bxs-droplet-half'></i>
            <div class="details">
              <span>_</span>
              <p>Humidity</p>
            </div>
          </div>
        </div>
      </section>
    </div>
    
    <script src="script.js"></script>

  </body>
</html>

En segundo lugar, cree un archivo CSS con el nombre style.css y pegue los códigos dados en su archivo CSS. Recuerde, debe crear un archivo con extensión .css.

@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 100vh;
  background: #43AFFC;
}
::selection{
  color: #fff;
  background: #43AFFC;
}
.wrapper{
  width: 400px;
  background: #fff;
  border-radius: 7px;
  box-shadow: 7px 7px 20px rgba(0, 0, 0, 0.05);
}
.wrapper header{
  display: flex;
  font-size: 21px;
  font-weight: 500;
  color: #43AFFC;
  padding: 16px 15px;
  align-items: center;
  border-bottom: 1px solid #ccc;
}
header i{
  font-size: 0em;
  cursor: pointer;
  margin-right: 8px;
}
.wrapper.active header i{
  margin-left: 5px;
  font-size: 30px;
}
.wrapper .input-part{
  margin: 20px 25px 30px;
}
.wrapper.active .input-part{
  display: none;
}
.input-part .info-txt{
  display: none;
  font-size: 17px;
  text-align: center;
  padding: 12px 10px;
  border-radius: 7px;
  margin-bottom: 15px;
}
.input-part .info-txt.error{
  color: #721c24;
  display: block;
  background: #f8d7da;
  border: 1px solid #f5c6cb;
}
.input-part .info-txt.pending{
  color: #0c5460;
  display: block;
  background: #d1ecf1;
  border: 1px solid #bee5eb;
}
.input-part :where(input, button){
  width: 100%;
  height: 55px;
  border: none;
  outline: none;
  font-size: 18px;
  border-radius: 7px;
}
.input-part input{
  text-align: center;
  padding: 0 15px;
  border: 1px solid #ccc;
}
.input-part input:is(:focus, :valid){
  border: 2px solid #43AFFC;
}
.input-part input::placeholder{
  color: #bfbfbf;
}
.input-part .separator{
  height: 1px;
  width: 100%;
  margin: 25px 0;
  background: #ccc;
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
}
.separator::before{
  content: "or";
  color: #b3b3b3;
  font-size: 19px;
  padding: 0 15px;
  background: #fff;
}
.input-part button{
  color: #fff;
  cursor: pointer;
  background: #43AFFC;
  transition: 0.3s ease;
}
.input-part button:hover{
  background: #1d9ffc;
}

.wrapper .weather-part{
  display: none;
  margin: 30px 0 0;
  align-items: center;
  justify-content: center;
  flex-direction: column;
}
.wrapper.active .weather-part{
  display: flex;
}
.weather-part img{
  max-width: 125px;
}
.weather-part .temp{
  display: flex;
  font-weight: 500;
  font-size: 72px;
}
.weather-part .temp .numb{
  font-weight: 600;
}
.weather-part .temp .deg{
  font-size: 40px;
  display: block;
  margin: 10px 5px 0 0;
}
.weather-part .weather{
  font-size: 21px;
  text-align: center;
  margin: -5px 20px 15px;
}
.weather-part .location{
  display: flex;
  font-size: 19px;
  padding: 0 20px;
  text-align: center;
  margin-bottom: 30px;
  align-items: flex-start;
}
.location i{
  font-size: 22px;
  margin: 4px 5px 0 0;
}
.weather-part .bottom-details{
  display: flex;
  width: 100%;
  justify-content: space-between;
  border-top: 1px solid #ccc;
}
.bottom-details .column{
  display: flex;
  width: 100%;
  padding: 15px 0;
  align-items: center;
  justify-content: center;
}
.column i{
  color: #5DBBFF;
  font-size: 40px;
}
.column.humidity{
  border-left: 1px solid #ccc;
}
.column .details{
  margin-left: 3px;
}
.details .temp, .humidity span{
  font-size: 18px;
  font-weight: 500;
  margin-top: -3px;
}
.details .temp .deg{
  margin: 0;
  font-size: 17px;
  padding: 0 2px 0 1px;
}
.column .details p{
  font-size: 14px;
  margin-top: -6px;
}
.humidity i{
  font-size: 37px;
}

Por último, cree un archivo JavaScript con el nombre de script.js y pegue los códigos dados en su archivo JavaScript. Debe crear un archivo con la extensión .js y recordar que debe pasar su clave API en la URL de la API, de lo contrario, esta aplicación meteorológica no funcionará y devolverá el error "algo salió mal". Puede obtener esta clave en el sitio oficial de OpenWeatherMap de forma gratuita.

const wrapper = document.querySelector(".wrapper"),
inputPart = document.querySelector(".input-part"),
infoTxt = inputPart.querySelector(".info-txt"),
inputField = inputPart.querySelector("input"),
locationBtn = inputPart.querySelector("button"),
weatherPart = wrapper.querySelector(".weather-part"),
wIcon = weatherPart.querySelector("img"),
arrowBack = wrapper.querySelector("header i");

let api;

inputField.addEventListener("keyup", e =>{
    if(e.key == "Enter" && inputField.value != ""){
        requestApi(inputField.value);
    }
});

locationBtn.addEventListener("click", () =>{
    if(navigator.geolocation){
        navigator.geolocation.getCurrentPosition(onSuccess, onError);
    }else{
        alert("Your browser not support geolocation api");
    }
});

function requestApi(city){
    api = `https://api.openweathermap.org/data/2.5/weather?q=${city}&units=metric&appid=your_api_key`;
    fetchData();
}

function onSuccess(position){
    const {latitude, longitude} = position.coords;
    api = `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&units=metric&appid=your_api_key`;
    fetchData();
}

function onError(error){
    infoTxt.innerText = error.message;
    infoTxt.classList.add("error");
}

function fetchData(){
    infoTxt.innerText = "Getting weather details...";
    infoTxt.classList.add("pending");
    fetch(api).then(res => res.json()).then(result => weatherDetails(result)).catch(() =>{
        infoTxt.innerText = "Something went wrong";
        infoTxt.classList.replace("pending", "error");
    });
}

function weatherDetails(info){
    if(info.cod == "404"){
        infoTxt.classList.replace("pending", "error");
        infoTxt.innerText = `${inputField.value} isn't a valid city name`;
    }else{
        const city = info.name;
        const country = info.sys.country;
        const {description, id} = info.weather[0];
        const {temp, feels_like, humidity} = info.main;

        if(id == 800){
            wIcon.src = "icons/clear.svg";
        }else if(id >= 200 && id <= 232){
            wIcon.src = "icons/storm.svg";  
        }else if(id >= 600 && id <= 622){
            wIcon.src = "icons/snow.svg";
        }else if(id >= 701 && id <= 781){
            wIcon.src = "icons/haze.svg";
        }else if(id >= 801 && id <= 804){
            wIcon.src = "icons/cloud.svg";
        }else if((id >= 500 && id <= 531) || (id >= 300 && id <= 321)){
            wIcon.src = "icons/rain.svg";
        }
        
        weatherPart.querySelector(".temp .numb").innerText = Math.floor(temp);
        weatherPart.querySelector(".weather").innerText = description;
        weatherPart.querySelector(".location span").innerText = `${city}, ${country}`;
        weatherPart.querySelector(".temp .numb-2").innerText = Math.floor(feels_like);
        weatherPart.querySelector(".humidity span").innerText = `${humidity}%`;
        infoTxt.classList.remove("pending", "error");
        infoTxt.innerText = "";
        inputField.value = "";
        wrapper.classList.add("active");
    }
}

arrowBack.addEventListener("click", ()=>{
    wrapper.classList.remove("active");
});

Eso es todo, ahora ha creado con éxito una aplicación meteorológica en HTML CSS y JavaScript. Si su código no funciona o ha enfrentado algún error / problema, descargue los archivos del código fuente desde el botón de descarga proporcionado. Es gratis y se descargará un archivo .zip, luego tendrá que extraerlo.

Después de extraer el archivo, abra el archivo JavaScript y pase su clave API en la URL de la API. Puede obtener esta clave en el sitio oficial de OpenWeatherMap de forma gratuita. También puede utilizar cualquier otra API de sitio para este proyecto. Si lo hace, debe modificar los códigos JavaScript en consecuencia.

https://www.codingnepalweb.com/build-weather-app-html-javascript/

#javascript #html 

Edwina  Namiiro

Edwina Namiiro

1649692800

A Plugin For Babel V6 That Transforms inline Styles Defined In JS

babel-plugin-css-in-js  

A plugin for Babel v6 which transforms inline styles defined in JavaScript modules into class names so they become available to, e.g. the className prop of React elements. While transforming, the plugin processes all JavaScript style definitions found and bundles them up into a CSS file, ready to be requested from your web server.

babel-plugin-css-in-js works seamlessly on both client and server. It has built-in support for media queries, pseudo-classes, attribute selectors, and theming. The plugin's options allow you to configure vendor-prefixing, minification, and class name compression.

If you're impatient, visit the live demo. The source code for it can be found in the example directory.

Example

In order for the plugin to work, in your components, surround each inline style specification with a module-level cssInJS() function call. This provides a hook for the plugin to process the first argument given to the call and then replace it with an object literal containing the resulting class names as values.

In

<Button className={styles.button} />

var styles = cssInJS({
  button: {
    padding: 5,
    backgroundColor: "blue"
  }
});

Out

JavaScript:

<Button className={styles.button} />

var styles = {
  button: "example_js_styles_button"
};

CSS:

.example_js_styles_button {
  padding: 5px;
  background-color: blue;
}

The stylesheet specification format is explained further down.

Note the return value of cssInJS(...) must be assigned to a variable. The name of the variable is used to distinguish multiple cssInJS calls within a file.

Installation

Install via npm:

$ npm install babel-plugin-css-in-js --save-dev

Usage

Via .babelrc (Recommended)

.babelrc

{
  "plugins": ["css-in-js"]
}

Via CLI

$ babel  --plugins css-in-js  script.js

Via Node API

require('babel-core').transform('code', {
  plugins: ['css-in-js']
});

Options

The plugin allows configuration of several parameters which control the generated CSS. You can pass options to the plugin by using a two-element array when adding the plugin. For instance, using .babelrc:

{
  "presets": [
    "es2015",
    "react"
  ],
  "plugins": [
    "foo-plugin",
    ["css-in-js", { "vendorPrefixes": true, "bundleFile": "public/bundle.css" }]
  ]
}

Available options:

OptionDefaultDescription
vendorPrefixesfalseIf true, the generated CSS is run through autoprefixer to add vendor prefixes to the rules. If set to an object, it is passed to autoprefixer as options argument.
minifyfalseSet to true to enable minification of the generated CSS. The popular clean-css package is used for this.
compressClassNamesfalseSet to true to shorten/obfuscate generated CSS class names. A class name like "my_file-my_styles_var-my_name" will so be converted to, e.g., "_bf".
mediaMap{}This allows you to define media query shortcuts which are expanded on building the CSS. Example: using { phone: "media only screen and (max-width: 640px)" } as value for this option and a stylesheet spec having "@phone" as a key, that key will be translated to @media only screen and (max-width: 640px) in the final CSS.
contextnullIf set to an object, each identifier found on the right-hand side of a style rule is substituted with the corresponding property value of this object. If set to a file path, the file is require'd and the exported object is used as stylesheet context.
cacheDirtmp/cache/If you set the compressClassNames option to true, the class name cache will be persisted in a file in this directory.
bundleFilebundle.cssAll generated CSS is bundled into this file.
identifiercssInJSThe name used for detecting inline styles to transform.
transformOptions{ presets: ['es2015'] }Babel options to use when passing a function as argument (instead of an object) to cssInJS().

Stylesheet Specification Format

Here's what you can put inside the parentheses of cssInJS(...).

Simple Styles

{
  myButton: {
    border: 'solid 1px #ccc',
    backgroundColor: 'lightgray',
    display: 'inline-block'
  },

  myInput: {
    width: '100%',
    // ... etc.
  }
}

An inline style is not specified as a string. Instead it is specified with an object whose properties form the CSS ruleset for that style. A property's key is the camelCased version of the rule name, and the value is the rule's value, usually a string.

There's also a shorthand notation for specifying pixel values, see this React tip for more details.

Pseudo-Classes and Attribute Selectors

{
  myButton: {
    border: 'solid 1px #ccc',
    backgroundColor: 'lightgray',
    display: 'inline-block',
    cursor: 'pointer',

    ':focus': {
      borderColor: '#aaa'
    },

    ':hover': {
      borderColor: '#ddd',

      ':active': {
        borderColor: '#eee'
      }
    },

    '[disabled]': {
      cursor: 'not-allowed',
      opacity: .5,

      ':hover': {
        backgroundColor: 'transparent'
      }
    }
  }
}

As you can see, pseudo-classes and attribute selectors can be nested arbitrarily deep. But you don't have to use nesting. Here is the example from above in the un-nested version:

{
  myButton: {
    border: 'solid 1px #ccc',
    backgroundColor: 'lightgray',
    display: 'inline-block',
    cursor: 'pointer'
  },
  'myButton:focus': {
    borderColor: '#aaa'
  },
  'myButton:hover': {
    borderColor: '#ddd'
  },
  'myButton:hover:active': {
    borderColor: '#eee'
  },
  'myButton[disabled]': {
    cursor: 'not-allowed',
    opacity: .5
  },
  'myButton[disabled]:hover': {
    backgroundColor: 'transparent'
  }
}

Media Queries

{
  myButton: {
    border: 'solid 1px #ccc',
    // ...
  },

  myInput: {
    width: '100%',
    // ...
  },

  '@media only screen and (max-width: 480px)': {
    myButton: {
      borderWidth: 0
    },

    myInput: {
      fontSize: 14
    }
  },

  '@media only screen and (max-width: 768px)': {
    myButton: {
      borderWidth: 2,

      ':hover': {
        borderWidth: 3
      }
    }
  }
}

Media queries can appear at the top-level (as shown above) or nested in the style:

{
  myButton: {
    border: 'solid 1px #ccc',

    '@media only screen and (max-width: 480px)': {
      borderWidth: 0,

      ':active': {
        borderColor: 'blue'
      }
    },

    '@media only screen and (max-width: 768px)': {
      // ...
    }
  }
}

Given you set { phone: 'media only screen and (max-width: 480px)', tablet: 'media only screen and (max-width: 768px)' } as mediaMap option for the transformation, the above spec can be simplified to:

{
  myButton: {
    border: 'solid 1px #ccc',

    '@phone': {
      borderWidth: 0,

      ':active': {
        borderColor: 'blue'
      }
    },

    '@tablet': {
      // ...
    }
  }
}

Expressions in Style Rules

You can do simple arithmetic and string concats on the right-hand side of style rules. Each identifier found is substituted with the corresponding property value of the context object provided as option.

Example for a given context { MyColors: { green: '#00FF00' }, myUrl: 'path/to/image.png' }:

{
  myButton: {
    color: MyColors.green,
    borderWidth: 42 + 'px',
    backgroundImage: 'url(' + myUrl + ')'
  }
}

Basic theming via nesting within global selectors

You can nest your styles within another selector which is prefixed with $. These "global" selectors will be prepended (without the dollar sign of course) to the styles when generating the CSS. Nested styles also support pseudo-classes, attribute selectors and media queries. Example:

{
  myButton: {
    color: 'black'
  },
  '$body.red-theme': {
    myButton: {
      color: 'red'
    }
  },
  '$.blue >': {
    myButton: {
      color: 'blue';
    }
  }
}

CSS output (assuming b1 will become the generated class name for myButton):

.b1 {
  color: black;
}

body.red-theme .b1 {
  color: red;
}

.blue > .b1 {
  color: blue;
}

Global Styles

To opt out of the autogenerated class names and use global CSS selectors instead, you can prefix a selector with $. The selector will be passed through unchanged to the CSS.

This is useful to define reset, site-wide, or legacy styles without having to use a separate pipeline.

{
  '$html, body': {
    margin: 0,
    padding: 0,
  },

  '$.small-caps': {
    fontVariant: 'small-caps',
    fontFeatureSettings: '"smcp"',
  },

  '$.legacy-button': {
    border: '1px solid gray',
  },
}

CSS:

html, body {
  margin: 0;
  padding: 0;
}

.small-caps {
  font-variant: small-caps;
  font-feature-settings: "smcp";
}

.legacy-button {
  border: 1px solid gray;
}

Global selectors will be omitted in the JS object that cssInJS returns.

Dynamic Styles using Function Expressions

In order to write style rules dynamically, you can use function expressions. A function gives more freedom than an object. It receives a context object as first parameter. With this, you can do any programmatic operation, such as conditionals or even iterating over something. ES6 syntax is also available.

The function will be executed in a completely blocked Node.js VM sandbox environment, reveiving only the context object. Therefore you cannot require or import other modules in its body, or access references outside its scope.

Another thing to keep in mind is that the bundle file extraction and the JS file transformation will be based on the function's return value (which should be an object conforming to the Stylesheet Specification Format).

Here's an example that generates a stylesheet object based on platform, theme and env information passed via the context argument:

const style = cssInJS(function(context) {
  const { env, platform, theme } = context;

  const buttonSize = 100;
  let marginList = [10, 8, 10, 8];

  if (platform === 'iOS') {
    marginList = marginList.map(v => v - 2);
  }

  return {
    button: {
      width: buttonSize,
      margin: marginList.map(v => v + 'px').join(' '),
      color: platform === 'Android' ? 'red' : 'blue',
      border: env === 'development' ? '2px solid red' : 'none'
    },

    buttonBox: {
      backgroundColor: theme === 'dark' ? 'black' : 'white';
    }
  };
});

The context argument in the above code can be passed from, e.g., a Webpack babel loader setting like this:

// webpack.config.js

const env      = process.env.NODE_ENV || 'test';
const platform = process.env.PLATFORM || 'desktop';
const theme    = process.env.THEME    || 'dark';

const babelPluginCSSInJS = [
  ["css-in-js", {
    compressClassNames: env === 'production',
    vendorPrefixes: true,

    // generate a CSS bundle for each platform and theme
    bundleFile: `build/bundle.${theme}.${platform}.css`,

    context: { env, platform, theme },
  }],
];

module.exports = {
  // ...
  module: {
    loaders: [{
      test: /\.js$/,
      loader: 'babel',
      query: {
        presets: ['es2015', 'react'],
        plugins: [
          babelPluginCSSInJS,
        ]
      },
    }],
  },
  // ...
}

Example

If you just want to see some example output for a file, head over to this repo's quick example. There you will find the code for a simple button component together with its transformed version and CSS file (both with and without compressed class names).

The code for a more sophisticated example can be found in the repo's example directory. After cloning this repo, see the example's README for more info on how to run it.

Caveats

  • Just using var styles = cssInJS(...) in your React modules and skipping the transformation step won't work. It's the transformation that is responsible for a) generating the real CSS, and b) turning your cssInJS(...) calls into object literals holding the CSS class names so you can do <foo className={styles.bar} /> without breaking React. But you are transpiling your JavaScript anyway to get these cool new ES2015 features, aren't you?
  • Apart from simple arithmetic and string concats, a stylesheet specification cannot contain advanced dynamic stuff, because although the transformer parses the source input, it is not compiled. If you really need to add truly dynamic styles, that's what the style attribute/prop was made for. style also has the positive side-effect of taking precedence over class names.

Contributing

  1. Fork it ( https://github.com/martinandert/babel-plugin-css-in-js )
  2. Run npm install to install dependencies.
  3. Run the tests. We only take pull requests with passing tests, and it's great to know that you have a clean slate: make test.
  4. Create your feature branch (git checkout -b my-new-feature)
  5. Add a test for your change. Only refactoring and documentation changes require no new tests. If you are adding functionality or are fixing a bug, we need a test!
  6. Make the test pass.
  7. Commit your changes (git commit -am 'add some feature')
  8. Push to your fork (git push origin my-new-feature)
  9. Create a new Pull Request

Author: martinandert
Source Code: https://github.com/martinandert/babel-plugin-css-in-js
License: MIT License

#css #javascript 

Como construir um aplicativo tradutor de linguagem em HTML CSS e JavaScript

Neste guia, você aprenderá como criar um aplicativo tradutor de linguagem em HTML, CSS e JavaScript.

Para construir este aplicativo Language Translator em JavaScript. Primeiro, você precisa criar quatro arquivos: HTML, CSS e JavaScript.

1: Primeiro, crie um arquivo HTML com o nome index.html

<!DOCTYPE html>
<html lang="en" dir="ltr">
  <head>
    <meta charset="utf-8">  
    <title>Language Translator | Codequs</title>
    <link rel="stylesheet" href="style.css">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <!-- Font Awesome CDN Link for Icons -->
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css"/>
  </head>
  <body>
    <div class="container">
      <div class="wrapper">
        <div class="text-input">
          <textarea spellcheck="false" class="from-text" placeholder="Enter text"></textarea>
          <textarea spellcheck="false" readonly disabled class="to-text" placeholder="Translation"></textarea>
        </div>
        <ul class="controls">
          <li class="row from">
            <div class="icons">
              <i id="from" class="fas fa-volume-up"></i>
              <i id="from" class="fas fa-copy"></i>
            </div>
            <select></select>
          </li>
          <li class="exchange"><i class="fas fa-exchange-alt"></i></li>
          <li class="row to">
            <select></select>
            <div class="icons">
              <i id="to" class="fas fa-volume-up"></i>
              <i id="to" class="fas fa-copy"></i>
            </div>
          </li>
        </ul>
      </div>
      <button>Translate Text</button>
    </div>
    <script src="js/countries.js"></script>
    <script src="js/script.js"></script>
  </body>
</html>

2: Em segundo lugar, crie um arquivo CSS com o nome de style.css

/* Import Google Font - Poppins */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&display=swap');
*{
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Poppins', sans-serif;
}
body{
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 10px;
  min-height: 100vh;
  background: #5372F0;
}
.container{
  max-width: 690px;
  width: 100%;
  padding: 30px;
  background: #fff;
  border-radius: 7px;
  box-shadow: 0 10px 20px rgba(0,0,0,0.01);
}
.wrapper{
  border-radius: 5px;
  border: 1px solid #ccc;
}
.wrapper .text-input{
  display: flex;
  border-bottom: 1px solid #ccc;
}
.text-input .to-text{
  border-radius: 0px;
  border-left: 1px solid #ccc;
}
.text-input textarea{
  height: 250px;
  width: 100%;
  border: none;
  outline: none;
  resize: none;
  background: none;
  font-size: 18px;
  padding: 10px 15px;
  border-radius: 5px;
}
.text-input textarea::placeholder{
  color: #b7b6b6;
}
.controls, li, .icons, .icons i{
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.controls{
  list-style: none;
  padding: 12px 15px;
}
.controls .row .icons{
  width: 38%;
}
.controls .row .icons i{
  width: 50px;
  color: #adadad;
  font-size: 14px;
  cursor: pointer;
  transition: transform 0.2s ease;
  justify-content: center;
}
.controls .row.from .icons{
  padding-right: 15px;
  border-right: 1px solid #ccc;
}
.controls .row.to .icons{
  padding-left: 15px;
  border-left: 1px solid #ccc;
}
.controls .row select{
  color: #333;
  border: none;
  outline: none;
  font-size: 18px;
  background: none;
  padding-left: 5px;
}
.text-input textarea::-webkit-scrollbar{
  width: 4px;
}
.controls .row select::-webkit-scrollbar{
  width: 8px;
}
.text-input textarea::-webkit-scrollbar-track,
.controls .row select::-webkit-scrollbar-track{
  background: #fff;
}
.text-input textarea::-webkit-scrollbar-thumb{
  background: #ddd;
  border-radius: 8px;
}
.controls .row select::-webkit-scrollbar-thumb{
  background: #999;
  border-radius: 8px;
  border-right: 2px solid #ffffff;
}
.controls .exchange{
  color: #adadad;
  cursor: pointer;
  font-size: 16px;
  transition: transform 0.2s ease;
}
.controls i:active{
  transform: scale(0.9);
}
.container button{
  width: 100%;
  padding: 14px;
  outline: none;
  border: none;
  color: #fff;
  cursor: pointer;
  margin-top: 20px;
  font-size: 17px;
  border-radius: 5px;
  background: #5372F0;
}
@media (max-width: 660px){
  .container{
    padding: 20px;
  }
  .wrapper .text-input{
    flex-direction: column;
  }
  .text-input .to-text{
    border-left: 0px;
    border-top: 1px solid #ccc;
  }
  .text-input textarea{
    height: 200px;
  }
  .controls .row .icons{
    display: none;
  }
  .container button{
    padding: 13px;
    font-size: 16px;
  }
  .controls .row select{
    font-size: 16px;
  }
  .controls .exchange{
    font-size: 14px;
  }
}

3: Terceiro, crie um arquivo JavaScript com o nome de países.js

 

const countries = {
    "am-ET": "Amharic",
    "ar-SA": "Arabic",
    "be-BY": "Bielarus",
    "bem-ZM": "Bemba",
    "bi-VU": "Bislama",
    "bjs-BB": "Bajan",
    "bn-IN": "Bengali",
    "bo-CN": "Tibetan",
    "br-FR": "Breton",
    "bs-BA": "Bosnian",
    "ca-ES": "Catalan",
    "cop-EG": "Coptic",
    "cs-CZ": "Czech",
    "cy-GB": "Welsh",
    "da-DK": "Danish",
    "dz-BT": "Dzongkha",
    "de-DE": "German",
    "dv-MV": "Maldivian",
    "el-GR": "Greek",
    "en-GB": "English",
    "es-ES": "Spanish",
    "et-EE": "Estonian",
    "eu-ES": "Basque",
    "fa-IR": "Persian",
    "fi-FI": "Finnish",
    "fn-FNG": "Fanagalo",
    "fo-FO": "Faroese",
    "fr-FR": "French",
    "gl-ES": "Galician",
    "gu-IN": "Gujarati",
    "ha-NE": "Hausa",
    "he-IL": "Hebrew",
    "hi-IN": "Hindi",
    "hr-HR": "Croatian",
    "hu-HU": "Hungarian",
    "id-ID": "Indonesian",
    "is-IS": "Icelandic",
    "it-IT": "Italian",
    "ja-JP": "Japanese",
    "kk-KZ": "Kazakh",
    "km-KM": "Khmer",
    "kn-IN": "Kannada",
    "ko-KR": "Korean",
    "ku-TR": "Kurdish",
    "ky-KG": "Kyrgyz",
    "la-VA": "Latin",
    "lo-LA": "Lao",
    "lv-LV": "Latvian",
    "men-SL": "Mende",
    "mg-MG": "Malagasy",
    "mi-NZ": "Maori",
    "ms-MY": "Malay",
    "mt-MT": "Maltese",
    "my-MM": "Burmese",
    "ne-NP": "Nepali",
    "niu-NU": "Niuean",
    "nl-NL": "Dutch",
    "no-NO": "Norwegian",
    "ny-MW": "Nyanja",
    "ur-PK": "Pakistani",
    "pau-PW": "Palauan",
    "pa-IN": "Panjabi",
    "ps-PK": "Pashto",
    "pis-SB": "Pijin",
    "pl-PL": "Polish",
    "pt-PT": "Portuguese",
    "rn-BI": "Kirundi",
    "ro-RO": "Romanian",
    "ru-RU": "Russian",
    "sg-CF": "Sango",
    "si-LK": "Sinhala",
    "sk-SK": "Slovak",
    "sm-WS": "Samoan",
    "sn-ZW": "Shona",
    "so-SO": "Somali",
    "sq-AL": "Albanian",
    "sr-RS": "Serbian",
    "sv-SE": "Swedish",
    "sw-SZ": "Swahili",
    "ta-LK": "Tamil",
    "te-IN": "Telugu",
    "tet-TL": "Tetum",
    "tg-TJ": "Tajik",
    "th-TH": "Thai",
    "ti-TI": "Tigrinya",
    "tk-TM": "Turkmen",
    "tl-PH": "Tagalog",
    "tn-BW": "Tswana",
    "to-TO": "Tongan",
    "tr-TR": "Turkish",
    "uk-UA": "Ukrainian",
    "uz-UZ": "Uzbek",
    "vi-VN": "Vietnamese",
    "wo-SN": "Wolof",
    "xh-ZA": "Xhosa",
    "yi-YD": "Yiddish",
    "zu-ZA": "Zulu"
}

4: Por último, crie um arquivo JavaScript com o nome de script.js

const fromText = document.querySelector(".from-text"),
toText = document.querySelector(".to-text"),
exchageIcon = document.querySelector(".exchange"),
selectTag = document.querySelectorAll("select"),
icons = document.querySelectorAll(".row i");
translateBtn = document.querySelector("button"),
selectTag.forEach((tag, id) => {
    for (let country_code in countries) {
        let selected = id == 0 ? country_code == "en-GB" ? "selected" : "" : country_code == "hi-IN" ? "selected" : "";
        let option = `<option ${selected} value="${country_code}">${countries[country_code]}</option>`;
        tag.insertAdjacentHTML("beforeend", option);
    }
});
exchageIcon.addEventListener("click", () => {
    let tempText = fromText.value,
    tempLang = selectTag[0].value;
    fromText.value = toText.value;
    toText.value = tempText;
    selectTag[0].value = selectTag[1].value;
    selectTag[1].value = tempLang;
});
fromText.addEventListener("keyup", () => {
    if(!fromText.value) {
        toText.value = "";
    }
});
translateBtn.addEventListener("click", () => {
    let text = fromText.value.trim(),
    translateFrom = selectTag[0].value,
    translateTo = selectTag[1].value;
    if(!text) return;
    toText.setAttribute("placeholder", "Translating...");
    let apiUrl = `https://api.mymemory.translated.net/get?q=${text}&langpair=${translateFrom}|${translateTo}`;
    fetch(apiUrl).then(res => res.json()).then(data => {
        toText.value = data.responseData.translatedText;
        data.matches.forEach(data => {
            if(data.id === 0) {
                toText.value = data.translation;
            }
        });
        toText.setAttribute("placeholder", "Translation");
    });
});
icons.forEach(icon => {
    icon.addEventListener("click", ({target}) => {
        if(!fromText.value || !toText.value) return;
        if(target.classList.contains("fa-copy")) {
            if(target.id == "from") {
                navigator.clipboard.writeText(fromText.value);
            } else {
                navigator.clipboard.writeText(toText.value);
            }
        } else {
            let utterance;
            if(target.id == "from") {
                utterance = new SpeechSynthesisUtterance(fromText.value);
                utterance.lang = selectTag[0].value;
            } else {
                utterance = new SpeechSynthesisUtterance(toText.value);
                utterance.lang = selectTag[1].value;
            }
            speechSynthesis.speak(utterance);
        }
    });
});

Agora você construiu com sucesso um tradutor de linguagem em HTML, CSS e JavaScript.