Javascript regex replace in-string variable with actual variable value - javascript

I would like "category/[categoryName]/[amount]" to become "category/movies/all" (replace "[variable-name]" with the value of the variable with the same name). I have this so far but I'm missing something:
let categoryName = "movies"; // example variable, set somewhere else
let amount = "all"; // example variable, set somewhere else
...
let searchUrl = "category/[categoryName]/[amount]"; // Set dynamically, could be any params
let regex = /\[(.+?)\]/ug;
searchUrl = searchUrl.replace(regex, window['$1']);
but the value of searchUrl just becomes "category/undefined/undefined".
Is what I'm trying to do even possible? Was that asked before and my question title is just malformed? I know how to do this with 2 regexes, first getting the variable names then looping in them and substituting. However I would like to do it with one "replace" only. Is that possible or I have to use 2 regexes?

If I understand correctly for this to work as dynamically as you state you will have to do the following
// example variable, you need to use var so its
// available on the window otherwise this will not work
var categoryName = "movies";
...
let searchUrl = "category/[categoryName]/all";
let regex = /\[(.+?)\]/ug;
let variableName = searchUrl.match(regex)[0];
searchUrl = searchUrl.replace(regex, window['variableName']);
Your dynamic variable will have to be stored globally for this work!

You're so close! What you have now tries to replace [categoryName] with the global variable $1, which doesn't exist. What you want is to use searchUrl.replace(regex, categoryName), assuming categoryName is dynamically set with the correct category.

It seems that with .replace you can enter multiple 'replacers', so you could say str.replace(regex, replacer1, replacer2, replacer3...). Alternatively, you can pass a function to replace a matched value each time one is found.
I just modified your code to:
let categoryName = "movies"; // example variable, set somewhere else
let amount = "all"; // example variable, set somewhere else
// previous answer suggestion
// let replacers = [categoryName, amount];
let searchUrl = "category/[categoryName]/[amount]"; // Set dynamically, could be any params
let regex = /\[(.+?)\]/gu;
let replacers = searchUrl.match(regex).map( m => m.replace(/\[|\]/g,''));
searchUrl = searchUrl.replace(regex, () => { let val = eval(replacers.shift()); return val; });
output => "category/movies/all"
Since your regex is global, it continues to find matches but since there is only 1 replacer in your original code, it replaces the match with that replacer.
i.e. categories/undefined/undefined (using searchUrl.replace(regex, window['$1']);)
You may want to put your replacers into an array. Then with each match, use a function to replace the match with the value stored in the array, as shown in my example above.
Note: This example works for 2 matches only.
Hope this helps.
MDN - Specifying a function as a parameter

Related

Why do the values not change in an Array after processing in for.Each?

I have 4 different values (strings) in JavaScript. I need to make a check, if one of these values is not a number. If so, then replace the value with "---", if not, do nothing. So I put the values in an array and called the forEach-function to check. So I actually want my predefined variables (before putting them in an array) to change if they are not a number, but only the elements of the array change.
So I did some researches and I found the difference between call-by-reference and call-by-value. So I changed my variables to String-Objects, but it does not work.
I know, hat calling the elements of my array would also work, but I want to understand why my actual variables does not change
?
var first = new String("1");
var second = new String("2");
var third = new String("3");
var fourth = new String("test");
var testArr = [first, second, third, fourth];
testArr.forEach(function (value, index) {
if (isNaN(value)) {
this[index] = "---";
}
}, testArr);
console.log(fourth);
//*here I expect "---" but it is "test"*
//I know that testArr[3] is now "---", but why not the variable fourth as well?
Value stored in variables will never be changed, because in your case variable host value itself, not reference. If you want to apply this kind of magic, you should:
Put initial values in array/object
Use objects instead of typed variables e.g:
var first = {value:'1'};
var second = {value:'2'};
var third = {value:'3'};
var fourth = {value:'replaceme'};
var testArr = [first, second, third, fourth];
testArr.forEach(function (obj, index) {
if (isNaN(obj.value)) {
obj.value = "---";
}
});
console.log(fourth);

My variables wont save in the array, they get replaced? help me

