Using Protractor I'm trying to verify if the sort works after I click on the sort by button. I've seen similar solutions here, but none of them works for my case.
On the page I have different values listed (15, 13, 67, ...) and for this I have home.myValues (using element.all). The flow would be:
store all numbers in an array and sort them with .slice().sort()
click on Sort by values button
store sorted numbers in an array
verify if sorted values match
Currently I have written the following, which doesn't work:
home.myValues.map(function(eachName) {
return eachName.getText().then(function(unSortedValues) {
initialSortedValues = unSortedValues.slice().sort();
return initialSortedValues;
});
});
// click on sort by values
home.sortByValues.click();
home.myValues.map(function(eachName) {
return eachName.getText().then(function(checkSortedValues) {
return checkSortedValues;
});
expect(initialSortedValues).toEqual(checkSortedValues);
});
Any suggestion is appreciated.
After some additional research I found this to work:
// verify my values are sorted
home.myValues.map(function(eachName) {
return eachName.getText().then(function(unSortedValues) {
return unSortedValues;
});
}).then(function(unSortedValues) {
// click on sort by value
home.sortByValue.click();
sortedValues = unSortedValues.slice();
sortedValues = sortedValues.sort(function(a, b){return a-b});
home.myValues.map(function(eachName) {
return eachName.getText().then(function(sortedValuesCheck) {
return sortedValuesCheck;
});
}).then(function(sortedValuesCheck) {
// verify sorted values equal expected
expect(sortedValues).toEqual(sortedValuesCheck);
});
});
Related
I am trying to merge storefront filtering and sorting in my custom theme collections page in Shopify.
Both things work, but the 'sort_by' parameters are overwriting the filtering ones when these are multiple.
i.e of how the URL should look once filtering with two parameters (sizes XXS and XL) and sorting by ascending price:
../collections/new-arrivals?filter.v.option.size=XXS&filter.v.option.size=XL&sort_by=price-ascending
But this is what happens when sorting:
../collections/new-arrivals?filter.v.option.size=XXS&sort_by=price-ascending
Second filtering parameter gets overwritten by the sorting one.
Pasting below my code for the JS piece that triggers the sorting behaviour.
// sortby
$(function() {
Shopify.queryParams = {};
if(location.search.length) {
for(var aKeyValue, i = 0, aCouples = location.search.substr(1).split('&'); i < aCouples.length; i++) {
aKeyValue = aCouples[i].split('=');
if (aKeyValue.length > 1) {
Shopify.queryParams[decodeURIComponent(aKeyValue[0])] = decodeURIComponent(aKeyValue[1]);
}
}
}
document.querySelector('.sort-by').addEventListener('change', function(e) {
var value = e.currentTarget.value;
Shopify.queryParams.sort_by = value;
location.search = new URLSearchParams(Shopify.queryParams).toString();
});
})
Has someone ever tried to achieve something like this?
I would appreciate any help.
Thanks in advance,
I have a group for which elements after reduction look like this pseudocode :
{
key:"somevalue",
value: {
sum: the_total,
names:{
a: a_number,
b: b_number,
c:c_number
}
}
}
In my dc-js geoChoropleth graph the valueAccessor is (d) => d.value.sum
In my title, I would like to use the names component of my reduction. But when I use .title((d) => {...}), I can onjly access the key and the value resulting from the valueAccessor function instead of the original record.
Is that meant to be ?
This is a peculiarity of the geoChoropleth chart.
Most charts bind the group data directly to chart elements, but since the geoChoropleth chart has two sources of data, the map and the group, it binds the map data and hides the group data.
Here is the direct culprit:
_renderTitles (regionG, layerIndex, data) {
if (this.renderTitle()) {
regionG.selectAll('title').text(d => {
const key = this._getKey(layerIndex, d);
const value = data[key];
return this.title()({key: key, value: value});
});
}
}
It is creating key/value objects itself, and the value, as you deduced, comes from the valueAccessor:
_generateLayeredData () {
const data = {};
const groupAll = this.data();
for (let i = 0; i < groupAll.length; ++i) {
data[this.keyAccessor()(groupAll[i])] = this.valueAccessor()(groupAll[i]);
}
return data;
}
Sorry this is not a complete answer, but I would suggest adding a pretransition handler that replaces the titles, or alternately, using the key passed to the title accessor to lookup the data you need.
As I noted in the issue linked above, I think this is a pretty serious design bug.
I'm working on this project that someone else already started and I'm unsure how this part of code works, it's actually doing what I don't want it to do.
Currently when I use a select multiple and press the button it adds to the array the ones that I DIDN'T select, when I want it to add the ones I did select to the array, this array is then used as the data for a table so it's obvious it's selecting the wrong stuff.
This is the method when the button is pressed. package_courses is the final array that the table data is populated with.
addCourses() {
const currentCourses = this.packageForm.package_courses.map((item) => item.course_id);
const courses = this.courses.filter((item) => {
return this.selectedCourses.indexOf(item.id) && currentCourses.indexOf(item.id) < 0
});
courses.forEach((course) => {
this.packageForm.package_courses.push({
course_id: course.id,
course: course,
price: 0
});
});
this.selectedCourses = [];
},
In the second line the filter method loops all items in this.courses and returns only those items where the statement inside returns true. indexOf is an array method that searches an array for the specified item and returns the position of the item in the array or -1 if the items isn't found. so I guess what you want to do is filter for courses where indexOf is greater or equals than/to 0, instead of less, here is your code modified.
addCourses() {
const currentCourses = this.packageForm.package_courses.map((item) => item.course_id);
const courses = this.courses.filter((item) => {
return this.selectedCourses.indexOf(item.id) && currentCourses.indexOf(item.id) >= 0
});
courses.forEach((course) => {
this.packageForm.package_courses.push({
course_id: course.id,
course: course,
price: 0
});
});
this.selectedCourses = [];
},
I have attempted to extend this fiddle
https://jsfiddle.net/rn3ja9n4/
here
https://jsfiddle.net/thyfoubq/32/
but it is unclear what I should use to power the dc.selectmenu or if the it is even capable of working in the multi-key scenario.
Is this possible?
I have tried several variations of this but i can't seem to get the filter to work with the composite key or the single branch key
var storedim =ndx.dimension(function(d){ return [d.store]})
var storegroup =storedim.group()
storeselect
.dimension(storedim)
.group(storegroup)
.multiple(true)
.size(5)
.controlsUseVisibility(true)
.title(kv => kv.key);
----------------------- possible solution that appears to work---------
---change the group to remove empty bins
var suppliersSumGroup = remove_empty_bins(suppliersSumDistinct.group().reduceSum( d => d.earnings ));
function remove_empty_bins(source_group) {
return {
all:function () {
return source_group.all().filter(function(d) {
return d.value !=0; //appears to work borrowed from another SO post
//unsure which one but it seems logical and works for this example
});
}
};
}
I am using dexie.js to interface with IndexedDB. I am wondering if it is possible to orderby or sortby using more than one index at once (eg. db.people.orderBy( index1, desc : index2, asc )...
If it is possible, what is the correct syntax?
Either use compound indexes, or use Collection.and().
If you can live with only targeting Chrome, Firefox or Opera, you can use compound indexes. If it must work on Safari, IndexedDBShim, Edge or IE, you cannot use compound indexes today. There's a shim that enables it for IE/Edge though, but it is still in beta, so I would recommend to instead use Collection.and() for those cases.
Let' say you have a form where users can fill in various attributes of friends:
<form>
<input name="name"/>
<input name="age"/>
<input name="shoeSize" />
</form>
Using Collection.and()
First, pick the most probably index to start your search on. In this case, "name" would be a perfect index that wouldn't match so many items, while age or shoeSize would probably match more friends.
Schema:
db.version(X).stores({
friends: "id, name, age, shoeSize"
});
Query:
function prepareQuery () {
// Pick a good index. The picked index will filter out with IndexedDB's built-in keyrange
var query;
if (form.name.value) {
query = db.friends.where('name').equals(form.name.value);
} else if (form.age.value) {
query = db.friends.where('age').equals(parseInt(form.age.value));
} else if (form.shoeSize.value) {
query = db.friends.where('shoeSize').equals(parseInt(form.shoeSize.value));
} else {
query = db.friends.toCollection();
}
// Then manually filter the result. May filter a field that the DB has already filtered out,
// but the time that takes is negligible.
return query.and (function (friend) {
return (
(!form.name.value || friend.name === form.name.value) &&
(!form.age.value || friend.age == form.age.value) &&
(!form.shoeSize.value || friend.shoeSize == form.shoeSize.value));
});
}
// Run the query:
form.onsubmit = function () {
prepareQuery() // Returns a Collection
.limit(25) // Optionally add a limit onto the Collection
.toArray(function (result) { // Execute query
alert (JSON.stringify(result, null, 4));
})
.catch (function (e) {
alert ("Oops: " + e);
});
}
Using compound indexes
As written above, compound indexes code will only work on mozilla- and chromium based browsers.
db.version(x).stores({
friends: "id, name, age, shoeSize," +
"[name+age+shoeSize]," +
"[name+shoeSize]," +
"[name+age]," +
"[age+shoeSize]"
});
The prepareQuery() function when using compound indexes:
function prepareQuery() {
var indexes = []; // Array of Array[index, key]
if (form.name.value)
indexes.push(["name", form.name.value]);
if (form.age.value)
indexes.push(["age", parseInt(form.age.value)]);
if (form.shoeSize.value)
indexes.push(["shoeSize", parseInt(form.shoeSize.value)]);
var index = indexes.map(x => x[0]).join('+'),
keys = indexes.map(x => x[1]);
if (indexes.length === 0) {
// No field filled in. Return unfiltered Collection
return db.friends.toCollection();
} else if (indexes.length === 1) {
// Single field filled in. Use simple index:
return db.friends.where(index).equals(keys[0]);
} else {
// Multiple fields filled in. Use compound index:
return db.friends.where("[" + index + "]").equals(keys);
}
}
// Run the query:
form.onsubmit = function () {
prepareQuery() // Returns a Collection
.limit(25) // Optionally add a limit onto the Collection
.toArray(function (result) { // Execute query
alert (JSON.stringify(result, null, 4));
})
.catch (function (e) {
alert ("Oops: " + e);
});
}
Using arrow functions here to make it more readable. Also, you're targeting chromium or firefox and they support it already.