Search string inside array javascript - javascript

I am looking for a simple function to check if a specific string is inside my array.
function checkRegion(departement){
var region = '';
if(alsace.indexOf(departement) != -1)
{
region = "alsace";
}
if(aquitaine.indexOf(departement) != -1){
region = "aquitaine";
}
if(auvergne.indexOf(departement) != -1){
region = "auvergne";
}
if(basseNormandie.indexOf(departement) != -1){
region = "basse-normandie";
}
if(iledefrance.indexOf(departement) != -1){
region = "ile-de-france";
}else{
region = 'undennnnnfined';
}
return region;
};
Any solution ?
Thanks

Your problem lies in the use of consecutive if statements without chaining them together to make a complete check.
Doing it your way, the code actually completely disregards all the if statements, but the last one.
So, if iledefrance.indexOf(departement) != -1 gives false, it'will always execute the code inside else, meaning it'll set region = 'undennnnnfined'.
Note:
In the code, I replaced != -1 with ~ as it makes for a somewhat more succinct code. In essence, it will convert -1 to 0, namely false.
Be sure to check out MDN's documentation for more if you are not familiar.
• 1st Option :
Try chaining your if statements together in an if/else if/else format as follows:
function checkRegion(departement){
var region = '';
if(~alsace.indexOf(departement)) {
region = "alsace";
}
else if(~aquitaine.indexOf(departement)) {
region = "aquitaine";
}
else if(~auvergne.indexOf(departement)) {
region = "auvergne";
}
else if(~basseNormandie.indexOf(departement)) {
region = "basse-normandie";
}
else if(~iledefrance.indexOf(departement)) {
region = "ile-de-france";
}
else{
region = 'undennnnnfined';
}
return region;
};
• 2nd Option :
Create two arrays:
One should contain your region arrays (alsace, aquitaine etc) &
One more containing the names of your arrays as strings, so that you can return the appropriate string based on the array that was evaluated as true.
Code:
function checkRegion(departement) {
var
regions = [alsace, aquitaine, auvergne, basseNormandie, iledefrance],
regionsNames = ["alsace", "aquitaine", "auvergne", "basseNormandie", "iledefrance"];
for (var i = 0; i < regions.length; i++) {
if (~regions[i].indexOf(departement)) {
return regionsNames[i];
}
}
return "undennnnnfined"; // If the 'for' loop doesn't return anything, it's false.
};
Demos:
Working demo with the 1st solution → here.
Working demo with the 2nd solution → here.
Snippets:
Snippet with the 1st solution:
function checkRegion(departement){
var region = '';
if(~alsace.indexOf(departement)) {
region = "alsace";
}
else if(~aquitaine.indexOf(departement)) {
region = "aquitaine";
}
else if(~auvergne.indexOf(departement)) {
region = "auvergne";
}
else if(~basseNormandie.indexOf(departement)) {
region = "basse-normandie";
}
else if(~iledefrance.indexOf(departement)) {
region = "ile-de-france";
}
else{
region = 'undennnnnfined';
}
return region;
};
var
alsace = ["Strasbourg", "Colmar"],
aquitaine = ["Gironde", "Landes", "Dordogne", "Pyrenees-Atlantiques", "Lot-et-Garonne"],
auvergne = [],
basseNormandie = [],
iledefrance = [];
alert(checkRegion("Strasbourg"));
Snippet with the 2nd solution:
function checkRegion(departement) {
var
regions = [alsace, aquitaine, auvergne, basseNormandie, iledefrance],
regionsNames = ["alsace", "aquitaine", "auvergne", "basseNormandie", "iledefrance"];
for (var i = 0; i < regions.length; i++) {
if (~regions[i].indexOf(departement)) {
return regionsNames[i];
}
}
return "undennnnnfined"; // If the 'for' loop doesn't return anything, it's false.
};
var
alsace = ["Strasbourg", "Colmar"],
aquitaine = ["Gironde", "Landes", "Dordogne", "Pyrenees-Atlantiques", "Lot-et-Garonne"],
auvergne = [],
basseNormandie = [],
iledefrance = [];
alert(checkRegion("Strasbourg"));

