· Ensuring mobile-only
· Aiming for consistency across Mobile OS, browser apps
· Handling orientation changes
· Handling interruptions
· Handling touch events
· Trial interaction design
· Compartmentalizing the app
· Logging participant activity + metadata
< head >
...
< meta name="HandheldFriendly"
content="true" />
< meta name="apple-mobile-web-app-capable"
content="yes" />
< meta name="mobile-web-app-capable"
content="yes" />
< meta name="viewport"
content="minimal-ui,
width=device-width,
initial-scale=1.0,
minimum-scale=1.0,
maximum-scale=1.0,
user-scalable=no" />
...
< /head>
In non-experimental settings, set user-scalable to yes for accessibility.
@media only screen
and (min-device-width: 320px)
and (max-device-width: 1440px)
and (max-device-height: 1440px)
and (-webkit-min-device-pixel-ratio: 2)
and (orientation: portrait) {
...
}
@media only screen
and (orientation: landscape) {
...
}
@media only screen
and (min-device-width: 1440px) {
...
}
Most contemporary smartphones have device pixel ratios > 2.
Ensure desired phone orientation (portrait / landscape)
window.addEventListener('load', function() {
// respond to loading in undesirable orientation
}
window.onresize = function(e) {
// respond to rotation to undesirable orientation
}
e.g., the participant switches apps, responds to a notification, etc.
window.onblur = function(e) {
// respond to interruption (e.g., log + discard trial)
}
window.onfocus = function(e) {
// respond to resumption
}
d3.select('#some_button')
.on('touchstart', function() {
d3.event.preventDefault();
// respond to touch event
}
Also: touchmove, touchend
app.js // node application requiring express, socket.io, ...
package.json
participantList.js // for server-side condition allocation
web.config
webpack.config.js
src
globals.js // global variables
index.js // app initialization
dataset.js // stimuli data (UN economic metrics)
chart.js // the visualization stimuli
taskList.js // experimental task specifications
initTasks.js // allocate tasks and conditions to participant
trial.js // specifying the logic of a single trial
public
style.css
index.html
main.js // output from webpack
assets // folder of images, icons, etc.
trial = {
user_id: userID,
trial_index: trial_index,
condition: trial_condition,
accuracy: 0,
start_time: 0,
interruptions: 0,
interruption_time: 0,
end_time: 0,
completion_time: 0,
give_up: false,
...
};
appInsights.trackEvent("TrialComplete", trial);
Application Insights custom event logging also includes client metadata in the tail of each log event (e.g., device, browser, approximate location).
> colnames(p_metadata.df)
[1] "user_id" "load_time" "completion_time" "duration"
[5] "client_Model" "client_OS" "client_Reg" "client_Browser"
[9] "condition" "ordering" "Height" "Width"
[13] "chart_dim" "excluded"
> levels(p_metadata.df$client_OS) # MobileTrendVis
[1] "Android"
"Android 4.3"
"Android 5.0"
"Android 5.1"
"Android 6.0"
"Android 7.0"
"Android 7.1"
[8] "Android 8.0"
"Android 8.1"
"iOS 10.3"
"iOS 11.4"
"iOS 12.0"
"iOS 12.1"
> levels(p_metadata.df$client_Browser) # MobileTrendVis
[1] "Chrome Mobile 51.0"
"Chrome Mobile 56.0"
"Chrome Mobile 59.0"
"Chrome Mobile 67.0"
[5] "Chrome Mobile 68.0"
"Chrome Mobile 69.0"
"Chrome Mobile 70.0"
"Chrome Mobile 71.0"
[9] "Chrome Mobile iOS 68.0"
"Chrome Mobile iOS 70.0"
"Chrome Mobile iOS 71.0"
"Facebook 193.0"
[13] "Firefox iOS 13.2"
"Firefox Mobile 63.0"
"Mobile Safari 10.0"
"Mobile Safari 11.0"
[17] "Mobile Safari 12.0"
"Samsung Internet 7.4"
> summary(participant_metadata.df$Height)# MobileTrendVis
Min. 1st Qu. Median Mean 3rd Qu. Max.
452.0 549.2 560.0 587.0 620.5 822.0
> summary(participant_metadata.df$Width)# MobileTrendVis
Min. 1st Qu. Median Mean 3rd Qu. Max.
320.0 360.0 375.0 378.6 412.0 414.0
Ranges Over Time experiment (InfoVis 2018):
· 13 colleagues in pilot experiment #1, local & remote
· 12 crowdsourced participants (MTurk) in pilot experiment #2
· 100 crowdsourced participants (MTurk) in final experiment (13 excluded)
---
· 125 participants (total)
Mobile Trend Vis experiment (InfoVis 2019):
· 20 colleagues in pilot experiment #1, local & remote
· 16 crowdsourced participants (MTurk) in pilot experiment #2
· 16 crowdsourced participants (MTurk) in pilot experiment #3 (improved quality control, added trial time-out)
· 113 crowdsourced participants (MTurk) in final experiment (17 excluded)
---
· 165 participants (total)
socket.on('userID', function(msg) { // new participant
if (participantList.length > 0) {
// move next participant to progressList
// participantList contains condition assignments
}
else if (completedList.length > 0) {
// add extra participant considering completedList
// and its participants' condition assignments
}
else if (progressList.length > 0) {
// add extra participant when no one has finished yet
}
else {
// this shouldn't ever happen, but if it does, randomize
}
}
RangesOnMobile, MobileTrendVis experimental applications share common infrastructure:
· Node.js web application deployed on Azure
· Custom event logging with Azure Application Insights
· CSS media queries to enforce mobile-only
· Sever-side condition assignment & re-balancing
· Handlers for orientation changes & interruptions
Application developer to focus on:
· Isolated chart component
· Defining trial logic
· Trial bank initialization
Mobile-only alternative (or extension of) the experimentr framework?
experimentr. L. Harrison,
C. Gramazio, F. Yang, K. Aragam, E. Peck, and D. Schroeder (2019).
github.com/codementum/experimentr