How to insert a function inside another function and alphabetize a phrase? - javascript

I take the opportunity to ask two things, the first I want to alphabetically order a phrase that the user previously writes but for some reason it does not finish printing the result, the second is to read the phrase and indicate if there is any repeated word and how many times it is repeated and show it On the screen of course, I wanted to do it with a function but I don't know how to put one function inside another:
Here I attach code:
var Miventana;
function AbrirVen() {
//ventana secundaria
/* pondra la ventana en el centro de la pantalla; sin importar la resolución que esté utilizando el equipo cliente.
Las variables A y H darán el tamaño a la ventana.*/
var Ancho = screen.width;
var Alto = screen.height;
var A = Ancho*50/100;
var H = Alto*50/100;
var difA = Ancho - A;
var difH = Alto - H;
var tope = difH/2;
var lado = difA/2;
var Opciones="status=no, menubar=no, directories=no, location=no, toolbar=no, scrollbars=yes, resizable=no, width="+A+", height="+H+", top="+tope+", left="+lado+"";
Miventana = open("página que vas a abrir","_blank",Opciones);
var frase = document.getElementById("frase").value;
var palabras = frase.split(" ");
var primerapalabra = palabras[0];
var ultimapalabra = palabras[palabras.length-1];
var ordenLongitud = frase.slice();
Miventana.document.write(`Primera palabra: ${primerapalabra}`,"<br>");
Miventana.document.write(`Última palabra: ${ultimapalabra}`);
var numNom = frase.length;
Miventana.document.write("</br> Tu frase tiene " + numNom + " palabras </br>");
frase.sort(function (a, b) {
return a.toLowerCase().localeCompare(b.toLowerCase());
});
ordenLongitud.sort(function(a, b) {
return a.length - b.length
});
Miventana.document.getElementById("letras").innerHTML = 'Alfabetico: ' + frase + '<br>Longitud: ' + ordenLongitud;
function checkString(text,index){
if((text.length - index)==0 ){ //stop condition
return false;
}else{
return checkString(text,index + 1)
|| text.substr(0, index).indexOf(text[index])!=-1;
}
}
for(var frase in texts){
var text = texts[frase].split("");
Miventana.document.write(text + " -> " + text.some(function(v,i,a){return a.lastIndexOf(v)!=i;}) +"<br/>");
}
}

I want to alphabetically order a phrase that the user previously writes but for some reason it does not finish printing the result
You're sorting the wrong variable. You should sort the palabras variable, which is an array containing the splitted words rather than frase, which is the string.
var Miventana;
function AbrirVen() {
// [...]
var frase = document.getElementById("frase").value;
var palabras = frase.split(" ");
var primerapalabra = palabras[0];
var ultimapalabra = palabras[palabras.length-1];
var ordenLongitud = frase.slice();
Miventana.document.write(`Primera palabra: ${primerapalabra}`,"<br>");
Miventana.document.write(`Última palabra: ${ultimapalabra}`);
var numNom = frase.length; // <<< this should be palabras.length (not `frase`)
Miventana.document.write("</br> Tu frase tiene " + numNom + " palabras </br>");
frase.sort(function (a, b) { // <<< again you should sort palabras
return a.toLowerCase().localeCompare(b.toLowerCase());
});
// [...]
}
the second is to read the phrase and indicate if there is any repeated word and how many times it is repeated and show it
You could do that by using an object which holds the counts for each word (I took that approach from How to count duplicate value in an array in javascript):
var counts = {};
palabras.forEach(function (x) { counts[x] = (counts[x] || 0) + 1; });
for (k in counts) {
if (counts[k] > 1) {
// Show the output however you like
console.log(`Word '${k}' appears ${counts[k]} times`)
}
}
Finally:
I wanted to do it with a function but I don't know how to put one function inside another
There's no problem at all with defining a function inside another function. We could take the counting lines above, abstract them into a function and just call it from AbrirVen():
var Miventana;
function AbrirVen() {
// [...]
var frase = document.getElementById("frase").value;
var palabras = frase.split(" ");
// [...]
function displayCounts(words_to_be_counted) {
var counts = {};
words_to_be_counted.forEach(function (x) { counts[x] = (counts[x] || 0) + 1; });
for (k in counts) {
if (counts[k] > 1) {
// Show the output however you like
console.log(`Word '${k}' appears ${counts[k]} times`)
}
}
}
displayCounts(palabras)
// [...]
}

