I'd like to have on an ecommerce product page the simple "in stock" or "out of stock" message, but the ERP solution that I've to use only permit to retrive from its db the number of items currentrly in stock.
I can only use JS, so I'm thinking to a small function that will search for the string I have, extract only the number, do an if/else in order to replace a trigger id with the proper content.
here the content of the function:
var strAval = strAval.search (/\<div id\=\"\#avail\" class\=\"hidden\"\>/ + /\d+/ + /<\/div>/);
var strAval2 = strAval.substring (32,-6);
if (strAval2 > 0) {
var str = document.getElementById("#in-stock").innerHTML;
var res = str.replace("#in-stock","IN STOCK");
document.getElementById("#in-stock").innerHTML = res;
}
else {
var str = document.getElementById("#in-stock").innerHTML;
var res = str.replace("#in-stock","OUT OF STOCK");
document.getElementById("#in-stock").innerHTML = res;
}
the string that I've into the html is:
<div id="#avail" class="hidden">329</div>
where "329" is an example - this number is variable from 1 to 4 digits [ 0 - 12 - 329 - 2654 ]
There's something wrong, but I don't know what.
I'm learning JS, so I'm really new to it.
Thanks to all.
Related
I need some assistance figuring out how to sum a column of dynamic totals that could be a positive or negative dollar amount, or an indication of stock shares.
I have a tab-delimited text file of donor contributions for that I am matching up against a CSV file of other related customer data that I am using to create a statement letter which will show a "donation history" of a particular donor. Each donor has a different amount of donations, and to complicate things, the column of data for a particular donation record could show either "$1,000.00" or "($1,000.00)" or "2 Shares APPL". The number with the parentheticals is of course, representing a negative number.
At the end of this column, I need to show a string that will read either "Total: $1,000.00," or if any of the donation history contains a donation record that included shares of stock the returned string will simply read, "$1,000.00 & Stock."
I have been racking my brain trying to come up with the JS rule that can achieve this. I have the JS rule that is generating the donation history correctly, but summing the donation amount column is causing me to go crazy...
Here is the JS for generating my donation history list in the letter (this seems to be working fine):
var contributionList = new ExternalDataFileEx("/~wip/248839 Frontiers/Master Data/Double Data proof.txt", "\t");
var donor_id = Field("Supporter");
var lb = "<br>\n";
var matches = new Array();
for (var i = 0; i <= contributionList.recordCount; i++) {
var idVariable = contributionList.GetFieldValue(i, "Supporter");
var dateVariable = contributionList.GetFieldValue(i, "Donation Date");
var ministryVariable = contributionList.GetFieldValue(i, "Ministry Designation");
var giftVariable = contributionList.GetFieldValue(i, "Donation Amount");
var tsSettings = "<p tabstops=19550,Right,,;29600,Left,,;>";
var ts = "<t>";
if (donor_id == idVariable)
matches.push(tsSettings + dateVariable + ts + giftVariable + ts + ministryVariable);
}
//return matches;
return matches.join(lb);
Now here is the JS code that is not working just fine. I am trying to tally the donation amount column, it only returns "Total: $0.00 & Stock" every time (I have tried to explain my thought process via comments):
var contributionList = new ExternalDataFileEx("/~wip/248839 Frontiers/Master Data/Double Data proof.txt", "\t");
var donor_id = Field("Supporter");
for (var i = 0; i <= contributionList.recordCount; i++) {
var idVariable = contributionList.GetFieldValue(i, "Supporter");
var giftVariable = contributionList.GetFieldValue(i, "Donation Amount");
var sum = 0;
var shares = 0;
var tsSettings = "<p tabstops=19550,Right,,;29600,Left,,;>";
var ts = "<t>";
var totalStr = "Total ";
var stockStr = " & Stock";
var totalFormatted = FormatNumber("$#,###.00", Math.max(0, StringToNumber(sum)));
// Match data from linked file to current Supporter
if (donor_id == idVariable) {
// Look at current record and see if it contains the word "Share(s)"
// or not and act accordingly
if (giftVariable.match(/(^|\W)share($|\W)/i) || giftVariable.match(/(^|\W)shares($|\W)/i)) {
// Turn switch "on" if donation amount is a share or shares so
// we can have the " & Stock" appended to our string.
shares = 1;
// Because this donation is/are shares, we must "zero" this
// amount to make the math work when we sum everything up...
giftVariable = 0;
// This is where we are keeping our running total...
sum += giftVariable[i];
} else {
// This record was not a donation of share(s) so we now have to
// determine whether we are dealing with postive or negative numbers
// and then strip out all of the non-number characters, remove and
// replace the () whis just a "-," leaving us with a number we can
// work with...
// If number has parenthesis, then deal with it...
if (giftVariable.indexOf("(")) {
// Strip out all the ()$, characters...
giftVariable = giftVariable.replace(/[()$,]/g,"")
// Append the minus sign to the number...
giftVariable = "-" + giftVariable;
sum += giftVariable[i];
} else {
giftVariable = giftVariable.replace(/[$,]/g,"");
sum += giftVariable[i];
}
}
}
}
// Return Total...
if (shares == 1) {
return tsSettings + totalStr + ts + totalFormatted + stockStr;
} else {
return tsSettings + totalStr + ts + totalFormatted;
}
Any assistance would be greatly appreciated!
The problem (and code) needs to be broken into smaller, atomic steps. From your description it sounds like you should:
load a text file into memory
for each line in the file
extract: {
donor_id
charity
gift
and store the results in a contributions dictionary
for each item in the contributions dictionary
transform gift string into {
dollarAmount: float with a default of 0.0
stock: name with a default of ""
}
create an empty dictionary called totals
each item will have the shape {
id
dollarAmount as a float
stocks an an array
}
for each item in the contributions dictionary
lookup the id in the totals dictionary
if it exists
totals[id].dolarAmount += item.dollarAmount
totals[id].stocks.push(item.stock)
otherwise
totals[id].dollarAmount = item.dollarAmount
totals[id].stocks = [item.stock]
normalize your charities
for each item in totals dictionary
remove any empty strings from item.charities
create your report
for each item in totals dictionary
write`${item.id} donated `${item.dollarAmont}` ${item.stocks.length > 1 ? 'and stock' : ''
I believe you are trying to do too many things at once. Instead, the goal should be to normalize your data before you attempt to perform any calculations or aggrgrations, then normalize your aggregrations before writing your summaries or reports.
I would also stay away from using any direct string manipulation. You should have a dedicated function whose only purpose is to take a string like "($20.34) and 1 share of APPL" and return either 20.34, -20.34, or 0.0. And a different function whose only purpose is to take the same string and return either true or false is stock was present.
I'm currently making a chatbox in JQuery. I've been using indexOf but I think it might be more efficient to use regExp.
my current code is
function ai(message){
if (username.length<3){
username = message;
send_message("Nice, to meet you " + username + ", how are you doing?");
}
if(message.indexOf("how are you?")>=0) {
send_message("I'm feeling great!");
}
if(message.indexOf("weather")>=0 ){
send_message("In England it is shitty");
}
var n = message.search(/\b(cat|cats|kitten|feline)\b/i);
if (n !== -1) {
send_message("i hate cats");
}
else {
for (i=0; i <= botChat.length; i++) {
var re = new RegExp (botChat[i][0], 'i');
if (re.test(message)) {
var length = botChat[i].length - 1;
var index = Math.ceil( length * Math.random());
var reply = (botChat[i][index]);
send_message(reply);
}
}
}
}
and a typical line from my array is
new Array ("I need (.*)\." , "Why do you need $1?", "Would it really help you to get $1?" , "Are you sure you need $1?"),
i'm trying to demonstrate the ways of creating a chatbot. The first four responses work perfectly
it takes a name, comments on the weather and can search for cats. What it can't do is perform the loop. Has anyone any suggestions?
This is a follow on from my previous question which can be found here
Link For Previous Question
I am posting a new question as the answer I got was correct, however my next question is how to take it a step further
Basically I have a string of data, within this data somewhere there will be the following;
Width = 70
Void = 40
The actual numbers there could be anything between 1-440.
From my previous question I found how to identify those two digits using regular expression and put them into separate fields, however, my issue now is that the string could contain for example
Part Number = 2353
Length = 3.3mm
Width = 70
Void = 35
Discount = 40%
My question is;
How do I identify only the Width + Void and put them into two separate fields, the answer in my previous question would not solve this issue as what would happen is in this example I would have an array of size 4 and I would simply select the 2nd and 3rd space.
This is not suitable for my issue as the length of array could vary from string to string therefore I need a way of identifying specifically
Width = ##
Void = ##
And from there be able to retrieve the digits individually to put into my separate fields
I am using JavaScript in CRM Dynamics
A simpler option is to convert the whole string into an object and get what you need from that object.
str = "Part Number = 2353\n" +
"Length = 3.3mm\n" +
"Width = 70\n" +
"Void = 35\n" +
"Discount = 40%\n";
data = {};
str.replace(/^(.+?)\s*=\s*(.+)$/gm, function(_, $1, $2) {
data[$1] = $2;
});
alert(data['Width']);
Width\s+=\s+(\d+)|Void\s+=\s+(\d+)
You can try this.Grab the capture.See demo.
http://regex101.com/r/oE6jJ1/31
var re = /Width\s+=\s+(\d+)|Void\s+=\s+(\d+)/igm;
var str = 'Part Number = 2353\n\nLength = 3.3mm\n\nWidth = 70\n\nVoid = 35\n\nDiscount = 40%';
var m;
while ((m = re.exec(str)) != null) {
if (m.index === re.lastIndex) {
re.lastIndex++;
}
// View your result using the m-variable.
// eg m[0] etc.
}
You can use this regex for matching input with Width and Void in any order:
/(\b(Width|Void) += *(\d+)\b)/
RegEx Demo
Your variable names and values are available in captured groups.
I have two fields that I'd like to match. (already done the validation functions for field 1 and 2)
field01 has a client number Txxxxx xxxxx (can be T G or M)
field02 has the area code 416 / 905 / 647
I'd like to match T with 416, G with 905, and M with 647.
and show a relationship error if the rules were broken.
I made a separate function trying to compare the two.
function validatecompare(errMessages)
{
var clientID = document.pizza.field02;
var telenum = document.pizza.field03;
var client = clientID.value;
var phone = telenum.value;
var firstL = "";
var areaC = "";
firstL=client.substr(0,1);
areaC =phone.substr(0,3);
if ((firstL) !=areaC)
{
errMessages += "<li>Client Number and Telephone No. are not consistent with our set up rules.</li>\n";
}
return errMessages;
}
I know that's wrong, I just have no idea how to compare two fields from two separate functions. The error message will pop up regardless of what I do. Even if I violate the rules for field 1 and 2 the error message will pop up with those when it shouldn't.
If there is somewhere I can read up on how to do this would be excellent for future reference.
any help would be greatly appreciated, thanks.
You're literally comparing 416 and T. You need some kind of lookup table:
function validatecompare(errMessages) {
var clientID = document.pizza.field02;
var telenum = document.pizza.field03;
var client = clientID.value;
var phone = telenum.value;
var firstL = client.charAt(0);
var areaC = phone.substr(0, 3);
var areaCodes = {
'416': 'T',
'905': 'G',
'647': 'M'
};
if(firstL !== areaCodes[areaC]) {
errMessages += "<li>Client Number and Telephone No. are not consistent with our set up rules.</li>\n";
}
return errMessages;
}
I've got a string with the following format:
City, State ZIP
I'd like to get City and State from this string.
How can I do that with JavaScript? edit: note that he doesn't mention he already has the zip code when he gets here, if that helps you in your solution ~~ drachenstern
var address = "San Francisco, CA 94129";
function parseAddress(address) {
// Make sure the address is a string.
if (typeof address !== "string") throw "Address is not a string.";
// Trim the address.
address = address.trim();
// Make an object to contain the data.
var returned = {};
// Find the comma.
var comma = address.indexOf(',');
// Pull out the city.
returned.city = address.slice(0, comma);
// Get everything after the city.
var after = address.substring(comma + 2); // The string after the comma, +2 so that we skip the comma and the space.
// Find the space.
var space = after.lastIndexOf(' ');
// Pull out the state.
returned.state = after.slice(0, space);
// Pull out the zip code.
returned.zip = after.substring(space + 1);
// Return the data.
return returned;
}
address = parseAddress(address);
This is probably better then using regular expressions and String.split(), as it takes into account that the state and city may have spaces.
EDIT: Bug fix: It only included the first word of multi-word state names.
And here's a minified version. :D
function parseAddress(a) {if(typeof a!=="string") throw "Address is not a string.";a=a.trim();var r={},c=a.indexOf(',');r.city=a.slice(0,c);var f=a.substring(c+2),s=f.lastIndexOf(' ');r.state=f.slice(0,s);r.zip=f.substring(s+1);return r;}
There are many ways to do this. Here's a very naive one:
var parts = "City, State ZIP".split(/\s+/); // split on whitespace
var city = parts[0].slice(0, parts[0].length - 1); // remove trailing comma
var state = parts[1];
var zip = parts[2];
Here's one that accounts for the presence of spaces in either the city or state or both:
var parts = "san fran bay, new mex state 666666".split(/\s+|,/),
partition = parts.indexOf(""),
city = parts.slice(0, partition).join(" "),
state = parts.slice(partition + 1, -1).join(" "),
zip = parts.pop();
This last one only works if you're lucky enough to be in an environment that supports destructuring assignment:
var city, statezip, state, zip, parts;
[city, statezip] = "Spaced City, New Mexico ZIP".split(/,\s*/);
parts = statezip.split(/\s+/);
zip = parts.pop();
state = parts.join(" ");
None of these perform any validation, of course.
Ok, since advising regex isn't good, here's my solution. It takes into account cities that have spaces in them, which the other responses here don't seem to do:
var str = "New York, NY 20101";
var cityAndRest = str.split(',');
var city = cityAndRest[0];
var stateAndZip = cityAndRest[1].trim().split(' ');
var state = stateAndZip[0];
var zip = stateAndZip[1];
First assumption: American addresses only.
First find out if the last 5 or the last 10 characters are numeric. A simpler test is to see if the last character is numeric. If so, it's probably got the zip code included. Then a simple test to see if the last 10 contains a space (city #####) or if the last ten include a dash (12345-6789) to figure out if it's a 5 or 5+4 zip. We'll test for a hyphen and no space. (city-du-lac 12345 captures -lac 12345)
Next, all addresses split the city and state by a comma, so we want the last comma. Find the index of the last comma, and split there. I don't know of a city that uses commas in it's name, and I'm sure not gonna let my parser burst on an unknown if I can help it. I do ignore the fact that Washington DC could also be Washington, DC. I figure edge cases are for libraries, not one off scripts.
Lastly, trim everything that remains to remove trailing or leading spaces.
function IsNumeric(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
var addr = 'New York City, New York 10101';
//var addr = 'San Bernadino, CA 11111';
function getCityStateZip(addr){
var city; var state;var zip;
city = ''; state = ''; zip = '';
var addrLen = addr.length;
if ( IsNumeric( addr.substring(addrLen - 1) ) ) {
//contains a zipcode - just a sanity check
//get last 10 characters for testing easily
var lastTen = addr.substring( addrLen - 10 );
if ( lastTen.indexOf('-') > 0 && ( lastTen.indexOf(' ') == -1 ) ) {
//found a hyphen and no space (matches our complex rule for zipcodes)
zip = lastTen;
} else {
zip = addr.substring( addrLen - 5 ); //assume a basic 5 zip code
}
}
var zipLen = zip.length;
addrLen = addrLen - zipLen - 1;
addr = addr.substring(0, addrLen ); //remove the chars we just moved into zip
var lastComma = addr.lastIndexOf(',');
if ( lastComma == -1 ) {
//you have a problem, how do you want to handle it?
}
city = addr.substring(0,lastComma); //skip the comma itself, yes?
state = addr.substring(lastComma + 2);
return { 'city':city,'state': state,'zip': zip};
}
getCityStateZip(addr)
IsNumeric js function can be found here Validate decimal numbers in JavaScript - IsNumeric()
Easy way but no validation:
var addrObj={};
parseAddress("Beverly Hills, CA 90210",addrObj);
function parseAddress(address, addrObj){
var arr=address.replace(","," ").split(" ");
addrObj.zip=arr.pop();
addrObj.state=arr.pop();
addrObj.city=arr.join(" ");
}
For this type of thing you might want to use JavaScripts RegEx functions.
Here's some info:
http://www.javascriptkit.com/javatutors/re.shtml