js dynamic regular expr [duplicate] - javascript

This question already has answers here:
Template literal inside of the RegEx
(2 answers)
Closed 1 year ago.
hi I am coding an online shop ,
currently working on add to cart functionality,
like to store product ids and their quantity in a cookie like this id1:qt1,id2:qt2...
like to check if a product is already is in cart , looks like my regular expr doesn't work
const reg = new RegExp(`${product_id}:\d+`);
if (!reg.test(cart_cookie)){
const values = cart_cookie.split(',');
values.push(`${product_id}:1`);
setCookie('cart', values.join(','), 7);
}
else {
console.log('already in cart.')
}

Yep, your regex is off :)
It stumped me for a second, but its clear when you check what your "regex" string actually evaluates to: /product_id:d+/. This is because the string you're passing in sees the \d as a literal d. To fix this, just throw another \ in there so the original \ is whats being escaped. Before, you were matching things like "apple:ddddddd".
Once you do that, your code DOES seem to work, but maybe just not like you expect it to?
I've put your code into a function, since you would -- presumably -- be calling this every time you want to add an item to the cart, and added a console.log statement to show the end value of the "cookie."
// Just as a stand in for actual values
let cart_cookie = 'apples:2,oranges:3,bananas:1';
function addCartItem(product_id) {
const reg = new RegExp(`${product_id}:\\d+`);
console.log(reg)
if (!reg.test(cart_cookie)){
const values = cart_cookie.split(',');
values.push(`${product_id}:1`);
console.log('cart_cookie is now ', values.join(','));
setCookie('cart', values.join(','), 7);
}
else {
console.log('already in cart.')
}
}
addCartItem('apples');
// already in cart.
addCartItem('kiwis');
// cart_cookie is now apples:2,oranges:3,bananas:1,kiwis:1
Its fixed! 🥳 But...
I'm not quite sure what your product ids look like, but if they contain special characters (e.g. periods, question marks, etc.) it'll cause some issues with how your regex performs. I doubt you have things like question marks in it, but something like this illustrates my point:
let cart_cookie = '123.15:3,2.5.141:1';
/* ... */
addCartItem('1.3.15');
// already in cart.
I know, its a rather unlikely scenario -- and it might not even apply to you if you know your product ids won't contain anything tricky -- but if you're goal is to build an online shop, you'll probably want to cover all your bases.
Even fixing that, this still has a potential issue, as this will only let you add a quantity of 1 to an item thats not already in the cart, with no ability to increment it after that. Not sure if thats what you're going for.
This veers off of the main question you posed, but a potentially better solution might be using the browser's localstorage (or sessionstorage) to keep track of the cart. This would allow you to use more familiar data structures to store this info, rather than a string that you have to pray you're parsing correctly.
More info on that here: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage

you can use just array method instead you don't need for regex for that,
for example..
const values = cart_cookie.split(',');
values.foreach(value => {
if(value != product_id){
values.push(`${product_id}:1`);
setCookie('cart', values.join(','), 7);
}
});

Related

String separation and combining

I have a challenge that I am trying to solve and cannot seem to come up with a solid solution.
I have 3 records like this:
"a,b,c,d,e","1,2,3,4,5","record 1"
"f,g,h,i","11,12,15,16","record 2"
"x,y,z","19,20,21","record 3"
Looking to create this output
"a,1"
"b,2"
"c,3"
"d,4"
"e,5"
...
...
"y,20"
"z,21"
How would I go about this using java-script or
I have have worked out how to separate each string but collecting both substrings and looping through seems to be a challenge.
This can get a little bit Tricky if you dont have a constant format.
In this example i have two strings and each sub-string is separated by ",".
Also both strings should be the same length.
I return the result as an array here. You can append it to a existing string instead.
s1 = "1,2,3,4,5";
s2 = "a,b,c,d,e";
s3 = [];
for(i=0; s1.length>i;i++){
if(s1[i] != ","){
s3.push(s1[i]+","+s2[i]);
}
}
console.log(s3);
Since im not sure if i did understand the Question correctly...
If you dont understand something or the answer is not what you excepted, let me know in the comments and i will try to adapt to it.

How to allow for another index string to run a script