I am trying to save my variables in an array. Theses variables are written in by the user and saved to localStorage when a button is pressed. On my other html page i reach these variables and put them in 3 different arrays(the variables, that go in three arrays). Then the user writes in new text and save to the variables. Now to the problem. The newly created variables don't add to the array, they replace. I'm thinking this is due to to the same variable name however I can't find an solution.
I have tried to change variable names etc for saving the new variable but cant find solution.
//This is html page 2 (gets the items from localhost)
var TankaKostnadVar = localStorage.getItem("StorageKostnadVar");
var TankaLiterVar= localStorage.getItem("StorageLiterVar");
var TankaDatumVar = localStorage.getItem("StorageDatumVar");
var arrayKostnad = [];
var arrayLiter = [];
var arrayDatum = [];
arrayKostnad.push(TankaKostnadVar,);
arrayLiter.push(TankaLiterVar,);
arrayDatum.push(TankaDatumVar,);
document.write(arrayLiter,arrayKostnad,arrayDatum); //Ignore this, just test
//This is the code where the user is writing and it saves to localStorage.
//Html page 1 that saves the variables
var TankaKostnadVar = document.getElementById("tankaKostnad").value;
var TankaLiterVar = document.getElementById("tankaLiter").value;
var TankaDatumVar = document.getElementById("tankaDatum").value;
localStorage.setItem("StorageKostnadVar", TankaKostnadVar);
localStorage.setItem("StorageLiterVar", TankaLiterVar);
localStorage.setItem("StorageDatumVar", TankaDatumVar);
I expect the array to add the variable. So if the user writes an 5 the array should first be [5] then when the user writes an 8 the array should be [5,8]
If you don't want use JSON, you can save string comma separated and, when necessary, transform the items to numbers. To transform in numbers you can use map function or a for. Localstorage only save strings, so if you need to be back to numbers you need to use JSON.parse or use function parseInt, that is global.
//Retrieve saved items from localstorage
var TankaKostnadVar = localStorage.getItem("StorageKostnadVar"); // "1,2"
var TankaLiterVar = localStorage.getItem("StorageLiterVar");
var TankaDatumVar = localStorage.getItem("StorageDatumVar");
TankaKostnadVar += "," + document.getElementById("tankaKostnad").value;
TankaLiterVar += "," + document.getElementById("tankaLiter").value;
TankaDatumVar += "," + document.getElementById("tankaDatum").value;
localStorage.setItem("StorageKostnadVar", TankaKostnadVar);
localStorage.setItem("StorageLiterVar", TankaLiterVar);
localStorage.setItem("StorageDatumVar", TankaDatumVar);
// if you want to transform TankaKostnadVar and others two, just do like this
TankaKostnadVar.split(','); // result: ['1', '2']
// if you want to transform to number
TankaKostnadVar = TankaKostnadVar.split(',').map( function(number) {
return parseInt(number)
} );
The split function of string, breaks a strings in parts separated by one string. In this case, breaks a string separated with comma. So "1,2" turns into ['1', '2'].
If you want to keep adding to the array you'll need to push the entire array you're holding in memory up to localStorage after appending a new element. Alos, localStorage only stores string values so if you want to maintain the Array structure you'll have to use JSON.stringify() before running setItem() and then JSON.parse() next time you access those values with getItem().
//This is the code where the user is writing and it saves to localStorage.
//Html page 1 that saves the variables
var TankaKostnadVar = document.getElementById("tankaKostnad").value;
var TankaLiterVar = document.getElementById("tankaLiter").value;
var TankaDatumVar = document.getElementById("tankaDatum").value;
localStorage.setItem("StorageKostnadVar", JSON.stringify( [TankaKostnadVar] ));
localStorage.setItem("StorageLiterVar", JSON.stringify( [TankaLiterVar] ));
localStorage.setItem("StorageDatumVar", JSON.stringify( [TankaDatumVar] ));
//This is html page 2 (gets the items from localhost)
var TankaKostnadVar = localStorage.getItem("StorageKostnadVar");
var TankaLiterVar = localStorage.getItem("StorageLiterVar");
var TankaDatumVar = localStorage.getItem("StorageDatumVar");
var arrayKostnad = JSON.parse(TankaKostnadVar);
var arrayLiter = JSON.parse(TankaLiterVar);
var arrayDatum = JSON.parse(TankaDatumVar);
// Now you have arrays with data, but I don't know what you want to do with them...
// you could add more values like this (still page 2)...
arrayKostnad.push('new value 1')
arrayLiter.push('new value 2')
arrayDatum.push('new value 3')
localStorage.setItem("StorageKostnadVar", JSON.stringify( arrayKostnad ));
localStorage.setItem("StorageLiterVar", JSON.stringify( arrayLiter ));
localStorage.setItem("StorageDatumVar", JSON.stringify( arrayDatum ));
// now check the values again
var TankaKostnadArr = JSON.parse(localStorage.getItem("StorageKostnadVar"));
var TankaLiterArr = JSON.parse(localStorage.getItem("StorageLiterVar"));
var TankaDatumArr = JSON.parse(localStorage.getItem("StorageDatumVar"));
document.write(TankaKostnadArr, TankaLiterArr, TankaDatumArr)
And this is what I would do to clean things up a little...
// Import these functions and variables to any file that needs to interact with LocalStorage
var storageKeys = ["StorageKostnadVar","StorageLiterVar","StorageDatumVar"];
function addToArray(key, val, arrObj) {
arrObj[key].push(val)
}
function storeAllLocalStorage(arrayObject) {
Object.keys(arrayObject).forEach(key=>{
localStorage.setItem(key, JSON.stringify(arrayObject[key]));
})
}
// Use above functions when needed
var storedArrays = storageKeys.reduce((acc,key)=> {
var val = JSON.parse(localStorage.getItem(key));
if (typeof val === 'array') return {...acc, [key]:val};
return {...acc, [key]:[val]};
},{})
addToArray("StorageKostnadVar", document.getElementById("tankaKostnad").value, storedArrays);
addToArray("StorageLiterVar", document.getElementById("tankaLiter").value, storedArrays);
addToArray("StorageDatumVar", document.getElementById("tankaDatum").value, storedArrays);
storeAllLocalStorage(storedArrays)
You are simply using localStorage.setItem which saves your values with the given key. If the key exists, it will replace the value. Before you do a .setItem, get the value from the local storage first, then parse it to array so that you can finally push the new user inputs to that parsed array. Then you can .setItem to replace the "outdated" value from the localStorage.
UPDATE Example:
Sorry for leaving this hangin without an example. Here it is:
// Get array from local storage
const stringifiedArray = localStorage.getItem('myCollection');
// If there is no 'myCollection' from localStorage, make an empty array
const myCollection = stringifiedArray ? JSON.Parse(stringifiedArray) : [];
myCollection.push('My new item added'); // update array
localStorage.setItem('myCollection', JSON.stringify(myCollection)); // save