Related

How to underline charachters in InDesign with JavaScript?

I started writing this piece of code for InDesign to underline all letters except from the one with descendants, and added a dialog window to chose stroke and offset of the line.
Now I have two problems:
the program underlines all letters
the stroke and offset won't change
I'm a beginner in Javascript and it's the first time coding for InDesign. Does someone have a clue? Thank you!
// UNDERLINE ALL BUT NO DESCENDANTS
//Make certain that user interaction (display of dialogs, etc.) is turned on.
app.scriptPreferences.userInteractionLevel = UserInteractionLevels.interactWithAll;
if (app.documents.length != 0){
try {
// Run script with single undo if supported
if (parseFloat(app.version) < 6) {
main();
} else {
app.doScript(main, ScriptLanguage.JAVASCRIPT, undefined, UndoModes.ENTIRE_SCRIPT, "Expand State Abbreviations");
}
// Global error reporting
} catch ( error ) {
alert( error + " (Line " + error.line + " in file " + error.fileName + ")");
}
}else{
alert("Open a document first before running this script.");
}
///MAIN FUNCTION
function main(){
if(app.selection.length != 0){
myDisplayDialog();
}
}
//INTERFACE
function myDisplayDialog(){
//declare variables
//general
var myDoc = app.activeDocument;
var mS = myDoc.selection;
// dialog
var myDialog = app.dialogs.add({name:"Underliner"});
var myLabelWidth = 70;
with(myDialog.dialogColumns.add()){
with(borderPanels.add()){
with(dialogColumns.add()){
with(dialogRows.add()){
staticTexts.add({staticLabel:"Stroke:", minWidth:myLabelWidth});
staticTexts.add({staticLabel:"Offset:", minWidth:myLabelWidth});
}
}
with(dialogRows.add()){
staticTexts.add({staticLabel:""});
var myStroke = measurementEditboxes.add({editValue:1, editUnits:MeasurementUnits.points});
var myOffset = measurementEditboxes.add({editValue: 15, editUnits:MeasurementUnits.points});
}
}
}
var myResult = myDialog.show();
if(myResult == true){
var myStroke = myStroke.editValue;
var myOffset = myOffset.editValue;
myDialog.destroy();
underline(mS,myStroke,myOffset);
}
else{
myDialog.destroy();
alert("Invalid page range.");
}
}
//REAL FUNCTION
function underline(charList,stroke, offset){
var len = charList.length;
const doNotUnderline = ['g','j','p','q','y'];
for (var i=0; i < len; i++){
try{
var myChar = charList[i];
//console.log(typeof myText);
if (includes(myChar, doNotUnderline) == false)
{
myChar.underline = true;
myChar.underlineWeight == stroke;
myChar.underlineOffset == offset;
} else {
myChar.underline = false;
}
}catch(r){
alert(r.description);
break;
}
}
}
//function to know if char is in array
function includes(elemento,array)
{
var len = array.length;
for(var i=0; i<len ;i++)
{
if(array[i]==elemento){return true;}
}
return false;
}
Try these changes in the function underline():
//REAL FUNCTION
function underline(words,stroke, offset) { // <------ here 'words' instead of 'charList'
var charList = words[0].characters; // <------ here get 'characters' of the 'words'
var len = charList.length;
const doNotUnderline = ['g','j','p','q','y'].join(); // <------- here '.join()'
for (var i=0; i < len; i++){
try{
var myChar = charList[i];
// if (includes(myChar, doNotUnderline) == false) // <----- no need
if (doNotUnderline.indexOf(myChar.contents) < 0) // <------ 'indexOf()' instead of 'includes()'
{
myChar.underline = true;
myChar.underlineWeight = stroke; // <------- here '=' instead of '=='
myChar.underlineOffset = offset; // <------- here '=' instead of '=='
} else {
myChar.underline = false;
}
}catch(r){
alert(r.description);
break;
}
}
}
Probably there can be another improvements as well. It's need additional researches. But if you change these lines it should work to a degree.
And there is one little thing that improves user experience greatly: to keep last used values in the input fields. It can be done pretty easy, let me know it you need it.
Update
Here is the way I'm using to store and restore any preferences of my scripts.
Add somewhere at the start of your script these lines:
// get preferences
var PREFS = { stroke: 1, offset: 15 }; // set default prefs
var PREFS_FILE = File(Folder.temp + '/underline_prefs.json'); // the file with preferences
if (PREFS_FILE.exists) PREFS = $.evalFile(PREFS_FILE); // get the prefs from the file
Now you can use the global values PREFS.stroke and PREFS.offset anywhere you want. In your case they go here:
with(dialogRows.add()){
staticTexts.add({staticLabel:""});
var myStroke = measurementEditboxes.add({editValue:PREFS.stroke, editUnits:MeasurementUnits.points});
var myOffset = measurementEditboxes.add({editValue:PREFS.offset, editUnits:MeasurementUnits.points});
}
This way script will get the stroke and weight from the file underline_prefs.json that will be stored in the standard temporary folder of current user.
Final step is to save the values back into the file after the script got them from the dialog window.
I'd put this piece of code here:
if (myResult == true) {
var myStroke = myStroke.editValue;
var myOffset = myOffset.editValue;
myDialog.destroy();
underline(mS, myStroke, myOffset);
// save preferences here
PREFS.stroke = myStroke;
PREFS.offset = myOffset;
PREFS_FILE.open('w');
PREFS_FILE.write(PREFS.toSource());
PREFS_FILE.close();
} else {
myDialog.destroy();
alert("Invalid page range.");
}
Voilá. Now don't need to type the values every time they differ from default ones.