I have no script abilitiy, but i'd like to edit an existing script which is currently restricting the script from running on any page other then the one that has a certain string in the URL.
Here is the snippet of the script which limits it from running
if(location.href.indexOf("MODULE=MESSAGE")>0||location.href.indexOf("/message")>0)
This only allows the script to run on these pages
mysite/2014/home/11609?MODULE=MESSAGE1
and the pages range from Message1 to Message20
mysite/2014/home/11609?MODULE=MESSAGE20
I would like to also allow the script to be loaded and ran on these pages
mysite/2014/options?L=11609&O=247&SEQNO=1&PRINTER=1
where the SEQNO=1 ranges from 1 to SEQNO=20, just like the MESSAGE1-MESSAGE20 do
Can someone show me how i can edit that small snippet of script to allow the SEQNO string found in the url to work also.
Thanks
If you can't just remove the condition altogether (there's not enough context to know if that's an option), you can just add another or condition (||) like so:
if(location.href.indexOf("MODULE=MESSAGE")>0
||location.href.indexOf("/message")>0
||location.href.indexOf("SEQNO=")>0)
Note that the second clause there isn't actually being used in any of your examples, so could potentially be removed. Also note that this isn't actually checking for a number so it isn't restricted to Message1 to Message20 as you suggest. It would match Message21 or even MessageFoo. That may or may not be a problem for you. You can make the conditions as restrictive or as lose as makes sense.
If you just want to check for the existence of "SEQNO", simply duplicate what is being done for "MODULE_MESSAGE".
if(location.href.indexOf("MODULE=MESSAGE")>0 ||
location.href.indexOf("SEQNO=")>0 ||
location.href.indexOf("/message")>0)
If you want to also ensure that "MESSAGE" ends in 1-20, and "SEQNO=" ends in 1-20, you can use a regex.
// create the end part of the regex, which checks for numbers 1-20
var regexEnd = "([1-9]|1[0-9]|20)[^0-9]*$";
// create the individual regexes
var messageRegex = new RegExp("MODULE=MESSAGE" + regexEnd);
var seqnoRegex = new RegExp("SEQNO=" + regexEnd);
// now comes your if statement, using the regex test() function, which returns true if it matches
if(messageRegex.test(location.href) ||
seqnoRegex.test(location.href) ||
location.href.indexOf("/message")>0)

Regex replace anything but numbers with increments letter using javascript

