I am trying to create a JavaScript function which would extract pre-defined variables from a string. Within the string, these variables will be nested within the "<>" character set.
For example:
the string which is typed by the user could be: I am <me> , my age is <myage>
which would then render the text: I am Joe Bloggs , my age is 21 (given the two user defined variables 'me' and 'myage')
I have begun to use the split funciton, but this is not going well.
function parse_String(theString) {
var varSplit = theString.split("<");
};
Is there an elegant solution, either using javascript or RegEx?
You seem to look for a 'templating' function. If you format the initial string like this 'I am {0}, my age is {1}', you could use this method:
function stringFormat() {
var args = [].slice.call(arguments);
return this.replace(/(\{\d+\})/g, function(a) {
return args[ +(a.split(/[{}]/)[1]) || 0 ];
});
};
// usage
stringFormat.call('I am {0}, my age is {1}','Joe Bloggs','21');
//=> I am Joe Bloggs, my age is 21
You could add the method to String.prototype:
String.prototype.Format = stringFormat;
// usage
'I am {0}, my age is {1}'.Format('Joe Bloggs','21');
You can use
var result = theString.substring(theString.indexOf('<')+1, theString.indexOf('>'))
You can simple do a replace function. I assume you want to replace the predifined places with your own variables.
function parse(string, data) {
$.each(data, function (v, k) {
string = string.replace('<'+k+'>', v);
});
return string;
}
Example
parse("<me> is <age> years old", {me:'Han', age:22});
output: Han is 22 years old
Related
The output of this program is undefined instead of string name.
I am taking a date as input to the program and comparing the date with the existing dates of president array. In case if the date matches then i want to return the president name for that particular date
process.stdin.resume();
process.stdin.setEncoding('utf8');
var stdin = '';
process.stdin.on('data', function (chunk) {
//printing the value returned by presidentOnDate function
console.log(JSON.stringify(presidentOnDate(chunk)));
});
//This is presidents array
var presidents = [
{"number":32,"president":"Franklin D. Roosevelt","took_office":"1933-03-04","left_office":"1945-04-12"},
{"number":33,"president":"Harry S. Truman","took_office":"1945-04-12","left_office":"1953-01-20"},
{"number":34,"president":"Dwight D. Eisenhower","took_office":"1953-01-20","left_office":"1961-01-20"},
{"number":35,"president":"John F. Kennedy","took_office":"1961-01-20","left_office":"1963-11-22"},
{"number":36,"president":"Lyndon B. Johnson","took_office":"1963-11-22","left_office":"1969-01-20"},
{"number":37,"president":"Richard Nixon","took_office":"1969-01-20","left_office":"1974-08-09"},
{"number":38,"president":"Gerald Ford","took_office":"1974-08-09","left_office":"1977-01-20"},
{"number":39,"president":"Jimmy Carter","took_office":"1977-01-20","left_office":"1981-01-20"},
{"number":40,"president":"Ronald Reagan","took_office":"1981-01-20","left_office":"1989-01-20"},
{"number":41,"president":"George H. W. Bush","took_office":"1989-01-20","left_office":"1993-01-20"},
{"number":42,"president":"Bill Clinton","took_office":"1993-01-20","left_office":"2001-01-20"},
{"number":43,"president":"George W. Bush","took_office":"2001-01-20","left_office":"2009-01-20"},
{"number":44,"president":"Barack Obama","took_office":"2009-01-20","left_office":"2017-01-20"}
];
//PresidentOnDate function which should return a president name based on input date
function presidentOnDate(date) {
var output="";
for(var i=0;i<presidents.length;i++){
//console.log(presidents[i].took_office);
if((presidents[i].took_office)==date){
output+=presidents[i].president;
}
}
return output;
}
I think the problem is you are passing in a buffer instead of a string.
Try changing the chunk buffer to a string before passing it to presidentOnDate.
So instead of presidentOnDate(chunk) try presidentOnDate(chunk.toString())
Try this function it's working fine.
problem you facing when you take input it take \r\n also so when you compare both you get false that y output showing null.
EX:input string: "2009-01-20\r\n" compare with : took_office: "2009-01-20" => result false
EX: input string with trim: "2009-01-20" compare with : took_office: "2009-01-20" => result True
change only : (presidents[i].took_office) ==date.trim()
function presidentOnDate(date) {
var output="";
for(var i=0;i<presidents.length;i++){
if((presidents[i].took_office) ==date.trim()){
output+= presidents[i].president;
}
}
return output;
}
I am saving string into mongoDB with preset variable as
'Current time is ${time}'
After that I am retrieving somewhere else this string and would like to assign value to time
It would look something like this
const time = '15:50'
const response = result //saves string retreived from mongo
res.json({
response: response
})
But that returns 'Current time is ${time}' instead of 'Current time is 15:50'
I am aware that the string should be in `` instead of single quotes for variable to work, not sure though how to implement that as output from mongo
Anyone could point me to correct direction?
An alternative is to pass the string and parameters to a function and reduce over the parameters object:
var str = 'Current time is ${time}';
var params = { time: '13:30' };
function merge(str, params) {
return Object.keys(params).reduce((out, key) => {
return str.replace(`\${${key}}`, params[key]);
}, '');
}
console.log(merge(str, params));
And this is an example of interpolation magic, as mentioned in other answer ;) Note, than even without the evil() ;)
var time = '15:50'
var response = 'Current time is ${time}'
var converted = (_=>(new Function(`return\`${response}\`;`))())()
console.log(converted)
Interpolation is not performed on a string variable that happens to contain a template literal placeholder. In order for interpolation to happen, you must have a literal string in the code, enclosed in back ticks with a placeholder:
let time = '15:50';
let message = `Current time is ${time}`
console.log(message); // "Current time is 15:50"
If you must store strings in your database, you'll have to come up with your own mechanism for interpolating your placeholders.
I try since hours and using the (very less helpful API documentation :S) to get translation for my plugin working.
tinymce.translate('Cut'); // returns Ausschneiden for de
So far, so good.
tinymce.translate('myplugin.test'); // returns myplugin.test
I checked tinymce.i18n.data and can see through inspector that it contains the data I added with
tinymce.addI18n('de.myplugin', {
"test": 'test label'
});
before.
This is probably something stupid but I can not figure it out.
UPDATE
I now add my own functionality to do it manually as I can not figure it out how to do it:
plugin_translate = function(val) {
return (eval('tinymce.i18n.data.' + tinymce.settings.language + '.' + val) != undefined)
? eval('tinymce.i18n.data.' + tinymce.settings.language + '.' + val)
: val;
}
And my plugin/langs/de.js looks like this
tinymce.addI18n('de', { 'plugin': { "title" : 'Titel' }});
This doesn't look right but at the moment it works until someone enlighten me.
Translations are registered using tinymce.addI18n(langCode, translationMap) or tinymce.util.I18n.add(langCode, translationMap).
The first parameter is a language code like "en", "en_US" or "de". This should be the same value used for the language init property. Note that you should not include the plugin prefix here.
The second parameter is a map of translation-key to translation pairs. The translations can take positional arguments like {0} and {1}. You should prefix your keys with your plugin name to avoid naming clashes. For example:
{
"myplugin.test": "test label",
"myplugin.greeting": "Hello {0}, you are welcome"
}
So combining all those parts together you might register English and German translations like:
tinymce.addI18n("en", {
"myplugin.title": "My Plugin",
"myplugin.greeting": "Hello {0}, you are welcome"
});
tinymce.addI18n("de", {
"myplugin.title": "Mein Plugin",
"myplugin.greeting": "Hallo {0}, du bist willkommen"
});
Then to use the translation call tinymce.translate(translationKey) which returns the translated string. For a string without arguments you can just pass the same key you used in the map. For example:
var title = tinymce.translate("myplugin.title");
If your translation has parameters you have to wrap the key up in an array. For example:
var name = getName(); // get the name from the user
var greeting = tinymce.translate(["myplugin.greeting", name]);
If for some reason you need to override the translation you can provide an object with a raw string. For example:
var name = getName(); // get the name from the user
var key = name === "James" ? {"raw": "Go away!"} : ["myplugin.greeting", name];
var greeting = tinymce.translate(key);
Is there a better way to build strings in JavaScript than doing string concatination?
It would make my code cleaner if I could do something like ruby where you can expand variables in a string instead of doing lots of "foo" + bar + "baz".
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
});
};
console.log("{0} bar {1}.".format("foo","baz"));
Will produce:
"foo bar baz"
Chris Nielsen has provided a pure-JavaScript solution in this answer:
String.prototype.supplant = function (o) {
return this.replace(/{([^{}]*)}/g,
function (a, b) {
var r = o[b];
return typeof r === 'string' || typeof r === 'number' ? r : a;
}
);
};
alert("I'm {age} years old!".supplant({ age: 29 }));
alert("The {a} says {n}, {n}, {n}!".supplant({ a: 'cow', n: 'moo' }));
You could also use CoffeScript, which is a language that compiles to JavaScript. It supports string interpolation:
author = "Wittgenstein"
quote = "A picture is a fact. -- #{ author }"
sorry guys but all this is not very the ruby way, here is a basic p equivalent, sorry for the eval, that surely can be done better..
if you just want the concatenation, just replace the document.write by return in the first solution
function p(str){
document.write(str.replace(/#{(\w)}/g, function(match, s){return eval(s)})+"<br>");
}
String.prototype.p = function() {
return this.replace(/#{(\w)}/g, function(match, s){return eval(s)})+"<br>";
};
var f="foo", b="bar"
p("#{f} #{b}")
document.write("#{f} #{b}".p());
=> foo bar
=> foo bar
EDIT: i added a prototype version, had some difficulties with that one
var myStr = [];
myStr.push('something')
console.log(myStr.join(""))
If you deal with lots of strings then using an array where you push the string parts and at the end join them (with an empty string as delimiter) seems to be the most efficient across platforms.
"Is there a JavaScript equivalent of rubys “#{}” sequences?"
With respect to an equivalent, no. JavaScript natively does not have string interpolation. Though you could use a function to replicate it to some degree.
pylover's answer will give you something like what you want.
You might also look into CoffeeScript, which is a nice language that compiles to JavaScript and has string interpolation, among other (perhaps too many) features.
It is called syntactic sugar.
var a = 2;
var b = 4;
var c = "together";
var text = `Add ${a*b} elements ${c}.`;
console.log(text)
// "Add 8 elements together." (515,988,604 op/sec)
vs.
var text = "Add" + " " + a*b + " " + "elements" + " " + c + ".";
console.log(text)
// "Add 8 elements together." (511,188,184 op/sec 0.73% slower)
First method is faster and better to read.
Performance tested here: JSPerf string test
I'm trying to achieve the following though with my intermediate JavaScript skills I'm not sure if this is possible.
This is related in part to this question.
Now I have 2 arrays
a) Has the various language in (e.g. "en-GB", "fr", "de" etc)
b) Has a suffix of a URL based on the browser language above (e.g. "fr/","de/","uk/")
What I am trying to achieve is:
1) User hits a page, browser detects which browser it is using from the array (a)
2) Depending on what the browser is based on (a), it then searches through (b) and if they match, e.g. if the language is "fr" it will use the suffix "fr/" from the array in (b).
3) It will then add this suffix to a top level domain (which is always constant)
Is this even possible to achieve (I'm sure it is)? Can it be done purely via JavaScript (or JQuery)? How would I go about doing this?
Here's some of the code I have so far:
var IAB_Array = new Array("de-at","nl-be","fr-be","da","de","hu","en-ie","ga","es","fr","it","nl","no","pl","en","en-GB","en-US","en-gb","en-us"); //language array
var IAB_suffix = new Array("at/","be-nl/","be-fr","den/","de/","hu/","ie/","es/","fr/","it/","nl/","nor/","pl/","uk/"); //URL suffix Array
var IAB_lang = "en-GB"; //default language
var IAB_link = "http://www.mysitegoeshere/";
if(navigator.browserLanguage) IAB_lang = navigator.browserLanguage; //change lang if detection supported
if(window.navigator.language) IAB_lang = window.navigator.language; //change lang if detection supported
function IAB_Lang_detect () { //execute search
for (var i=0;i<IAB_Array.length;i++) {
if(IAB_Array[i]==IAB_lang) {
document.write(IAB_Array[i]); //output matched array value
}
}
return false;
}
var IAB_URL = ""+IAB_link+IAB_suffix[1]+""; //this is the resulting URL
document.write(IAB_URL);
IAB_Lang_detect ();
I hope someone can help as I'm a little confused! It's more so the matching the values from the 2 arrays and then subsequently selecting the correct suffix that I'm having trouble with.
Thanks
(function () {
"use strict";
var lang_map = {
"de-at": "at/",
"nl-be": "be-nl/",
"fr-be": "be-fr",
"da": "den/",
"de": "de/",
"hu": "hu/",
"en-ie": "ie/",
"ga": "ie/",
"es": "es/",
"fr": "fr/",
"it": "it/",
"nl": "nl/",
"no": "nor/",
"pl": "pl/",
"en": "uk/",
"en-GB": "uk/",
"en-US": "uk/",
"en-gb": "uk/",
"en-us": "uk/"
},
lang = (navigator && navigator.browserLanguage) || (window.navigator && window.navigator.language) || "en-GB";
window.location = "http://www.mysitegoeshere/" + lang_map[lang];
}());
I'd do it differently and use an object:
var IAB_Object = { "it-It": "it/", "en-Gb": "en/" ....}
if(IAB_Object.hasOwnProperty(IAB_lang)){
//you have a match, the suffix is
var suffix = IAB_Object[IAB_lang];
}else{
//you don't have a match use a standard language
}
I probably wouldn't use arrays for this at all. You can use an object:
var IABInfo = {
"de-at": "at/",
"ln-be": "be-nl/",
// ...and so on
};
Then index directly into that object:
var value = IABInfo[IABLang]; // Where IABLang contains a string, like "de-at"
So:
var suffix = IABInfo[IABLang];
if (suffix) { // Did we have it?
document.write(suffix);
}
This works because all JavaScript objects are free-form key/value maps. Here's a simpler example:
var lifeTheUniverseAndEverything = {
answer: 42,
question: "?"
};
You can look up a property either using dotted notation with a literal, or by using square bracket ([]) notation with a string. So all four of these output exactly the same thing:
// 1. Dotted notation with a literal:
console.log("The answer is " + lifeTheUniverseAndEverything.answer);
// 2. Bracketed notation with a string
console.log("The answer is " + lifeTheUniverseAndEverything["answer"]);
// 3. The string needn't be a literal, it can come from a variable...
var name = "answer";
console.log("The answer is " + lifeTheUniverseAndEverything[name]);
// 4. ...or indeed any expression:
console.log("The answer is " + lifeTheUniverseAndEverything["a" + "n" + "swer"]);
So by making your IAB info a map in an object literal, you can make it much easier to look things up: Just use bracketed notation with the desired language code.