Javascript How to check the length of multiple variables and return the result in an efficient way?

At the moment I have an if the condition that checks if any of the string variable lengths is greater than 2 if true check for another condition, else console.log the output.
var previous_data_change = 'last_changed on 10/01/2019 13:56:34';
var current_data_change= "";
var current_data_end = "";
var current_data_profile = "normal";
// check for changes
if (
previous_data_change.length >= 2 ||
current_data_start.length >= 2 ||
current_data_end.length >= 2 ||
current_data_profile.length >= 2
) {
if (previous_data_change.includes("last_changed")) {
console.log(`last change comments: ${previous_data_change}`)
}
} else {
console.log(`no change in previous record`)
}
i have tried refactoring it using some,
var previous_data_change = 'last_changed on 10/01/2019 13:56:34';
var current_data_change= "";
var current_data_end = "";
var current_data_profile = "normal";
var filter_col = [
previous_data_change,
current_data_change,
current_data_end,
current_data_profile
];
change_boolean = filter_col.some((element) => element.length >= 2);
if (change_boolean && previous_data_change.includes("last_changed")) {
console.log(`last change comments: ${previous_data_change}`);
} else {
console.log("no change in previous record");
}
is there any way to shorten it further?
Since you want any of them to be length greater than 2. You can simply merge them instead of writing 4 if conditions.
var previous_data_change = 'last_changed on 10/01/2019 13:56:34';
var current_data_change= "";
var current_data_end = "";
var current_data_profile = "normal";
var string_to_check = previous_data_change + current_data_start + current_data_end + current_data_profile;
// check for changes
if (string_to_check.length < 2) {
console.log(`no change in previous record`)
return false;
}
if (previous_data_change.includes("last_changed")) {
console.log(`last change comments: ${previous_data_change}`)
return true;
}

javascript function return "undefine" from jsp page

