I have a dropdown of country on a webpage. I need to validate the country names in drop down is sorted using Protractor-Cucumber.
I located all options in dropdown using element.all() and used a forEach loop on array. For each iteration, it extract the text and add to another array. Since extracting text takes some time, my resultant array does not have texts in same order as it appears in drop down.
element.all(by.css('ul.sbsb_b')).then(function(allOptions){
allOptions.forEach(function(optn){
optn.getText().then(function(text){
result.push(text);
})
})
});
If my dropdown contains options as A,B,C,D then resultant array should give me in same order. Above logic works fine for less number of options. I want forEach to do iteration one by one instead of all at once because of asynchronous nature.
The method I would attempt for this issue would be to convert your ElementArrayFinder into an array of strings directly using .getText(). I would imagine this would preserve the order but cannot say for sure.
element.all(by.css('ul.sbsb_b')).getText().then(function(allOptions){
console.log(typeof allOptions)
console.log(Array.isArray(allOptions))
}
To preform your validation there are two approaches you could take which do not require any particular order of the state names array you are extracting.
You could sort the array and then expect them both to be equal.
element.all(by.css('ul.sbsb_b')).getText().then(function(allOptions){
expect(allOptions.sort()).toEqual(expectedStates);
}
Or you could validate that the array you have created is the same length as your expected array of states and then verify that every expected state appears at least once in the created array
element.all(by.css('ul.sbsb_b')).getText().then(function(allOptions){
expect(allOptions.length).toBe(expectedStates.length);
for(let i = 0; i < expectedStates.length; count++){
expect(allOptions).toContain(expectedStates[i]);
}
}
I have a domino view with an amount column but some values are empty...and need to be. The problem is that the #Sum works fine until I have an empty value then it stops summing.
eg: if the values are 5,5,"" and 5 I get a sum of 10 and not 15.
I've traced the problem to the #DbLookup which is that it stops building the return array when it encounters a blank value. There is no built in method of dealing with null values.
https://www.ibm.com/support/knowledgecenter/en/SSVRGU_9.0.1/reference/r_wpdr_atfunctions_dblookup_r.html
To make things harder, #dbLookup returns a string if only one is found or an array if more than one are found. If the values are 5,5,"" and 5 it returns an array of 2 values.
var alloc = #Sum(#DbLookup(#DbName(), "SubForms",MainFrmID , "ca_ca_ca_ca_amount"));
if (isNaN(alloc)){
return "$0.00";
}else{
return "$" + alloc.toFixed(2);
}
Can anyone help me refactor the #sum or #DbLookup to allow for empty values? Unfortunately I cannot define any new functions for this solution. The environment is locked down tightly. With a list of values of 5,5,"" and 5 I need a sum of 15.
I would try #Sum(#TextToNumber(#Trim(#Text(#DbLookup(...)))))
I would try
#Sum( #Transform( #Dblookup ( ....
If #DbLookup does not do what you need, you could always iterate over documents or view entries to build the sum.
The flow would be roughly like this:
1. Get a handle to the current database.
2. Get a handle to the "SubForms" view.
3a. Get a view entry collection using using getAllEntriesByKey() with MainFrmID as key, if a view column exists that displays the values you need.
--OR--
3b. Get a document collection using getAllDocumentsByKey() with MainFrmID as key, if no view column exists that displays the values you need.
4. Iterate over the collection to sum up values, using getColumnValues().get(columnNumber) to access the value from each view entry, or getItemValueDouble(fieldName) to access the value from each document.
That way you can easily detect null values and discard them.
this is my first question on stackoverflow.
and a little bit experience on code.
so I have a localstorage like this:
myDB: "[{"key:"123","label":"abc"}]
I have a div with "abc" as value:
<div id="name">abc</div>
And many id's div clone with different value
<div id="name">abc</div>
<div id="name">cde</div>
<div id="name">efg</div>
I want to read the value of the ID "name", make a if/else like looking "abc" are in the localstorage, if yes delete it with the key. else not delete.
I have thinking of using document.getElement to get value from ID and compare it to localstorage and using if else to do that thing. But there are many clone have that event to trigger the function to delete it. So the function don't know which ID's value to be compare and delete it.
I really awkward for this newbie question. But I have to ask, many thanks first :)
*New question:
I want to delete last element of the localstorage.
Can I convert localstorage to array then using array.pop(). Then convert the changed array again to the localstorage?
First, as was mentioned by others, id must be unique. You can use any other attribute instead, for example, class:
<div class="name">abc</div>
<div class="name">def</div>
<div class="name">ghi</div>
<div class="name">jkl</div>
<div class="other">mno</div>
Then, to query these elements, you could use document.getElementsByClassName("name") which will return you an array-like object. You can convert this object to an array of values using a combination of spread syntax and map method:
let values = [...document.getElementsByClassName("name")].map(e => e.innerHTML);
To work with the local storage you can use localStorage.setItem and localStorage.getItem. As you know, the local storage stores only strings, so JSON.parse and JSON.stringify methods will be helpful too.
Here is the example of code:
localStorage.setItem("myDB", '[{"key":"123","label":"abc"}, {"key":"456","label":"mno"}]');
console.log('Local storage before: ', localStorage.getItem("myDB"));
// extracting div values to an array
let values = [...document.getElementsByClassName("name")].map(e => e.innerHTML);
// creating a js object from myDB string
let db = JSON.parse(localStorage.getItem("myDB"));
// leaving only those elements, which labels are not in the values array
localStorage.setItem("myDB", JSON.stringify(db.filter(item => !values.includes(item.label))));
console.log('Local storage after: ', localStorage.getItem("myDB"));
JSFiddle link: https://jsfiddle.net/v03wpgq1/4/
id attributes should be unique on the page, otherwise only the last one on the page has the ability to be referenced easily (or at least, properly).
There should be a section that contains these which makes them easily queryable. Perhaps inside of an element with an id guaranteed to uniquely hold a set of name value pairs.
Using document.querySelectorAll is your best bet for finding these elements, and will be made easier by creating a structure that can be queried.
With a set of items to look for, it should be easy to iterate and test for values and keys inside of localStorage.
I have the the following data being returned by my api.
[{"category":"Amazon","month":"Feb","total":9.75},
{"category":"Amazon","month":"Mar","total":169.44},
{"category":"Amazon","month":"Apr","total":10.69},
{"category":"Amazon","month":"May","total":867.0600000000001},
{"category":"Amazon","month":"Jun","total":394.43999999999994},
{"category":"Amazon","month":"Jul","total":787.2400000000001},
{"category":"Amazon","month":"Aug","total":1112.4400000000003},
{"category":"Amazon","month":"Sep","total":232.86999999999998},
{"category":"Amazon","month":"Oct","total":222.26999999999998},
{"category":"Amazon","month":"Nov","total":306.09999999999997},
{"category":"Amazon","month":"Dec","total":1096.2599999999998}]
I want to format it so that the months are all grouped under each category like this:
[{"category":"Amazon","month":{"Jan":9.75,"Feb":9.75,"Mar":9.75,"Apr":9.75,etc...}]
How can I do this with javascript?
What I'm ultimately trying to do is to display some pivoted data in a table. I'm not sure what the best design is to accomplish this.
Right now, I'm just setting up a table dynamically and adding in the data corresponding to each row. Are there better design patterns for doing this?
You can reduce the array of objects to an object using the categories as keys, and adding the months, and then map it back to an array again
var arr = [{"category":"Amazon","month":"Feb","total":9.75},
{"category":"Amazon","month":"Mar","total":169.44},
{"category":"Amazon","month":"Apr","total":10.69},
{"category":"Amazon","month":"May","total":867.0600000000001},
{"category":"Amazon","month":"Jun","total":394.43999999999994},
{"category":"Amazon","month":"Jul","total":787.2400000000001},
{"category":"Amazon","month":"Aug","total":1112.4400000000003},
{"category":"Amazon","month":"Sep","total":232.86999999999998},
{"category":"Amazon","month":"Oct","total":222.26999999999998},
{"category":"Amazon","month":"Nov","total":306.09999999999997},
{"category":"Amazon","month":"Dec","total":1096.2599999999998}];
var o = arr.reduce( (a,b) => {
a[b.category] = a[b.category] || [];
a[b.category].push({[b.month]:b.total});
return a;
}, {});
var a = Object.keys(o).map(function(k) {
return {category : k, month : Object.assign.apply({},o[k])};
});
console.log(a);
I would take the following approach:
Write down on a piece of paper how to solve the problem (the "algorithm").
Flesh out this algorithm with more details. Sometimes this is called "pseudo-code".
Convert the pseudo-code into JavaScript.
For instance, your algorithm might look like this:
Create a new thing to hold the results.
Loop through the elements in the input.
For each element in the input, update the results thing.
Return the result.
Sometimes it helps to read out the algorithm aloud to yourself. Or animate the algorithm on a blackboard. Or talk through the algorithm with someone nearby.
The pseudo-code might be:
Create a new array containing a new object to hold the results, with a category property set to "Amazon", and a months property set to an empty object.
Loop through the elements in the input array.
For each element, add a new property to the months property of the results object, whose key is the value of the month property from the element, and whose value is the value of the total property from the element.
Return the result.
If you have specific questions about any of those steps, you can research it further, or ask, such as:
How do I create a new array, with an object inside?
How do I loop through the elements of an array?
How do I retrieve a property from an object?
How do I add a new key/value pair to an object?
How do I return the result?
If you are unfamiliar with any of the terms used above--such as array, object, property, key, value, or element--research them and make sure you know what they mean. Knowing and using correct terminology is the first step to successful programming!
When converting your algorithm into JS, write it step by step, and test it at each phase. For instance, start with a version which doesn't loop over the input at all, and make sure it produces a correct output of [{category: "Amazon", month: {}}]. Walk though your code in the debugger at this and each following step--if you don't know how to use the debugger, learning that should be your first priority! If you want to check a little bit of syntax, to make sure it does what you think, just try it out by typing it into the console. If you don't know what the console is, learning that should be another top priority.
All the above assumes that you've got a single Amazon category. If you are going to have multiple categories, and want multiple objects (one for each) in your output array, then start over from the top and write the algorithm and pseudo-code which can handle that.
I have a database of about 64000 products, and when I'm trying to find some with certain text in the name, I need to iterate over all 64000 of them, checking each one individually with a function.
Is there a better way to have IndexedDB return only objects where the value matches a certain regexp or contains a certain string?
No.
I think the closest you can get to this is storing an array of keywords together with your string data, and then use a multiEntry index. You could retrieve a list of objects containing any particular keyword, though you must make an intersection of results yourself if you want to query for multiple words at once.