Related

How to print data from an object and error [object Object] does not appear?

I have this program that as soon as it starts up, it asks you to enter the number of books that you want to register in the program and the number of authors that each book will have.
The program will ask you to register a name for each author, surname, age and nationality.
Once this is done, there is a button that shows all the books registered with their authors and the data of the books, and I have the problem that I am not able to show the data of the authors since only [object Object] appears.
Edit:
I have managed to print the element.autores by console.log, without the error obejct object appearing but I am not able to get it out through a document.write or something similar, here I leave a screenshot of how it should appear:
And if I try to put elements.autores.nombre to print only the name, it appears undefined both in the console.log and in the document.write
Here my code:
javascript:
var biblioteca = new Array();
function libro(titulo, autores, anyo, editorial) {
this.titulo = titulo;
this.autores = autores;
this.anyo = anyo;
this.editorial = editorial;
}
function autor(nombre, apellidos, edad, nacionalidad) {
this.nombre = nombre;
this.aepellidos = apellidos;
this.edad = edad;
this.nacionalidad = nacionalidad;
}
window.onload = function () {
document.getElementById("mostrar").onclick = Mostrar;
document.getElementById("insertar").onclick = insertarlibro;
document.getElementById("insertar").onclick = insertarautor;
}
function insertarlibro() {
var autores = new Array();
var titulo = prompt("Insertar el nombre del titulo del libro");
var anyo = parseInt(prompt("Año"));
var editorial = prompt("Inserta su editorial");
var numautores = parseInt(prompt("Cuantos autores vas a insertar"));
for (let i = 0; i < numautores; i++) {
let autor = insertarautor();
autores.push(autor);
}
var registrohecho = new libro(titulo, autores, anyo, editorial);
return registrohecho;
}
console.log(insertarlibro);
function insertarautor() {
var nombre = prompt("Insertar el nombre del autor").toUpperCase();
var apellidos = prompt("Insertar el apellidos del autor").toUpperCase();
var edad = parseInt(prompt("Edad"));
var nacionalidad = prompt("¿De que pais es el autor?");
var registrohecho = new autor(nombre, apellidos, edad, nacionalidad);
return registrohecho;
}
console.log(insertarautor);
var numlibros = parseInt(prompt("Cuantos libros vas a insertar"));
for (let i = 0; i < numlibros; i++) {
var insertalibro = insertarlibro();
biblioteca.push(insertalibro);
}
function Mostrar() {
biblioteca.forEach(element => {
console.log("Error" + JSON.stringify(element.autores));
var muestra = "Nombre del libro:" + element.titulo + " autores: " + element.autores + " Año en el que se publico: " + element.anyo + " Editorial: " + element.editorial;
document.write(muestra);
});
}
And the html part:
<div id="insertar">
<input type="button" value="Insertar">
</div>
<div id="mostrar">
<input type="button" value="Mostrar">
</div>
You are trying to get element.autores, which is an array. To get e.g. get the nombre, you wold have to acces it with element.autores[0].nombre.
So your code to output all books (with authors) would be something like this:
biblioteca.forEach(element => {
var muestra = "Nombre del libro:" + element.titulo + " autores: ";
element.autores.forEach(author => {
muestra += `nombre: ${author.nombre}, aepellidos: ${author.aepellidos}, edad: ${author.edad}, nacionalidad: ${author.nacionalidad} `;
})
muestra += "Año en el que se publico: " + element.anyo + " Editorial: " + element.editorial;
document.write(muestra);
});

Jquery selector when attribute data is not empty