i have a jsp page and call a JS function which is in some abc.js file from this JSP page.
i have included this js file to jsp page.
JSP JavaScript Code:-
function doFinish(tableId, col, field)
{
var oldselectedCells = "";
var selItemHandle = "";
var selRightItemHandle = "";
var left = -1;
var right = -1;
// Get the table (tBody) section
var tBody = document.getElementById(tableId);
// get field in which selected columns are stored
var selectedCellsFld = document.getElementById(tableId + datatableSelectedCells);
selectedCellsFld.value = oldselectedCells;
for (var r = 0; r < tBody.rows.length; r++)
{
var row = tBody.rows[r];
if (row.cells[col].childNodes[0].checked == true)
{
selectedCellsFld.value = oldselectedCells +
row.cells[col].childNodes[0].id;
selItemHandle = row.cells[col].childNodes[0].value
oldselectedCells = selectedCellsFld.value + datatableOnLoadDivider;
left = selItemHandle.indexOf("=");
right = selItemHandle.length;
selRightItemHandle = selItemHandle.substring(left+1,right);
var index=getColumnIndex(tBody,"Name");
if(index!=null)
{
if(field == 1)
{
window.opener.document.TemplateForm.eds_asbactionscfg_item_handle_child_physpart.value = selRightItemHandle;
window.opener.document.TemplateForm.ChildPhysicalPart.value = row.cells[index].childNodes[0].innerHTML;
}
else if (field == 2)
{
window.opener.document.TemplateForm.eds_asbactionscfg_dev_doc_item_handle_name.value = selRightItemHandle;
window.opener.document.TemplateForm.DeviationObject.value = row.cells[index].childNodes[0].innerHTML;
}
else if (field == 3)
{
window.opener.document.TemplateForm.eds_asbactionscfg_dev_doc_item_handle_name.value = selRightItemHandle;
window.opener.document.TemplateForm.DeviationObject.value = row.cells[index].childNodes[0].innerHTML;
}
}
}
}
window.close();
}
JS Code:-
function getColumnIndex(tBody,columnName)
{
var cells = tBody.parentNode.getElementsByTagName('th');
for (var i=0;i<cells.length; i++)
{
if(cells[i].hasChildNodes())
{
if(cells[i].childNodes[0].innerHTML.replace(/(\r\n|\n|\r)/gm ,"").trim() == columnName)
{
return i;
}
}
}
}
i had debug this code with firebug & calling getColumnIndex(tBody,columnName) function works fine but when it return to caller the var index=getColumnIndex(tBody,"Name"); the index value is "undefine".
suggest some solution.
getColumnIndex(tBody,columnName) function works fine.
as if it matches this if condition
if(cells[i].childNodes[0].innerHTML.replace(/(\r\n|\n|\r)/gm ,"").trim() == columnName)
{
return i;
}
so that it returns something.
but when you replace this
var index=getColumnIndex(tBody,"Name"); so that coulmnName would be "Name" in String.
And it doesn't match with any columnName so that your condition going to be wrong and function doesn't return anything.
var index=getColumnIndex(tBody,"Name"); the index value is "undefine".
suggestion is put some else condition on that and return some error message like this :
if(cells[i].childNodes[0].innerHTML.replace(/(\r\n|\n|\r)/gm ,"").trim() == columnName)
{
return i;
} else{
// put some error message
// return null
}
i had debug this code with firebug & calling getColumnIndex(tBody,columnName) function works fine
From this, I'm assuming that there isn't anything wrong with the implementation of your getColumnIndex function, so your issue with getting an undefined value must have to do with when this function is returning a value.
but when it return to caller the var index=getColumnIndex(tBody,"Name"); the index value is "undefine".
This leads me to assume that your tBody variable is not being set correctly, given that the "function works fine".
I'm assuming there is a case in your code where the conditions of your getColumnIndex function is not met.
function getColumnIndex(tBody,columnName)
{
var cells = tBody.parentNode.getElementsByTagName('th');
for (var i=0;i<cells.length; i++)
{
if(cells[i].hasChildNodes())
{
if(cells[i].childNodes[0].innerHTML.replace(/(\r\n|\n|\r)/gm ,"").trim() == columnName)
{
return i;
}
}
}
// If your code reaches this point, then the prior conditions have not been met
// You can choose to do something else here for return false/undefined etc.
return undefined;
}

Javascript Recursion returning undefined