Extract variable declarations from JavaScript file

I am trying to create a variable name exchanger. Simple iterating over lines from a JavaScript file and exchange every variable name with a random name from a dictionary i can supply.
I can do that so far, but i am stuck optimizing the search regex for variable keywords.
I first define Keywords which i am looking for:
const VARIABLE_KEYWORDS = ["var", "let", "const"];
Then i iterate over every line from the input file and extract the variable names and store them in an array. Once i have all variable names stored, i make them unique and then simply replace them in the original file with a random word.
That is my extractVariables(line) logic, where the variable line is a string:
function extractVariables(line) {
let lineCnt = 1;
let found_vars = [];
// if the line is not empty, parse it
if (line.trim().length !== 0) {
// find a variable keyword
for (let key of VARIABLE_KEYWORDS) {
// regex to match the variable keyword and its not inside a string definition \"|\' , and is not used as a property name |\.
var re = new RegExp("(?<!\"|\')\\b" + key + "\\b(?!\"|\')", "g");
// while there are variables declared in the line, add them to the variables array
while ((match = re.exec(line)) != null) {
const indexOfKeyword = match.index + key.length;
// get the name after and store it in an array
if (indexOfKeyword > 0) {
let found_var = line.substr(indexOfKeyword).trim().split(' ').shift();
// if a keyword is found, but no variable defined afterwards do not break everything
if(found_var.length !== 0){
found_vars.push(found_var);
}
}
}
}
}
return found_vars;
}
My regex is missing some fixes.
new RegExp("(?<!\"|\')\\b" + key + "\\b(?!\"|\')", "g");
The lookbehind is not supported.
KEYWORDS inside a String like "foo var let me be" are still found, i only fixed it if they are the only word next to a " or '
Scopes {} are ignored
Can someone help me out please?