I am having this next issue.
I am developing a calendar with date formats and therefore what I need at this point is to be able to select all elements which their data attribute is not empty, in this case the na me of the attribute is data-hueco.
<p class="huecoDisponible" data-centro="HVA" data-hueco="0000000367#20201120#161000" style="cursor:pointer;">16:10</p>
I already tried certain things such as:
if(!$('.huecoDisponible').is(":empty")){
console.log(!$('.huecoDisponible').is(":empty"));
}
This approach obviously is not working.
I also have tried another option which is:
console.log($('.huecoDisponible').attr(':not([data-hueco=""])'));
console.log($('.huecoDisponible:not([data-hueco=""])');
In this case I am not quite sure if the selection is being done appropiately.
Finally, to give you one more hint is that I am creating all of these paragraphs by this next function which is called inside an AJAX method. Inside there I am creating the html elements by appending them to 7 different id's which present every day of the week.
Every p element has two data-attributes.
function filtrarPintarNuevoHueco(result, week){
html = '';
for (var b = 0; b < 7; b++ ) {
var diaFiltro = $('#'+arr[b]).attr("data-date");
let toto = result.citas.filter(c => c.fecha == diaFiltro);
for(var i = 0; i < toto.length; i++) {
let nuevoHueco = toto[i].fecha;
let codigoCita = toto[i].numcita;
let nuevoHuecoHora = toto[i].hora;
var hour = nuevoHuecoHora.substring(0, 2);
var min = nuevoHuecoHora.substring(2, 4);
let codigoCentro = toto[i].centro;
let nuevoHuecoHoraFormatted = hour + ':' + min;
html = '<p class="huecoDisponible" data-centro="' + codigoCentro + '" data-hueco="'+ codigoCita+ '" style="cursor:pointer;">'+ nuevoHuecoHoraFormatted+"</p>" ;
$("#" + arr[b] +' div').append(html);
}
}
$('.huecoDisponible').on('click', function(e){
e.preventDefault();
e.stopPropagation();
$('.huecoDisponible').removeClass("huecoDisponible_active");
$(this).addClass("huecoDisponible_active");
let dataHueco = $(this).attr("data-hueco");
let dataCentro = $(this).attr("data-centro");
let diaNombre = $(this).parent().parent().find("h3")[0].textContent;
let diaFecha = $(this).parent().parent().find("h4")[0].textContent;
let horaCita = $(this).attr("data-hueco").split("#")[2];
let hora = horaCita.substring(0,2);
let min = horaCita.substring(2,4);
let horaFormatted = hora + ":" + min;
reservarCitaMasHuecos(dataHueco, dataCentro, diaNombre, diaFecha, horaFormatted);
});
}
const devolverHuecosSemana = (especialista, diaSapLunes) => {
$.ajax({
url: '#Url.ActionLink("HuecosLibres", "HandlerEntityDbHub")',
type: "POST",
data: {"modo":"", "centro":"", "medico": especialista.idEspecialista, "fecha": diaSapLunes }
}).done(function (result, status, xhr) {
//tenemos que comprobar que estamos en el especialista que corresponde
if (result == undefined) {
alert("Este médico no tiene huecos");
} else {
result = JSON.parse(result);
if(result.citas.length > 0){
filtrarPintarNuevoHueco(result, diasSemana.week); // IT IS CALLED INSIDE HERE, PRINTS THE APPOINTMENT FOR A CERTAIN DAY OF THE WEEK
}else{
alert("Este médico no tiene huecos");
}
}
}).fail(function (jqXHR, textStatus, errorThrown) {
alert("Este médico no tiene huecos");
});
}
If anyone can give me some advice on how to proceed with the rest, it would be really appreciating.
Thanks you

JQuery function doesnt work after an other does

this code is from a cart of a music store I have made. The problem is that I need to check if the quantity I choose in the cart is in available in the stock. It works but if the user changes the quantity in the input number, the button pagar(pay) doesnt work. If I reaload the page it works but I need to do it without reload. The code:
$("#pagar").click(function() {
var tt_precio = $("#t_compra").text();
//solo cojo el precio tt y le quito el €;
var tt_precio = tt_precio.split(" ")[4];
var tt_precio = tt_precio.slice(0, -1);
var precios = [];
var fecha = new Date();
var date =
fecha.getFullYear() +
"/" +
Number(fecha.getMonth() + 1) +
"/" +
fecha.getDate();
$("[id*=precios]").each(function() {
var p = $(this)
.text()
.slice(0, -1);
precios.push(p);
});
var cantidades = [];
$("[type = number]").each(function() {
cantidades.push(Number($(this).val()));
});
var referencias = [];
$("[id*=referencias]").each(function() {
referencias.push($(this).text());
});
var nombres = [];
$("[id*=nombres]").each(function() {
nombres.push($(this).text());
});
var datos = {
precios: JSON.stringify(precios),
cantidades: JSON.stringify(cantidades),
referencias: JSON.stringify(referencias),
nombres: JSON.stringify(nombres),
tt_precio: tt_precio,
fecha: date
};
$.ajax({
type: "post",
data: datos,
url: "compra.php",
success: function(vuelta) {
alert(vuelta);
window.location.href = "/AccesoDatos/index.php";
}
});
});
$("seguir")
//cambiar precios
$("input").change(function() {
var valor = $(this).val();
var id = $(this).attr("id");
//para eliminar el simbolo del €
var precio = $("#precios" + id)
.text()
.slice(0, -1);
var datos = {
cantidad: valor,
referencia: id,
precio: precio
};
$.ajax({
type: "post",
data: datos,
url: "modificarCantidades.php",
success: function(datos) {
if (datos == -1) {
$("#span" + id).html("No hay suficientes unidades");
} else {
if (datos == 0) {
$("#fila" + id).remove();
$("#t_compra").html("0€");
$("#precio").html("0");
} else {
$("#span" + id).html("");
var precio = $("#precios" + id)
.text()
.slice(0, -1);
var cantidad = datos;
var total = precio * cantidad;
$("#total" + id).text(total + "€");
//alert(total);
var total_precio = 0;
var total_Cantidad = 0;
// coge todos los elementos que contienen en el id la palabra total y suma su valor
$("[id*=total]").each(function() {
var p = Number(
$(this)
.text()
.slice(0, -1)
);
total_precio += p;
});
//coge los inputs number para sumarlos
$("[type = number]").each(function() {
var c = Number($(this).val());
total_Cantidad += c;
});
//meto los valores nuevos en su sitio; --> en ajax hay que modificar el array de sesiones.
$("#unidades").html(total_Cantidad);
$("#precio").html(total_precio);
$("#t_productos").html(
"<strong>Total productos:</strong>" + total_Cantidad + "UDS"
);
$("#t_compra").html(
"<strong>Total de la compra:</strong>" + total_precio + "€"
);
}
}
}
});
});
It work clicking a button the first one and changing some input type="number", the problem is that if I use the onChange function, then I need to pay the updated cart but it is not posible because the button pay function doesn't work, I dont know why, I've tested whit an alert() at the top of the function, just below the call and it works but doesnt happend from there.
Change the below function:
$("input").change(function() {
For input field types change trigger function should not be used, try changing it with keyup function with 5 sec delay.
That might can help you out.
I have done something similar to this while you can use after doing some changes into it according to your need:-
//setup before functions
var typingTimer; //timer identifier
var doneTypingInterval = 2000; //time in ms, 5 second for example
var $input = $('#user_name');
//on keyup, start the countdown
$input.on('keyup', function () {
clearTimeout(typingTimer);
typingTimer = setTimeout(doneTyping, doneTypingInterval);
});
//on keydown, clear the countdown
$input.on('keydown', function () {
clearTimeout(typingTimer);
});
I've solved it, the problem was that the variable tt_precio was not set, when I click the button it does nothing because I dont update that value

Array does not work in Javascript

I tried to make a function that returns an array, the output should be "My name is Sarah Adam" but actually it does not return anything
/*global s:true*/
var m = 'My name is ';
function updateMsg(h) {
"use strict";
var el = m + h;
s = ['Adam', 'Joseph'];
return s;
}
var n1 = document.getElementById("msg");
n1.textContent = updateMsg("Sarah")[0];
you are returning s (the array) - I think you want to return the concatenated message. As in:
Updated to include variable last names
var m = 'My name is ';
function updateMsg(h, index) {
"use strict";
var el = m + h;
// array of last names
var s = ['Adam', 'Joseph'];
return el + ' ' + s[index]; // return the concatenated string instead
}
var n1 = document.getElementById("msg");
n1.textContent = updateMsg("Sarah", 0); // invoke with param
// console log (confirmation)
console.log(updateMsg("Sarah", 0));
console.log(updateMsg("Meenah", 1));
<div id="msg">
hw
</div>
You could use currying to accomplish this. Just swap your brackets [0] for parentheses (0).
var m = 'My name is ';
function updateMsg(h) {
var s = ['Adam', 'Joseph'];
return function(index) { // return a function that concatenates when given index
return m + h + " " + s[index];
};
}
var messageMaker = updateMsg("Sarah");
console.log(messageMaker(0));
console.log(messageMaker(1));
I think you want to acces one element of the list of lastnames an pass the name. I have corrected your code and do something similar to what you want :
let m = 'My name is ',
s = ['Adam', 'Joseph'],
updateMsg = (h, i) => m + h + ' ' + s[i],
n1 = document.getElementById("msg");
n1.textContent = updateMsg("Sarah", 0);
<p id="msg"></p>
Details are in the source in the comments.
SNIPPET
/*
Global variable: intro
*/
var intro = 'My name is ';
/*
Paramenter: who
*/
function updateMsg(who) {
/*
Array of 2 Strings: guess
Named it guess because that's
what I ended up doing with it
*/
var guess = [' Shadey', ' Joseph'];
/*
Concated String: `hello`
Since `intro` is global it's always accessible
`who` is the parameter with value of "Slim"
`guess[0]` = 'Shadey'
*/
var hello = intro + who + guess[0];
/*
Output of `updateMsg()` function is `hello`
which is "My name is Slim Shadey"
*/
return hello;
}
/*
Reference the `output` element as `noLogic`
*/
var noLogic = document.getElementById("msg");
/*
Set `noLogic's` text to whatever `updateMsg()`
returns
`updateMsg()` parameter is "Slim"
*/
noLogic.textContent = updateMsg("Slim");
<output id="msg"></output>
I guess the intent is to return an array with el prepended to each of the names in s. So you need to loop through the array to create the new array.
var m = 'My name is ';
function updateMsg(h) {
"use strict";
var el = m + h;
var s = ['Adam', 'Joseph'];
return s.map(function(name) {
return el + ' ' + name;
});
}
var n1 = document.getElementById("msg");
n1.textContent = updateMsg("Sarah")[0];
<div id="msg">
</div>

I cannot assign a value to a variable after call a function in javascript

I am making a modification of the popular game rock-paper-scissors-lizard-spock based on a algorithm proposed by someone on this site.
Here is my Js:
//¿Es obligatorio declarar las variables?
var Elementos = ["AIRE", "OSCURIDAD", "AGUA", "FUEGO", "TIERRA"];
var resultados = [" empata con ", " derrota a ", " pierde con "];
var opcionUsuario = false;
var opcionMago = false;
console.log("Default " + opcionUsuario);
//¿Qué elemento eligió el usuario?
function elementoElegido(elemento){
opcionUsuario = elemento;
log.value = "Has elegido " + Elementos[opcionUsuario] + ".";
console.log("User picks " + opcionUsuario);
}
//¡A pelear!
function guerra(opcionUsuario){
//console.log(opcionUsuario);
if(opcionUsuario === false){
log.value = "Por favor, elige un elemento primero joven aventurero."
}else{
opcionMago = Math.floor( Math.random() * (4 - 0 + 1) + 0 );
combate(opcionUsuario, opcionMago);
}
}
function combate(opcionUsuario, opcionMago) {
dif = opcionMago - opcionUsuario;
if(dif < 0) {
dif += Elementos.length;
}
while(dif > 2) {
dif -= 2;
}
log.value = "Tu elección: " + Elementos[opcionUsuario] + resultados[dif] + "la elección del mago: " + Elementos[opcionMago] + ".";
//¡Vuelve a elegir!
opcionUsuario = false;
console.log(opcionUsuario);
};
I set the variable opcionUsuario on false, but when I run the function guerra again, the variable opcion Usuario comes with the last value settled by the function elementoElegido.
How can I set the variable on false again in order to force the user to choose one element before continue? Why this happens? Thanks in advance.
Here is a live example.
When you pass a value as a function parameter, it generates a local variable with the assigned value being passed so this:
function foo(bar){
console.log(bar);
}
foo('hello world');
is actually interpreted as this:
function foo(bar){
var bar = [bars value]; //in this case, 'hello world'
console.log(bar); //logging the local variable
}
foo('hello world');
In order to achieve what you desire, you need reference the variable declared in the outer scope, which can be done easily:
var bar = 'hello world';
function foo(){
console.log(bar);
bar = 'goodbye world';
}
foo();//logs hello world
foo();//logs goodbye world;
console.log(bar); //goodbye world
Note: access to shared variables should be as limited as possible in order to reduce unexpected results and conflicts. It might be worth your time to looking into architectures that achieve this, such as the module pattern.

Categories