xcode uitest picker only moving one position - xcode

While working in Xcode Version 8.0 beta 5 (8S193k), I am trying to use the the following line to adjust the picker with four 'spinners'. (The indexes are correct as I have two other single pickers on the same page.)
let pickCD = app.pickerWheels.element(boundBy: 2)
let pickCB = app.pickerWheels.element(boundBy: 3)
let pickSD = app.pickerWheels.element(boundBy: 4)
let pickSB = app.pickerWheels.element(boundBy: 5)
pickCD.adjust(toPickerWheelValue: "None")
pickCB.adjust(toPickerWheelValue: "1")
pickSD.adjust(toPickerWheelValue: "1")
pickSB.adjust(toPickerWheelValue: "None")
The issue is that the pickers are only moving one position (in the direction of the desired value. For example, if the first spinner has values 'None', '1', '2', '3', '4', '5' and the current position is '3'. When I run the test the spinner will only move to the value '2' and not to 'None'.
The other two spinners are working correctly and will move through over 200 elements to select the correct label using the same commands.
Thoughts?

Related

Adjusting small multiples sparklines

I have an heatmap that show some data and a sparkline for each line of the heatmap.
If the user click on a row label, then the data are ordered in decreasing order, so each rect is placed in the right position.
Viceversa, if the user click on a column label.
Each react is placed in the right way but I'm not able to place the sparkline.
Here the code.
When the user click on a row label, also the path inside the svg containing the sparkline should be updated.
And then, when the user click on a column label, the svg containing the sparkline should be placed in the correct line.
To place the svg in the right place, I try to use the x and y attributes of svg. They are updated but the svg doesn't change its position. Why?
Here is a piece of code related to that:
var t = svg.transition().duration(1000);
var values = [];
var sorted;
sorted = d3.range(numRegions).sort(function(a, b) {
if(sortOrder) {
return values[b] - values[a];
}
else {
return values[a] - values[b];
}
});
t.selectAll('.rowLabel')
.attr('y', function(d, k) {
return sorted.indexOf(k) * cellSize;
});
Also, I don't know how to change the path of every sparkline svg. I could take the data and order them manually, but this is only good for the row on which the user has clicked and not for all the others.
How can I do?
The vertical and horizontal re-positioning/redrawing of those sparklines require different approaches:
Vertical adjustment
For this solution I'm using selection.sort, which:
Returns a new selection that contains a copy of each group in this selection sorted according to the compare function. After sorting, re-inserts elements to match the resulting order.
So, first, we set our selection:
var sortedSVG = d3.selectAll(".data-svg")
Then, since selection.sort deals with data, we bind the datum, which is the index of the SVG regarding your sorted array:
.datum(function(d){
return sorted.indexOf(+this.dataset.r)
})
Finally, we compare them in ascending order:
.sort(function(a,b){
return d3.ascending(a,b)
});
Have in mind that the change is immediate, not a slow and nice transition. This is because the elements are re-positioned in the DOM, and the new structure is painted immediately. For having a slow transition, you'll have to deal with HTML and CSS inside the container div (which may be worth a new specific question).
Horizontal adjustment
The issue here is getting all the relevant data from the selection:
var sel = d3.selectAll('rect[data-r=\'' + k + '\']')
.each(function() {
arr.push({value:+d3.select(this).attr('data-value'),
pos: +d3.select(this).attr('data-c')});
});
And sorting it according to data-c. After that, we map the result to a simple array:
var result = arr.sort(function(a,b){
return sorted.indexOf(a.pos) - sorted.indexOf(b.pos)
}).map(function(d){
return d.value
});
Conclusion
Here is the updated Plunker: http://next.plnkr.co/edit/85fIXWxmX0l42cHx or http://plnkr.co/edit/85fIXWxmX0l42cHx
PS: You'll need to re-position the circles as well.

d3 v4 select behaves differently when using a var

For some reason, these two code blocks behave differently for their children on the first run:
var date = this.svg.selectAll(".date")
.data(data);
date
.enter()
...
and
var date = this.svg.selectAll(".date")
.data(data)
.enter()
...
In the first example, the subsequent date.selectAll(".bar").data(d => d.animal).enter; has no items in .enter, whereas in the second example, there are items (but the subsequent updates don't work correctly). The even stranger thing is that if I just run the broken block twice, both of my problems are fixed.
When I use the variable, the _groups property is an empty array with the right length (placeholders?). When I chain functions without the variable, the _groups property is an array with the expected elements bound to data. I expected the binding to be done by the end of this block either way, but it's not.
jsfiddle
Side note: if you can help with the animation to start at the bottom only on .enter, that would be incredible
Selections in d3 v4 are immutable. This means that the subselections (to create the rectangles) are:
1: Never operating on the Entered elements
let date = svg.selectAll(".date").data(data);
// date selection/subselections don't contain entered elements
date.enter();
// date selection/subselections STILL don't not contain entered elements
2: Operating on only the Updated parent elements the first time, which are none
let date = svg.selectAll(".date").data(data).enter();
// date selection contains entered, but not updated elements
Solution
I had to reassign the variable used, and merge the parent selection, even though I wasn't doing anything with the Updates from it. Personally I find this pattern to be a little more confusing than v4, and the documentation not giving a great example of this pitfall. It's also awkward to need to assign the variable before/during the .enter just so that you can merge in the Updated elements.
var date = svg.selectAll(".date")
.data(data);
date = date
.enter()
.append("g")
.attr("class", "date")
.attr("transform", d => `translate(${xScale0(d.date)},0)`)
.merge(date);
// date is now a selection that contains both the entered and updated elements
Fixed bars: https://jsfiddle.net/vvag4ycs/4/
Fixed bars & animation: https://jsfiddle.net/vvag4ycs/5/

Reorder elements on mouse over (to solve Z-index conflict) when data is bound through `selectAll.data(data)`

I am working on a d3 plot, where I have multiple elements which might overlap when drawn.
Each element renders a timeline and has multiple graphical units (start circle, line and end circle), something like as below:
O----------O O
O--------------------O
O-------O-----O-------O
For example the third line has two timeline plot elements which are overlapping as start time of the 2nd timeline is before end time of the first timeline. Note that 2nd timeline in the first line has only start time (as end time and start time are same).
Now, the following code brings an element of the timeline to front on mouseover by moving the DOM node to be the last child of its parent.
d3.selection.prototype.moveToFront = function() {
return this.each(function(){
this.parentNode.appendChild(this);
});
};
But the problem is that this is not altering the order of the bound data and is breaking the overall plot.
Each of the plot element has specific order in the dom which is bound to the d3 data in the same order. When the code above changes the order to bring any element to the front it is breaking the order, it still thinks that the order of the children are the same, which is wrong.
Here is a sample JSFiddle to describe the issue:
https://jsfiddle.net/pixelord/g2gt1f03/57/
How can I retain the data order once I have altered the dom elements?
Thanks.
Instead of doing the html update by yourself let d3 do it, remember that d3 stands for data driven documents so rewrite your problem as
On mouseover move the selection's datum to the last position and then rerender the graph
Imagine that your data is [0,1,2,3], when you mouseover on any element that represents the second datum you move the second datum to the last position i.e. [0,2,3,1] and that's pretty much it
.on("mouseover", function() {
var selection = d3.select(this);
var d = selection.datum()
// find d in data, extract it and push it
var index = data.indexOf(d)
var extract = data.splice(index, 1)
data = data.concat(extract)
draw()
});
Next when you bind your data make sure you add a way to distinguish from both states which is done with the second parameter sent to the .data() function which might be an id
var data = [
[5, 8, 6],
[10, 10, 6],
[20, 25, 6],
[23, 27, 6]
].map(function (d, i) {
return {
id: i,
x1: d[0],
y1: d[2],
x2: d[1],
y2: d[2]
}
});
// ...
var itemGroup = maingroup.selectAll(".itemGroup")
.data(data, function (d) { return d.id })
Finally you'll need to tell d3 that we have modified the order of the elements and that it needs to do what you were doing by hand which is reorder the elements
// update
itemGroup.order()
Demo
I like the way Mauricio solved the issue.
However, after some investigation I came to know that I can specify key value while binding the data. So here is my solution without re-ordering the data itself:
I added a key value property for each data object which is unique.
I specify the key value while binding the data like,
data(data_list, funcion(d){return d.keyValue})
the problem was fixed.

VBA Chart Manipulation Slow

I wrote some Excel VBA code that generates a scatterplot and changes a few properties of the chart. (Code is below for reference.) The code moves slowly through tasks like deleting the chart legend, removing horizontal/vertical gridlines, and changing the X and Y series. Excel's timer gives me the following duration for each task:
insert scatterplot: 0.01171875
delete series: 0
plot x vs y: 0.55859375
delete legend: 0.5703125
delete chart title: 0.66015625
remove grid: 1.3046875
format axes: 0
overall: 3.11328125
Removing the grid, changing the title, plotting the X and Y series, and deleting the legend seem to take a long time. I've googled for alternative ways to write the code, but haven't been able to find anything useful. The code works entirely as expected, except for the slow speed. Any ideas as to what's causing the bad performance, and how I can speed this up? Thanks in advance.
EDIT: I've already turned off screen updating while working with the chart. The chart is generated/formatted while a userform is open, if that makes any difference.
Here is the relevant snippet of code:
With ActiveChart
'Delete all series currently in plot
Do While .FullSeriesCollection.Count > 0
.FullSeriesCollection(1).Delete
Loop
'Plot Actual (Y) vs. Inverse Distribution (X)
.SeriesCollection.NewSeries
.FullSeriesCollection(1).XValues = "=" & tempSheetName & "!$C:$C"
.FullSeriesCollection(1).Values = "=" & tempSheetName & "!$A:$A"
'Delete legend
.Legend.Delete
'Delete chart title
.SetElement (msoElementChartTitleNone)
'Remove gridlines
.SetElement (msoElementPrimaryValueGridLinesNone)
.SetElement (msoElementPrimaryCategoryGridLinesNone)
'Format axes
Dim xAxis As Axis, yAxis As Axis
Set xAxis = .Axes(xlCategory)
Set yAxis = .Axes(xlValue)
With yAxis
'Title y axis "actual"
.HasTitle = True
.AxisTitle.Caption = "Actual"
'Add tick marks
.MajorTickMark = xlOutside
End With
With xAxis
'Title x axis by dist type
.HasTitle = True
.AxisTitle.Caption = dist.getDistType
'Add tick marks
.MajorTickMark = xlOutside
End With
End With
Without the data and machine specifics it can be hard to say why this is slow, although here are some alternatives to some of the code you have.
The first and foremost thing I'd change is not to Activate the chart. If you are creating the chart through code, do so but set it to a variable, eg Set wcChart = ThisWorkbook.Charts.Add. Then change With ActiveChart to With wcChart.
Also, delete the FullSeriesCollection and then delete the chart title, remove the gridlines and change the axes before filling up the new data. The chart manipulation should be quicker with less data in the chart. Be careful here though because changing aspects of the chart in different orders can produce different outputs (as an example the layout of a legend).
You fill the new FullSeriesCollection with the entire columns of A and C, specify the exact range of the data rather than the whole column.
Other changes to try, I'm not saying these will work but they are worth a shot if you haven't tried. Instead of checking for a FullSeriesCollection each time:
Do While .FullSeriesCollection.Count > 0
.FullSeriesCollection(1).Delete
Loop
The following may be quicker:
For ii = .FullSeriesCollection.Count To 1 Step -1
.FullSeriesCollection(ii).Delete
Next ii
Also, instead of .SetElement for the Chart title and Gridlines I use the following:
'You have to set the title to 'True' before it'll work with 'False'. Go figure.
.HasTitle = True
.HasTitle = False
.HasMajorGridlines = False
.HasMinorGridlines = False

Line Plus Bar with Multi Bars?

I'm trying to make an chart using the default line plus bar chart, but I want to use two or more streams in the bars, is it possible?
Currently, when I try to do this, I got some trouble with the effects of the chart, and so I can't show properly the hover balloon of the bars, he always display the data of just one of the streams. But the main problem is the dates of x axis, displaying 1970's dates, when I remove the second stream of bars, the dates display well:
Anyone already tried to do this kind of chart successfully?
EDIT
Adding Fiddles:
Fiddle with two columns stream and messy dates
Fiddle with just one column stream and ok dates
I'm calling this kind of graph:
linePlusBarChart()
The problem with the dates is that your data contains timestamps (i.e. in seconds), but Javascript expects milliseconds. This is easily fixed by multiplying the values by 1000:
series.values = series.values.map(function (d) {
return {
x: d[0]*1000,
y: d[1]
}
});
The tooltip problem is actually a bug in NVD3 -- it's not meant to be used this way. The problem boils down to the mouseover handler assuming that the first item of the data is representative of what you want. You can fix this for your case by selecting the item by data point number modulo 2 (because there're two bars):
.on('mouseover', function(d,i) {
d3.select(this).classed('hover', true);
dispatch.elementMouseover({
point: d,
series: data[i%2],
pos: [x(getX(d,i)), y(getY(d,i))],
pointIndex: i,
seriesIndex: i%2,
e: d3.event
});
})
This will only work for exactly two bar series though. Updated jsfiddle with the modified NVD3 code here.

Resources