Global var in JavaScript

This is annoying me.
I'm setting an array in beginning of the doc:
var idPartner;
var myar = new Array();
myar[0] = "http://example.com/"+idPartner;
And I'm getting a number over the address, which is the id of partner. Great. But I'm trying to set it without success:
$.address.change(function(event) {
idPartner = 3;
alert(idPartner);
}
Ok. The alert is giving me the right number, but isn't setting it.
What's wrong?
Changing the value of the variable does not re-set the values within the array. That is just something javascript can't do automatically. You would have to re-generate the array for it to have the new id. Could you add the id to the value where you use the array instead of pre-setting the values in the array containing the id?
Edit: For example, you would do:
var myArray = [];
var myId = 0;
myArray[0] = "http://foo.com/id/";
and when you need to use a value from the array, you would do this:
var theVal = myArray[0] + myId;
Try this:
var myvar = ["http://site.com/"];
$.address.change(function(event) {
myvar[1] = 3;
}
then use myvar.join () where you need the full url.
The problem here is that at the line
myar[0] = "http://site.com/"+idPartner;
..you perform a string concatenation, meaning you copy the resulting string into the array at index position 0.
Hence, when later setting idPartnerit won't have any effect on the previously copied string. To avoid such effect you can either always construct the string again when the idPartnervariable updates or you create an object and you evaluate it when you need it like...
var MyObject = function(){
this.idPartner = 0; //default value
};
MyObject.prototype.getUrl = function(){
return "http://site.com/" + this.idPartner;
};
In this way you could use it like
var myGlblUrlObj = new MyObject();
$.address.change(function(event){
myGlblUrlObj.idPartner = ... /setting it here
});
at some later point you can then always get the correct url using
myGlblUrlObj.getUrl();
Now obviously it depends on the complexity of your situation. Maybe the suggested array solution might work as well, although I prefer having it encapsulated somewhere in an object for better reusability.
myar[0] = "http://site.com/" + idPartner;
After this line, myar[0] = "http://site.com/undefined" and it has nothing to do with the variable idPartner no more.
So, after that changing the value of idPartner will affect the value of myar[0].
You need to change the value of myar[0] itself.

Form value addition with js

I'm trying to write a order form that shows the value of the selected items automatically. The backend is already complete, and on the front end each field, all radio / checkbox, look like this:
<input type="radio" name="shirt-size" value="shirt_size_m[18]" />
'18' being the price, everything else being irrelevant to the front end price calculation. I cannot change the naming convention, so I need to get the value between the brackets on all the <input>s on the page (or below the parent ID), add them together (on update), and append the value to another ID. Jquery is already in use on the site if that makes thongs easier.
I just need to be pointed in the right direction as my JS experience is limited to examples and minor customizations :)
Try using a simple regular expression with Javascript's replace, to replace all non-numeric characters with the empty string:
var str = "shirt_size_m[18]";
var theNumber = parseInt(str.replace(/[^0-9]/g, ''));
alert(theNumber);
Demo: http://jsfiddle.net/XvTaY/1/
You could try something like this:
function calculate_sum(form_id) {
var $form = $(form_id);
var sum = 0;
$checkbox_and_radios = $form.find('input[type=checkbox], input[type=radio]').each(function(){
sum += parseInt($(this).val().match(/^[^\[]+\[(\d+)\]$/)[1]);
});
return sum;
}
$(function(){
$("#id_of_the_form").find('input[type=checkbox], input[type=radio]').change(function(){
var sum = calculate_sum("#form_id");
// I don't know the type of your element containing
// the sum, so I put multiple solutions here:
// some input element
$('#another_id').val(sum);
// or another element
$('#another_id').html(sum);
// I'm assuming you don't really mean append
// If you're sure you want to append: (but then the old value won't be deleted)
$('#another_id').append(sum);
});
});
u can use:
var v;
v = $('#input-identifier').val();
v = v.split("[");
v = v[1];
v = v.split("]");
v = v[0];
// now v has the number

Categories