I'm struggling in a recursive Javascript function to find a specific subdirectory. This is my code:
function navigateToParent() {
var parentFullPath = parentDirectory(); // gets the full Path String
if (parentFullPath != null) {
var parent = getDirectoryByName(parentFullPath, rootDirectory);
// set the parent directory object as the current one
currentDirectory(parent);
}
}
function getDirectoryByName(fullName, myDirectory) {
if (myDirectory.fullName == fullName) {
return myDirectory;
} else {
var subs = myDirectory.subDirectories;
for (i = 0; i < subs.length; i++) {
return getDirectoryByName(fullName,subs[i]);
}
}
}
Every directory object has the properties fullName(string),subDirectories(array of directories) and files(array of files). My aim is to get the correct directory object, where it's fullName is matching.
I know, that i have to break the for loop in some way, but i don't know how to do it exactly.
After overthinking the logic i came to this solution (seems to work):
function getDirectoryByName(fullName, myDirectory) {
if (myDirectory.fullName == fullName) {
return myDirectory;
} else {
var subs = myDirectory.subDirectories;
for (i = 0; i < subs.length; i++) {
var match = getDirectoryByName(fullName, subs[i]);
if (typeof match !== "undefined"){
return match;
}
}
}
}

Get only one match with regexp

In the function below I iterate through an array (incidents) which contains of strings. The strings is describing an incident (crime or accidents) that is scrapted from another web app, and what I'm doing is dividing and counting the different crimes / accidents and placing them in an object (INCIDENT_MATCHES).
However, some of the text strings may contain of several of the keywords that I search for (e.g. both "gunfire" and "battery"), but that I don't want. Instead I just want the first found word to be counted, and if more keywords are found they should be ignored.
How could this be done?
var INCIDENT_MATCHES = {
battery: /\w*(bråk)\w*|överfall|slagsmål|slogs|misshandel|misshandlad|\w*(tjuv)\w*/ig,
burglaries: /snattade|snattare|snatta|inbrott|bestulen|stöld|\w*(tjuv)\w*/ig,
robberies: /\w*(rån)\w*|personrån|\w*(ryckning)\w*|väskryckt*/ig,
gunfire: /skottlossning|skjuten|sköt/ig,
drugs: /narkotikabrott/ig,
vandalism: /skadegörelse|klotter|\w*(klottra)\w*/ig,
trafficAccidents: /(trafik|bil)olycka|(trafik|bil)olyckor|\w*(personbil)\w*|singelolycka|kollision|\w*(kollidera)\w*|påkörd|trafik|smitningsolycka/ig,
};
var j = 0,
incidentCounts = {},
incidentTypes = Object.keys(INCIDENT_MATCHES);
incidents.forEach(function(incident) {
matchFound = false;
incidentTypes.forEach(function(type) {
if(typeof incidentCounts[type] === 'undefined') {
incidentCounts[type] = 0;
}
var matchFound = incident.match(INCIDENT_MATCHES[type]);
if(matchFound){
matchFound = true;
incidentCounts[type] += 1;
}
});
j++;
});
You can return false from the "each" handler to stop iteration.
if(matchFound){
matchFound = true;
incidentCounts[type] += 1;
return false;
}
edit — and you'll want (I think) another test outside that, at the end of the outer loop:
j++; // I don't understand what that does ...
if (matchFound) return false;
I found this solution below to work. What I did was the following:
I replaced the second forEach statement with "every"
Put "return false" inside "if(matchFound)"
Added "else { return true; }" so that the loop continues if no match is found.
The code:
incidents[2].forEach(function(incident) {
matchFound = false;
incidentTypes.every(function(type) {
if(typeof crimesPerType[type] === 'undefined') {
crimesPerType[type] = 0;
}
var matchFound = incident.match(INCIDENT_MATCHES[type]);
if(matchFound){
crimesPerType[type] += 1;
if (type == 'trafficAccidents') {
incidents[3][j].push('traffic');
}
else {
incidents[3][j].push('crime');
}
return false;
}
else {
return true;
}
});

Categories

Resources