I have an equation/formula stored in database and I want it to be triggered based on key up input event in a webpage.
Example formula: [55-57]
This is a simple minus operation, where the number actually represents the id of a row in database
I have looked at this solution which replaces numbers found in a string to new value. But I need the new value to be replaced with incremented letters such as a, b and so on. Also the leading and ending brackets [] need to be removed so that I can perform an eval later using JavaScript.
Later the equation will be convert to a-b. Variable a and b represent other HTML elements that holds a value. So whenever I key in something into text field, changes will reflect on other part of webpage. It's like auto computation.
Thank you for those helping this. Hope this question will help somebody.
Try something like this. If you need more help, you seriously need to re-word your question or post a jsfiddle, or something.
var eqn = '55-57'; // brackets removed. Remove them with a regex of /\[|\]/g if you need to
var result = eval( eqn.replace( /\w+/g, function( res ){
return +document.getElementById( res[1] );
} );
Basically this replaces 55 and 57 with the numerical values of #55 and #57. It would also work for #b, etc.
It then eval's the result, basically doing whatever math is in your equation.

Why do lots of programmers move commas to the next line? [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 3 years ago.
Improve this question
Tell me please, what is the sacred power of the style below:
var javascript = new Language(
'Brendan Eich'
, new Date(1995, 0, 1)
, ['C', 'Java', 'Scheme']
);
Why do lots of programmers use that style? What benefits does it have? For example,
var javascript = new Language(
'Brendan Eich',
new Date(1995, 0, 1),
['C', 'Java', 'Scheme']
);
I like much more than previous. Thanks.
Lots of great answers already. Allow me to give you my own one, to make things as clear as possible.
I personally call this way of writing code 'Haskel style', since it's a common style to use in Haskell. Let me give you a Haskell example first:
data Settings = -- The user settings
{ has_sound :: Bool -- Determines if the user has sound
, has_power :: Bool -- Determines if the user has electricity
, has_graphics :: Bool -- Determines if the user has graphics
, user_name :: String -- The name of the user
, user_password :: String -- The hashed password of the user
, user_email :: Email -- The email address of the user
, stylesheet :: Style -- The stylesheet to use
}
And a Javascript snippet from one of my projects:
var events // Holds the events to generate a event handler for.
, var2 // Quick description for var2.
, var3 // Quick description for var3.
, ... // ...
;
events = // Event handlers will be generated for the following events:
[ "onmousedown" // Works outside of the window element
, "onmouseup" // Works outside of the window element
, "onmousemove" // Works outside of the window element
, "onmousewheel" // This will handle DOMMouseScroll aswell
];
Benefits of 'Haskell style'
Easy to read
'Haskell style' takes advantage of the column style layout. This column style makes your code more readable. In fact, it makes your code so much more readable that you use it all the time. Imagine writing code without tabs or leading spaces!
By taking advantage of column style layout, variable names, types, etc. are easier to read aswell. By grouping up variables by prefix, our future reader will easily find what he is looking for, without using a advanced search query.
Easy to document
Column style layout has more advantages. By grouping up our code we can add a column reserved for comments. Now you can read your code without even needing color highlighting, and adding information to your comment is as easy as finding the right column and modifying it.
Besides, this column-like style of documenting your code is pretty much what you get after using a documentation generator like Doxygen, removing the necessity for this kind of tool.
Easy to notice mistakes
Noticing a missing comma is a piece of cake using this style of coding. Simply look for a line that doesn't start with it! On the other side of the spectrum, we have the comma's at the end of the line. We missed one? Nope, because it is the last element, or because the expression continues on the next line.
And finding the first element in a list is as easy as could be. When dealing with long lines, the first element is easily overlooked, but by placing the first element on it's own line and puting a [ or { instead of a , right in front of it, it's easy to spot.
Easily scalable
You might say "But this layout style will get imposible to handle once the expression gets big!", which is quite true, but is this any different for the rest of your code?
I think that by using column style you will at least keep your code readable, which in the long run is worth more than the struggle you might have to fit it into a column layout.
All in one example!
var scalable = // This is a example variable
[
[ new MyObject // This is how I would style Object Allocation
( "11"
, "This is the first element"
, function // This is a very secret function...
( secret // ..with secret..
, variable // ..variable..
, names // ..names!
)
{
// <-- Use spaces, not tabs :)
}
)
, "12"
]
,
[ { id: 21 // Where's 20?
, name: "This is the third element" // It sure is
, func: function() { /* My body feels empty :c */ }
}
, "22" // Notice how 21 is a integer, not a string. Sneaky!
]
];
TL; DR
This style of placing comma's, 'Haskell style', has a couple of advantages:
Easy to read
Easy to document
Easy to notice mistakes
Easily scalable
If you have an extra comma in the end of the last line it will work in some browsers but not in all browsers. Making the error harder to detect than a extra comma at the beginning (which fails on all browsers). And most developers prefer to see the error right away (so they can fix it), instead of risking a production issue for inadvertently not supporting some browsers. Especially if the solution is as easy as removing a comma.
Plus, having the comma at the beginning of the line, make it simpler to add a line at the end and you will have to touch only that line (you will not need to add the comma in the line before). Which is important if you are using version control (e.g. diff, annotate, bisect). Someone can argue that adding a line at beginning of the array or object will need the same extra work of touching 2 lines (if you use commas at the beginning), but in my experience, inserting a line at the beginning is much less likely that inserting a line at the end.
This is because the comma belong to the new line next statement and not the previous one. (As #Dave Newton states it in his comment below: the pseudo-BNF would be foo [, foo]*-ish)
For example:
If you have this:
a,
b,
c
If you need to remove the c then you need to delete two things: de c and the comma on the previous line. If you do this:
a
,b
,c
now you only need to delete the ,c line. It makes more sense this way, because the comma behind the b in the first example only is needed because of the c. It does look worse this way though. It's a trade off between maintainability of your code and the way it looks.
I think it's done so that it's easier to spot a missed comma.
var something = 0,
foo = "a string",
somethingElse = []
bar;
var something = 0
, foo = "a string"
somethingElse = []
, bar;
It is easier to just look at your code to verify you have a comma where needed. If you had to scan the end of each line of code the missing commas wouldn't just jump out like they do when they are lined up on the left hand side.
This offers a little bit of protection in languages which don't accept trailing commas from accidentally introducing syntax errors with trailing commas
In SQL, trailing commas will cause syntax errors. In JavaScript, it will be accepted most places, but will fail with a cryptic error in some Internet Explorer versions, for example.
JS works in most browsers, but fails in some
var thing = {
a: 1,
b: 2,
// trailing comma
c: 3,
};
Syntax error in SQL
SELECT
col1,
col2,
-- Syntax error in SQL
col3,
FROM table
It's one way to make sure you don't forget the comma when adding a new item to a collection, and don't accidentally leave on a trailing comma in collections.
By putting it on the new line it's visually obvious.
I don't care for it, but I understand why people would.
You might be looking at generated code, for instance, when writing a loop to generate an SQL select statement sometimes I will write it like:
sql = "SELECT";
sql += " table.id"; // or some field that will always be in the query
for (var i = 0; i < 10; i++;) {
sql += ", table.field" + i;
}
sql += "FROM table" // etc
Instead of adding the comma at the end and then having a condition to omit it on the last iteration of the loop or doing:
sql = "SELECT";
for (var i = 0; i < 10; i++;) {
sql += " table.field" + i + ",";
}
sql += " table.id";
sql += "FROM table" // etc
Which is functionally equivalent, but then the ID doesn't appear where I usually want it.
Maybe because removing or adding line and its commas is simpler with second example

Passing 2 URL Parameters?

I need to pass 2 URL parameters in a URL. The URL originates in an email and the user will click the link directing them to my site. The first parameter triggers a script on the page the second parameter is for a module my CMS will render from the parameter.
First Parameter is : message=1 (This parameter triggers the javascript)
The second Parameter is: name={tag_recipientfirstname} (My CMS will render the module)
The script that is called for the first looks like this:
<script type="text/javascript">
var $j = jQuery.noConflict();
$j(document).ready(function() {
var url = window.location.href;
url = url.toLowerCase();
if (url.indexOf('message=1') != -1) {
$j("a.message").colorbox({
open:true
});
}
$j("a.message").colorbox(); //not related to URL parameter
});
</script>
The second parameter is used on the page as:
<div>
<p>{ module_url,name} (again CMS will render this module)</p>
</div>
EDIT
I realize I left a couple things out:
First: How do I pass both parameters so they will both function as listed above?
And the CMS I am using is Business Catalyst.
//split the `location.search` string at the ampersands
var search_arr = window.location.search.replace('?', '').split('&'),
len = search_arr.length,
get_vars = {},
tmp = [];
//iterate through the key/value pairs and add them to the `get_vars` object
for (var i = 0; i < len; i++) {
tmp = search_arr[i].split('=');
get_vars[tmp[0]] = tmp[1];
}
//you can now access your GET variables through the `get_vars` object like: `get_vars.name`
//you can check for the existence of a certain GET variable like this
if (typeof(get_vars['message-1']) != 'undefined') {
$j("a.message").colorbox({
open:true
});
}
Here is a demo:http://jsfiddle.net/aBH8K/1/ (http://jsfiddle.net/aBH8K/1/show/?message-1=3 to see with get var)
Some related documentation:
window.location: https://developer.mozilla.org/en/DOM/window.location
Your question is not so much about generic development, rather a very specific commercial product; I do not know which plan you subscribed (free o pay-for?) with them but in any case it would be best to go through their support (see also my conclusion)
Nevertheless I'll try to put you on the right track.
Your questions
First,
the url in the email
In the email you will have somehow to build a link with the two parameters you want as #Jasper is explaining.
this means something like:
http://yourwebsite.com/destination/path/?message=1&name={tag_recipientfirstname}
Everything after the question mark is a GET query string.
Parameters are separated by the "&" symbol.
I definitely don't know how properly build urls in BC emails, but I feel like it should be an automated somewhere allowing you to specify additional parameters if you need.
the javascript
What you got will still work. It's not very nice, and you can use Jasper's solution or any other such as How can I get query string values in JavaScript?
Nothing to do then unless you want to make it better and more robust.
Business Catalyst (the page)
You usually have ways in a CMS to retrieve get parameters. Often something like
{ GET.param_name }
One step back
I am no expert with BC, but I have the feeling that you are taking a complicate path for something that is probably already baked in.
Again I suggest you go into their support section (though it's rather confusing I must say!) and try to understand what's the best way to achieve your objective. There are always many ways to skin a poor cat.
If you are getting support in your plan, definitely go that way and try to explain what you objectives are rather then how to achieve the technical solution that you think is the good one!

Categories