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>
Related
Explanation. I am new to VueJS and JavaScript and I am trying to setup a search bar. So far, it works well, but I have one issue with it. I would like to be able to search through a description of an object even if the words I typed in the search bar are not in the correct order.
Example.
The string in the description would be "Gucci blue belt". If I type "Gucci blue", the result shows up since the description contains those words in this exact order. Therefore, I would like to add the functionality for which I can type "Gucci belt" and the item with the description "Gucci blue belt" would show up.
My current code in the computed section in VueJS
filteredsortedobjects (){
return this.sortedobjects.filter(object => {
var Objectslist_n = object.name;
var Objectslist_q = object.quantity;
var Objectslist_c = object.category;
var Objectslist_s = object.section;
var Objectslist_d = object.description;
var Objectslist_date = object.reception_date;
var Input = this.searchQuery;
/* Form arrays with all the information in the table */
var Objectslist_nq = Objectslist_n.concat(Objectslist_q);
var Objectslist_nqc = Objectslist_nq.concat(Objectslist_c);
var Objectslist_nqcs = Objectslist_nqc.concat(Objectslist_s);
var Objectslist_nqcsd = Objectslist_nqcs.concat(Objectslist_d);
var Objectslist_nqcsddate = Objectslist_nqcsd.concat(Objectslist_date);
/* Filtered variables */
var F_Objectslist = RemoveAccents(Objectslist_nqcsddate.toLowerCase());
var F_Input = RemoveAccents(this.searchQuery.toLowerCase());
/* Function to remove accents */
function RemoveAccents(str) {
var accents = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž';
var accentsOut = "AAAAAAaaaaaaOOOOOOOooooooEEEEeeeeeCcDIIIIiiiiUUUUuuuuNnSsYyyZz";
str = str.split('');
var strLen = str.length;
var i, x;
for (i = 0; i < strLen; i++) {
if ((x = accents.indexOf(str[i])) != -1) {
str[i] = accentsOut[x];
}
}
return str.join('');
};
console.log(F_Objectslist);
console.log(F_Input);
return F_Objectslist.includes(F_Input)
})
}
I am aware that the function to remove accents is not yet used since I have been testing things.
What I have tried doing. I have tried setting the variable F_Input (what is being written in the search bar) and F_Objectslist (a variable containing an array with all the words for the items, for instance, the names, the category, the section, the quantity, a description and a date) as strings by array.split(" "). That way, I was able to have an array of strings in this format in the console ["word", "word2", ...] for both my variables.
From this point, I am unsure on how to check if the strings in my F_Input array are all present in the array for F_Objectslist even if they are in a different order.
Thank you so much for your time!
Split F_Input on " ", then you can use 'Array.prototype.map()' to loop through the F_Input array of search terms using the same technique you have now.
Notice that I've chained all these together with a final call to the .every() method. That last one says that every map operation (search) must result in a true (or the result of the map operation must result in an array full of nothing but true);
const F_Objectslist = "this is search term, and this is term search".split(' ');
const F_Input = "search term";
let result = search(F_Objectslist, F_Input);
console.log(result);
let notFoundResult = search(F_Objectslist, "search dog");
console.log(notFoundResult);
function search(text, terms) {
return terms.split(' ').map(term =>text.includes(term)).every(found=>found===true);
}
I think you were already pretty close, I would approach it like this
function searchString(input, match) {
let is_a_match = true;
const match_arr = match.split(' ');
const input_arr = input.split(' ');
input_arr.forEach(word => {
if (match_arr.indexOf(word) === -1) {
is_a_match = false;
}
});
return is_a_match;
}
A working fiddle can be found here
Here is my answer.
I managed to make a quite responsive search bar that seeks information in the array! Here is the code if anyone is curious about it!
page.vue inside computed
filteredsortedobjects (){
return this.sortedobjects.filter(object => {
var Objectslist_n = "a" + object.name;
var Objectslist_c = object.category;
var Objectslist_s = object.section;
var Objectslist_q = object.quantity;
var Objectslist_d = object.description;
var Objectslist_date = object.reception_date;
var Input = this.searchQuery;
/* Form arrays with all the information in the table */
var Objectslist_nc = Objectslist_n + " " + Objectslist_c;
var Objectslist_ncs = Objectslist_nc + " " + Objectslist_s;
var Objectslist_ncsq = Objectslist_ncs + " " + Objectslist_q;
var Objectslist_ncsqd = Objectslist_ncsq + " " + Objectslist_d;
var Objectslist_ncsqddate = Objectslist_ncsqd + " " + Objectslist_date;
/* Filtered variables */
var F_Objectslist = RemoveAccents(Objectslist_ncsqddate.toLowerCase()).split(" ") + " ";
var F_Input = RemoveAccents(this.searchQuery.toLowerCase()).split(" ");
/* Function to remove accents */
function RemoveAccents(str) {
var accents = 'ÀÁÂÃÄÅàáâãäåÒÓÔÕÕÖØòóôõöøÈÉÊËèéêëðÇçÐÌÍÎÏìíîïÙÚÛÜùúûüÑñŠšŸÿýŽž';
var accentsOut = "AAAAAAaaaaaaOOOOOOOooooooEEEEeeeeeCcDIIIIiiiiUUUUuuuuNnSsYyyZz";
str = str.split('');
var strLen = str.length;
var i, x;
for (i = 0; i < strLen; i++) {
if ((x = accents.indexOf(str[i])) != -1) {
str[i] = accentsOut[x];
}
}
return str.join('');
};
return F_Input.every(object => {
if (F_Objectslist.indexOf(object) === -1) {
}
else {
return F_Objectslist.indexOf(object)
}
})
})
}
I have an input with a v-model="searchQuery" attribute. Also, there is a table containing
<tr id="tr" v-for="object in filteredsortedobjects" v-bind:key="object.name">
<td>
<p>{{ object.name }}</p>
</td>
<td>
<p>{{ object.category }}</p>
</td>
<td>
<p>{{ object.section }}</p>
</td>
<td>
<p>{{ object.quantity }}</p>
</td>
<td>
<p>{{ object.description }}</p>
</td>
<td>
<p>{{ object.reception_date }}</p>
</td>
</tr>
The object.something are imported from a JSON file using
<script>
import objects from "./Database/Objects.json";
</script>
You would probably have to set some data information in the data() section
searchQuery: ""
So I created a loop which goes through an object created by googles gecoding api. Finds certain values and than puts them into a "results list", the single elements have onClick functions. Now when I do the onClick functions with bind, they do work, when I do them with () => they don't. Maybe someone can explain to me why that doesn't work?
loop:
renderResults: function(){
var status = this.state.data.status;
var results = this.state.data.results;
var ok = (status === 'OK' ? true : false);
if (!status) {
return <div> </div>
}
if (!ok) {
return <div className="searchresults">Error, we couldn't find a match</div>
}
if (status && ok){
var size = Object.keys(results).length
console.log(this.state.data);
var validation_messages = this.state.data.results;
///* Get properties *///
var resul =[];
for (var key in validation_messages) {
console.log("####### " + key + " #######");
// skip loop i the property is from prototype
if (!validation_messages.hasOwnProperty(key)) continue;
var label1 = '';
var label2 = '';
var obj = validation_messages[key];
console.log(obj);
for (var prop2 in obj.address_components) {
if(!obj.address_components.hasOwnProperty(prop2)) continue;
var obj3 = obj.address_components[prop2];
if (obj3.types.indexOf('locality') !== -1) {
label1 = obj3.long_name;
}
if (obj3.types.indexOf('country') !== -1) {
label2 = obj3.long_name;
}
}
var lat = obj.geometry.location.lat;
var lng = obj.geometry.location.lng;
var placeid = obj.place_id;
var label3 = lat.toFixed(3) + "°N / " + lng.toFixed(3) + "°E";
console.log('label1: '+label1);
console.log('label2: '+label2);
console.log('label3: '+label3);
console.log('lat: ' + lat);
console.log('lng: ' + lng);
console.log('id: ' + placeid);
console.log(validation_messages[key].formatted_address);
resul.push(<div className="results" onClick={this.pushlabels.bind(this, label1, label2, label3)} >{label3}</div>);
}
console.log(resul);
return resul;
}
So this works:
resul.push(<div className="results" onClick={this.pushlabels.bind(this, label1, label2, label3)} >{label3}</div>);
This doesn't work:
resul.push(<div className="results" onClick={() => this.pushlabels(label1,label2,label3)} >{label3}</div>);
What do I mean with not working? If I take the version which doesn't work than I get only pushed the label1, label2, label3 from the last object in the loop.
So now I wonder why?
It has to do with variable scoop and closures, for a similar problem have a look at javascript scope problem when lambda function refers to a variable in enclosing loop
Here's a short and simple program that illustrates what happens:
function foo(first, second){
console.log(first + " : " + second)
}
var x = "x";
let bar = () => {foo("bar", x)}
let baz = foo.bind(this,"baz", x)
bar()
baz()
x = "y"
bar()
baz()
//Output:
//bar : x
//baz : x
//bar : y
//baz : x
So basically bind makes the function remember (it actually returns a new function with the parameters set) the current state of the variables. Where as a lamda looks at the variables when it's executed. That's why you only see the last three labels when you don't use bind.
I'm building one site at JOOMLA and at this site i want to put all the word "Inovflow" on the site, at the color blue and upercase. Like this "INOVFLOW".
I put this code on the js folder of the site:
jQuery(document).fn.findText = function(params){
var phrases = params.query,
ignorance = params.ignorecase;
wrapper = $(this);
var source = wrapper.html();
selection_class_name = params.style;
source = source.replace(/[\n|\t]+/gi, '');
source = source.replace(/\s+/gi, ' ');
source = source.replace(/> /gi, '>');
source = source.replace(/(\w)</gi, function(m, w){return(w + " <");});
phrases.forEach(function(str){
var regexp = makeRegexp(str);
source = source.replace(regexp, function (m){
return (emulateSelection(m));
});
});
wrapper.html(source);
var res_array = wrapper.find("[search=xxxxx]")
return(res_array);
};
function makeRegexp(s){
var space = '( )?(<span[^>]*>)?(</span[^>]*>)?( )?';
var result = s.replace(/\s/gi, space);
result = new RegExp(space + result + space, "gi");
return(result);
}
function emulateSelection (htmlPiece){
htmlPiece = htmlPiece.replace(/(?!=>)[^><]+(?=<)/g, function(w){
return(wrapWords(w));}
);
htmlPiece = htmlPiece.replace(/^[^><]+/, function(w){
return(wrapWords(w));}
);
htmlPiece = htmlPiece.replace(/[^><]+$/, function(w){
return(wrapWords(w));}
);
htmlPiece = htmlPiece.replace(/^[^><]+$/, function(w){
return(wrapWords(w));}
);
return( htmlPiece );
}
function wrapWords(plainPiece){
console.log("plain: " + plainPiece);
var start = '<span search="xxxxx">',
stop = '</span>';
return(start + plainPiece + stop);
}
jQuery(document).each($('.container').findText({query: ['INOVFLOW']}), function (){
$(this).addClass("changeColorInovflow");
});
After this, the page seems to get on a Infinite loop and doesn't load.
if instead of jQuery(document) I use $. the JS returns a error and doesn't run.
Am I doing something wrong?
If findText is intended to be a jQuery plugin, you'll need to update the way the function is declared.
$.fn.findText = function(params) {
var phrases = params.query;
// removed unused 'ignorance' var
var wrapper = this; // this is already a jQuery object
var source = wrapper.html();
selection_class_name = params.style;
source = source.replace(/[\n|\t]+/gi, '');
source = source.replace(/\s+/gi, ' ');
source = source.replace(/> /gi, '>');
source = source.replace(/(\w)</gi, function(m, w){return(w + " <");});
phrases.forEach(function(str){
var regexp = makeRegexp(str);
source = source.replace(regexp, function (m){
return (emulateSelection(m));
});
});
wrapper.html(source);
var res_array = wrapper.find("[search=xxxxx]")
return this; // return 'this' to make it chainable
}
Here are the relevant docs:
https://learn.jquery.com/plugins/basic-plugin-creation/
Then, when you call findText, you can use a much simpler selector:
$('.container').each(function() {
$(this).findText({query: ['INOVFLOW']}).addClass("changeColorInovflow");
});
The original code wouldn't work because each() takes either a function or an array with a callback as parameters, not a selector.
.each(): http://api.jquery.com/each/
jQuery.each(): http://api.jquery.com/jquery.each/
I'm practicing with event listeners and functions and am trying to build a very simple card game. My first 2 functions work to get values of card 1 and 2 once the respective buttons are clicked. I've built a third to combine the total, but having trouble pulling the generated values into a third function. My third function always returns zero. I get why, but haven't been able to find a solution to pull the values from the first 2 functions. Any help is appreciated, thanks.
var cardButton = document.getElementById('cardButton1');
var cardButton2 = document.getElementById('cardButton2');
var cardValue = document.getElementById('cardValue');
var cardValue2 = document.getElementById('cardValue2');
var cardTotalButton = document.getElementById('cardTotalButton');
var cardTotal = document.getElementById('displayTotal');
var card1Value = 0;
var card2Value = 0;
var totalCardsValue = 0;
var cardMin = 1;
var cardMax = 14;
function generateCard(){
var card1Value = randCard();
cardValue.innerHTML = 'card value is ' + card1Value;
return card1Value;
}
function generateCard2(){
var card2Value = randCard();
cardValue2.innerHTML = 'card value is ' + card2Value;
return card2Value;
}
function getPlayerTotal(){
var totalCardsValue = card1Value + card2Value;
//console.log(cardValue2 + 'test');
cardTotal.innerHTML = 'card total is ' + totalCardsValue;
}
cardButton.addEventListener('click',generateCard);
cardButton2.addEventListener('click',generateCard2);
cardTotalButton.addEventListener('click',getPlayerTotal);
function randCard(){
var genRandCard = Math.floor(Math.random()*cardMax)+1;
return genRandCard;
}
You are re-declaring your card1Value, card2Value, and totalCardsValue to a local scope. Remove the var in front of them. Doing it this way, you don't need to return any value from the generateCard() and generateCard() function because you're using the global variables.
function generateCard(){
card1Value = randCard(); //<-------Don't use var here
cardValue.innerHTML = 'card value is ' + card1Value;
return card1Value; //<-------This line is not really needed
}
function generateCard2(){
card2Value = randCard(); //<-------Don't use var here
cardValue2.innerHTML = 'card value is ' + card2Value;
return card2Value; //<-------This line is not really needed
}
function getPlayerTotal(){
totalCardsValue = card1Value + card2Value; //<-------Don't use var here
//console.log(cardValue2 + 'test');
cardTotal.innerHTML = 'card total is ' + totalCardsValue;
}
I'm trying to build a database based on some arbitrary data on a website. It's complex and changes for each site so I'll spare the details. Here's basically what I'm trying to do
function level0(arg) { textarea.innerHTML += arg + ' = {'; }
function level1(arg) { textarea.innerHTML += '\n\t' + arg + ': ['; }
function level2(arg) { textarea.innerHTML += arg + ', '; }
And so on. The thing is some level1's don't have any children and I can't get the formatting right.
My three problems are as follows.
The ending commas are going to break in IE (thank you MS)
Empty level1's shouldn't be printed if they don't have any children
Closing /curly?brackets/
HERE'S A DEMO of what I have so far. Notice the ending commas, the empty sub2 which shouldn't be printed, and no closing brackets or braces
Do I need to redesign the entire thing?
Is there also a way to have this all in one function so I don't have to worry if I add another layer?
EDIT
This needs to be done in a string format, I can't build an object and then stringify it, mostly because I need to know which element I'm in the middle of adding to.
Overall it looks that you still might want to build an object, but in case you insist on not building it - here is some sample solution:
function Printer() {
var result = '',
lastLevel = null,
close = {0:'\n}', 1:']', 2:''},
delimiter = {0: ',\n', 1:',\n', 2:','};
function closeLevel(level, noDelimiter) {
if(lastLevel === null)
return;
var l = lastLevel, d = level == lastLevel;
while(l >= level) {
result += close[l] + (l == level && !noDelimiter ? delimiter[l]:'');
l--;
}
}
this.level0 = function(arg) {
closeLevel(0);
result += arg + ' = {\n';
lastLevel = 0;
};
this.level1 = function(arg) {
closeLevel(1);
result += '\t' + arg + ': [';
lastLevel = 1;
};
this.level2 = function(arg) {
closeLevel(2);
result += arg;
lastLevel = 2;
};
this.getResult = function() {
closeLevel(lastLevel, true);
return result;
}
}
var p = new Printer();
p.level0('head');
p.level1('sub1');
p.level2('item1');p.level2('item2');p.level2('item3');
p.level1('sub2');
p.level1('sub3');
p.level2('newthing');
p.level0('head2');
document.getElementById('textarea').value = p.getResult();
You could see it in action here.
I'm not sure why you're building what looks like objects with nested arrays, using string concatenation. Something like this would be much simpler, since it wouldn't require fixing trailing commas, etc:
Edit: I've updated the code to make it keep track of the last level put in.
function Db() {
var level0, level1;
var data = new Object();
this.level0 = function(arg) {
level0 = new Object();
data[arg] = level0;
}
this.level1 = function(arg) {
level1 = new Array();
level0[arg] = level1;
}
this.level2 = function(arg) {
level1.push(arg);
}
this.toString = function() {
var s = '';
for(i in data) {
s += i + '\n';
for(j in data[i]) {
if(data[i][j].length>0) {
s += '\t' + j + ': [' + data[i][j] + ']\n' ;
}
}
}
return s;
}
}
Use like this:
var db = new Db();
db.level0('head');
db.level1('sub1');
db.level2('item1');db.level2('item2');db.level2('item3');
I've tested this in the demo you linked and it works just fine.