init
1
.dockerignore
Normal file
@@ -0,0 +1 @@
|
|||||||
|
PCSurvey/potree/pointclouds
|
||||||
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
PCSurvey/potree/pointclouds
|
||||||
|
*.tar
|
||||||
48
DOC.md
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
|
||||||
|
# Interactive Point Cloud Study
|
||||||
|
|
||||||
|
This project is the implementation of a point cloud study on QoE described in my Bachelor’s thesis.
|
||||||
|
|
||||||
|
### Brief Summary of Study Flow:
|
||||||
|
- User and task instructions
|
||||||
|
- Trial run
|
||||||
|
- Study begins
|
||||||
|
- End / Feedback / Code issuance
|
||||||
|
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
The folder **PCSurvey** contains all the code for the study. The folder **PCStatic** contains images and HTML files for the instruction and information phases of the study.
|
||||||
|
|
||||||
|
The files *survey.html* and *survey.js* serve as the entry point and logic for the study. The *survey.js* file constructs the study flow using jsPsych.
|
||||||
|
### The "potree" folder
|
||||||
|
It contains a folder **pointclouds**, which includes all the point clouds used for the study.
|
||||||
|
|
||||||
|
The file *paired_comparison_template.html* creates the interface for this evaluation condition. This interface was developed early on but ultimately was not used. It requires minor adaptations but is overall functional.
|
||||||
|
|
||||||
|
The files *sequentiell_template.html* and *sequentiell_template2.html* serve as the interfaces for the sequential evaluation method. We have two versions: one is the first, and the other is the second. It is necessary for them to be separate, even though they are very similar, due to the external HTML loading process in jsPsych.
|
||||||
|
|
||||||
|
The files *single_page_template_\*.html* are designated for each element and test condition (1, 2, and 3 elements in the cloud). Each stimulus varies in size and requires special configuration. These files manage those configurations.
|
||||||
|
|
||||||
|
All the mentioned files are used in the *survey.js* file to dynamically generate the evaluation block for the study.
|
||||||
|
|
||||||
|
|
||||||
|
## Deployment
|
||||||
|
The *docker-compose.yml* file provides an example configuration for starting the Docker container with the study. It builds the container using the *Dockerfile* and mounts the volumes for the point cloud folder and the output folder for the captured user data.
|
||||||
|
|
||||||
|
Configure mounting and ports based on your case.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
After deployment, it can be accessed on:
|
||||||
|
|
||||||
|
http://localhost/survey.html?worker=0&campaign=0&randkey=0
|
||||||
|
|
||||||
|
The parameters are necessary to pass the requirement test for the study.
|
||||||
|
|
||||||
|
## Authors
|
||||||
|
|
||||||
|
- Andreas Wilms
|
||||||
|
|
||||||
36
Dockerfile
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
# Verwenden Sie das offizielle PHP-Bild mit Apache
|
||||||
|
FROM php:8.1-apache
|
||||||
|
|
||||||
|
# Aktivieren Sie Apache-Module
|
||||||
|
RUN a2enmod rewrite ssl
|
||||||
|
|
||||||
|
# Kopieren Sie die PHP-Anwendungsdateien in das richtige Verzeichnis
|
||||||
|
COPY PCSurvey/ /var/www/html/
|
||||||
|
|
||||||
|
# Kopieren Sie die SSL-Zertifikate in die richtigen Verzeichnisse
|
||||||
|
COPY server.pem /etc/ssl/certs/server.pem
|
||||||
|
COPY server.key /etc/ssl/private/server.key
|
||||||
|
|
||||||
|
# Kopieren Sie die Apache SSL-Konfigurationsdatei
|
||||||
|
COPY httpd-ssl.conf /etc/apache2/sites-available/default-ssl.conf
|
||||||
|
|
||||||
|
# Fügen Sie eine ServerName Direktive in der Apache-Konfigurationsdatei hinzu
|
||||||
|
RUN echo "ServerName netcom-survey2.informatik.uni-augsburg.de" >> /etc/apache2/apache2.conf
|
||||||
|
|
||||||
|
# Aktivieren Sie die Standard-SSL-Site
|
||||||
|
RUN a2ensite default-ssl
|
||||||
|
|
||||||
|
# Exponieren Sie die Ports 80 und 443
|
||||||
|
EXPOSE 80 443
|
||||||
|
|
||||||
|
# Stellen Sie sicher, dass die Berechtigungen für die Anwendungsdateien korrekt sind
|
||||||
|
RUN chown -R www-data:www-data /var/www/html
|
||||||
|
RUN chmod -R 755 /var/www/html
|
||||||
|
|
||||||
|
# Create the /Data directory and set permissions
|
||||||
|
RUN mkdir -p /Data
|
||||||
|
RUN chown -R www-data:www-data /Data
|
||||||
|
RUN chmod -R 755 /Data
|
||||||
|
|
||||||
|
# Starten Sie den Apache-Server
|
||||||
|
CMD ["apache2-foreground"]
|
||||||
BIN
PCSurvey/.DS_Store
vendored
Normal file
92
PCSurvey/PCstatic/css/instructions.css
Normal file
@@ -0,0 +1,92 @@
|
|||||||
|
@font-face {
|
||||||
|
font-family: 'Cardo';
|
||||||
|
src: url(https://jonathan-harrell.com/wp-content/themes/jonathanharrell/fonts/Cardo-Italic.woff) format('woff2');
|
||||||
|
}
|
||||||
|
|
||||||
|
#intro_text {
|
||||||
|
max-width: 40rem;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 1rem;
|
||||||
|
text-align: left;
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
section {
|
||||||
|
margin-top: 3rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
#intro_text h1,
|
||||||
|
h2,
|
||||||
|
h3,
|
||||||
|
h4,
|
||||||
|
h5,
|
||||||
|
h6 {
|
||||||
|
line-height: 1.2;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
text-decoration: none;
|
||||||
|
color: #2eec96;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
height: 1px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
background-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.instructions ul,
|
||||||
|
.instructions ol {
|
||||||
|
margin: 0.075rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions li {
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions ul {
|
||||||
|
list-style: none;
|
||||||
|
padding-left: 50px;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions ul li {
|
||||||
|
position: relative;
|
||||||
|
padding-left: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions ul li::before {
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
content: '•';
|
||||||
|
}
|
||||||
|
|
||||||
|
.instructions ol {
|
||||||
|
padding-left: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
figure {
|
||||||
|
margin: 2rem 0;
|
||||||
|
padding: 1rem 0;
|
||||||
|
border-top: 1px solid #ccc;
|
||||||
|
border-bottom: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
#intro_text header h1 {
|
||||||
|
margin-top: 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
header p {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
p.thick {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#consent {
|
||||||
|
margin-bottom: 50px
|
||||||
|
}
|
||||||
125
PCSurvey/PCstatic/css/jspsych.css
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
/*
|
||||||
|
* CSS for jsPsych experiments.
|
||||||
|
*
|
||||||
|
* This stylesheet provides minimal styling to make jsPsych
|
||||||
|
* experiments look polished without any additional styles.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import url(https://fonts.googleapis.com/css?family=Open+Sans:400italic,700italic,400,700);
|
||||||
|
|
||||||
|
/* Container holding jsPsych content */
|
||||||
|
|
||||||
|
.jspsych-display-element {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jspsych-display-element:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jspsych-content-wrapper {
|
||||||
|
display: flex;
|
||||||
|
margin: auto;
|
||||||
|
flex: 1 1 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jspsych-content {
|
||||||
|
max-width: 95%; /* this is mainly an IE 10-11 fix */
|
||||||
|
text-align: center;
|
||||||
|
margin: auto; /* this is for overflowing content */
|
||||||
|
}
|
||||||
|
|
||||||
|
.jspsych-top {
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jspsych-middle {
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fonts and type */
|
||||||
|
|
||||||
|
.jspsych-display-element {
|
||||||
|
font-family: 'Open Sans', 'Arial', sans-serif;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.6em;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Form elements like input fields and buttons */
|
||||||
|
|
||||||
|
.jspsych-display-element input[type="text"] {
|
||||||
|
font-family: 'Open Sans', 'Arial', sans-serif;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* borrowing Bootstrap style for btn elements, but combining styles a bit */
|
||||||
|
.jspsych-btn {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 6px 12px;
|
||||||
|
margin: 0px;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: 400;
|
||||||
|
font-family: 'Open Sans', 'Arial', sans-serif;
|
||||||
|
cursor: pointer;
|
||||||
|
line-height: 1.4;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle;
|
||||||
|
background-image: none;
|
||||||
|
border: 1px solid transparent;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #333;
|
||||||
|
background-color: #fff;
|
||||||
|
border-color: #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jspsych-btn:hover {
|
||||||
|
background-color: #ddd;
|
||||||
|
border-color: #aaa;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jspsych-btn:disabled {
|
||||||
|
background-color: #eee;
|
||||||
|
color: #aaa;
|
||||||
|
border-color: #ccc;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* jsPsych progress bar */
|
||||||
|
|
||||||
|
#jspsych-progressbar-container {
|
||||||
|
color: #555;
|
||||||
|
border-bottom: 1px solid #dedede;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
text-align: center;
|
||||||
|
padding: 8px 0px;
|
||||||
|
width: 100%;
|
||||||
|
line-height: 1em;
|
||||||
|
}
|
||||||
|
#jspsych-progressbar-container span {
|
||||||
|
font-size: 14px;
|
||||||
|
padding-right: 14px;
|
||||||
|
}
|
||||||
|
#jspsych-progressbar-outer {
|
||||||
|
background-color: #eee;
|
||||||
|
width: 50%;
|
||||||
|
margin: auto;
|
||||||
|
height: 14px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0,0,0,0.1);
|
||||||
|
}
|
||||||
|
#jspsych-progressbar-inner {
|
||||||
|
background-color: #aaa;
|
||||||
|
width: 0%;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Control appearance of jsPsych.data.displayData() */
|
||||||
|
#jspsych-data-display {
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
187
PCSurvey/PCstatic/css/main.css
Normal file
@@ -0,0 +1,187 @@
|
|||||||
|
.clear_content {
|
||||||
|
all:initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#end-trial {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#replay {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.debug {
|
||||||
|
display:none;
|
||||||
|
background: #000;
|
||||||
|
color: #ff2277
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-fit_fill { object-fit: fill }
|
||||||
|
.object-fit_contain { object-fit: contain }
|
||||||
|
.object-fit_cover { object-fit: cover }
|
||||||
|
.object-fit_none { object-fit: none }
|
||||||
|
.object-fit_scale-down { object-fit: scale-down }
|
||||||
|
|
||||||
|
.work_container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
grid-template-columns: 188px auto 188px;
|
||||||
|
grid-template-areas:
|
||||||
|
"work1 work2 work3 "
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
font-family: "Courier New", Courier, serif;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 30px 100px 120px 40px 377px 377px 200px;
|
||||||
|
grid-template-columns: auto 565px 565px auto;
|
||||||
|
grid-gap: 20px 20px;
|
||||||
|
grid-template-areas:
|
||||||
|
". blank blank . "
|
||||||
|
". header_l header_r . "
|
||||||
|
". title_l title_r . "
|
||||||
|
". spacer spacer ."
|
||||||
|
". image1 image2 ."
|
||||||
|
". image3 image4 ."
|
||||||
|
". about work ."
|
||||||
|
}
|
||||||
|
|
||||||
|
.container_noimages {
|
||||||
|
font-family: "Courier New", Courier, serif;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 30px 100px 120px 40px 200px;
|
||||||
|
grid-template-columns: auto 565px 565px auto;
|
||||||
|
grid-gap: 20px 20px;
|
||||||
|
grid-template-areas:
|
||||||
|
". blank blank . "
|
||||||
|
". header_l header_r . "
|
||||||
|
". title_l title_r . "
|
||||||
|
". spacer spacer ."
|
||||||
|
". about work ."
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
visibility: hidden;
|
||||||
|
font-family: "Courier New", Courier, serif;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 30px 100px 30px;
|
||||||
|
grid-template-columns: auto 585px 565px auto;
|
||||||
|
background: #001122;
|
||||||
|
grid-template-areas:
|
||||||
|
". . . . "
|
||||||
|
". footer_left footer_right . "
|
||||||
|
". . . . "
|
||||||
|
}
|
||||||
|
|
||||||
|
.blank {
|
||||||
|
grid-area: blank;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer {
|
||||||
|
grid-area: spacer;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.left_header {
|
||||||
|
grid-area: header_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right_header {
|
||||||
|
grid-area: header_r;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.left_title {
|
||||||
|
grid-area: title_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left_title {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right_title {
|
||||||
|
grid-area: title_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img1{
|
||||||
|
grid-area: image1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img2{
|
||||||
|
grid-area: image2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img3 {
|
||||||
|
grid-area: image3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img4 {
|
||||||
|
grid-area: image4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worklist {
|
||||||
|
grid-area: work;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about {
|
||||||
|
grid-area: about;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worklist.work1{
|
||||||
|
grid-area: work1;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worklist.work2{
|
||||||
|
grid-area: work2;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worklist.work3{
|
||||||
|
grid-area: work3;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_left {
|
||||||
|
grid-area: footer_left;
|
||||||
|
color: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background: #001122;
|
||||||
|
height: 130px
|
||||||
|
}
|
||||||
|
|
||||||
|
img[class] {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left_header > img {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallimg {
|
||||||
|
height:48px;
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.experts {
|
||||||
|
font-size: 19px
|
||||||
|
}
|
||||||
259
PCSurvey/PCstatic/css/main_3col.css
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
#currentscore, #total_current_score {
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.clear_content {
|
||||||
|
all:initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.test {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#end-trial {
|
||||||
|
width: 110px;
|
||||||
|
height: 45px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#infotext {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#left-right{
|
||||||
|
width: 45%;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#right-left{
|
||||||
|
width: 45%;
|
||||||
|
height: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#replay {
|
||||||
|
width: 100px;
|
||||||
|
height: 47px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container > div {
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.head > div {
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer > div {
|
||||||
|
visibility:hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.debug {
|
||||||
|
display:none;
|
||||||
|
background: #000;
|
||||||
|
color: #ff2277
|
||||||
|
}
|
||||||
|
|
||||||
|
.hidden {
|
||||||
|
visibility: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.display_toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.object-fit_fill { object-fit: fill }
|
||||||
|
.object-fit_contain { object-fit: contain }
|
||||||
|
.object-fit_cover { object-fit: cover }
|
||||||
|
.object-fit_none { object-fit: none }
|
||||||
|
.object-fit_scale-down { object-fit: scale-down }
|
||||||
|
|
||||||
|
.work_container {
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: auto;
|
||||||
|
grid-template-columns: 120px 200px 200px 200px;
|
||||||
|
grid-template-areas:
|
||||||
|
" . work1 work2 work3 "
|
||||||
|
}
|
||||||
|
|
||||||
|
.head {
|
||||||
|
visibility: hidden;
|
||||||
|
font-family: "Courier New", Courier, serif;
|
||||||
|
display: grid;
|
||||||
|
/* grid-template-rows: 30px 100px 120px 40px 377px 377px 250 1fr; */
|
||||||
|
grid-template-columns: auto 350px 350px 350px auto;
|
||||||
|
grid-gap: 20px 20px;
|
||||||
|
grid-template-areas:
|
||||||
|
". blank blank blank . "
|
||||||
|
". header_l header_l header_r . "
|
||||||
|
". title_l title_l title_r . "
|
||||||
|
". spacer spacer spacer ."
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
align-items: center;
|
||||||
|
font-family: "Courier New", Courier, serif;
|
||||||
|
display: grid;
|
||||||
|
/* grid-template-rows: 30px 100px 120px 40px 377px 377px 250 1fr; */
|
||||||
|
grid-template-columns: auto 350px 350px 350px auto;
|
||||||
|
grid-gap: 20px 20px;
|
||||||
|
grid-template-areas:
|
||||||
|
/* ". blank blank blank . "
|
||||||
|
". header_l header_l header_r . "
|
||||||
|
". title_l title_l title_r . "
|
||||||
|
". spacer spacer spacer ." */
|
||||||
|
". text1 image1 image2 ."
|
||||||
|
". image3 image4 text2 ."
|
||||||
|
". image5 text3 image6 ."
|
||||||
|
". about work work ."
|
||||||
|
". hfh hfh hfh ."
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer {
|
||||||
|
align-items: left;
|
||||||
|
visibility: hidden;
|
||||||
|
font-family: "Courier New", Courier, serif;
|
||||||
|
display: grid;
|
||||||
|
grid-template-rows: 30px 100px 30px;
|
||||||
|
grid-gap: 20px 20px;
|
||||||
|
grid-template-columns: auto 350px 350px 350px auto;
|
||||||
|
background: #001122;
|
||||||
|
grid-template-areas:
|
||||||
|
". . . . . "
|
||||||
|
". footer_left footer_left footer_right . "
|
||||||
|
". . . . . "
|
||||||
|
}
|
||||||
|
|
||||||
|
.blank {
|
||||||
|
grid-area: blank;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spacer {
|
||||||
|
grid-area: spacer;
|
||||||
|
border-top: 1px solid #eee;
|
||||||
|
height: 30px
|
||||||
|
}
|
||||||
|
|
||||||
|
.text1 {
|
||||||
|
grid-area: text1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text2 {
|
||||||
|
grid-area: text2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text3 {
|
||||||
|
grid-area: text3;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.left_header {
|
||||||
|
grid-area: header_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right_header {
|
||||||
|
grid-area: header_r;
|
||||||
|
text-align: right;
|
||||||
|
font-size: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.left_title {
|
||||||
|
grid-area: title_l;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left_title {
|
||||||
|
font-size: 48px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right_title {
|
||||||
|
grid-area: title_r;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img1{
|
||||||
|
grid-area: image1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img2{
|
||||||
|
grid-area: image2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img3 {
|
||||||
|
grid-area: image3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img4 {
|
||||||
|
grid-area: image4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img5 {
|
||||||
|
grid-area: image5;
|
||||||
|
}
|
||||||
|
|
||||||
|
.img6 {
|
||||||
|
grid-area: image6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.worklist {
|
||||||
|
grid-area: work;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.about {
|
||||||
|
grid-area: about;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work1{
|
||||||
|
grid-area: work1;
|
||||||
|
display: inline-block
|
||||||
|
}
|
||||||
|
|
||||||
|
.work2{
|
||||||
|
grid-area: work2;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.work3{
|
||||||
|
grid-area: work3;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.footer_left {
|
||||||
|
grid-area: footer_left;
|
||||||
|
color: #fff
|
||||||
|
}
|
||||||
|
|
||||||
|
.header {
|
||||||
|
background: #001122;
|
||||||
|
height: 130px
|
||||||
|
}
|
||||||
|
|
||||||
|
.test img {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.left_header > img {
|
||||||
|
width: 50px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.smallimg {
|
||||||
|
height:48px;
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-bottom: 10px
|
||||||
|
}
|
||||||
|
|
||||||
|
.experts {
|
||||||
|
font-size: 19px
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 19px
|
||||||
|
}
|
||||||
|
|
||||||
|
#screenshot {
|
||||||
|
position: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
#slider {
|
||||||
|
width: 40%;
|
||||||
|
height: auto;
|
||||||
|
padding-top: 20px;
|
||||||
|
padding-bottom: 20px
|
||||||
|
}
|
||||||
79
PCSurvey/PCstatic/html/feedback.html
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Document</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
width: 20%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #bc0ba8;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
button:not(:disabled):hover {
|
||||||
|
background: #5d0570;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<section>
|
||||||
|
<h1 id="caption">Incorrect! You selected the wrong letter.</h1>
|
||||||
|
<h3 id="info-text">Don't worry, you can try again!</h3>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<button id="end-trial">Restart</button>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
var responses = JSON.parse(
|
||||||
|
jsPsych.data.get().last(1).select("responses").values
|
||||||
|
);
|
||||||
|
var controlLetter = jsPsych.data.get().last(1).select("controlLetter1")
|
||||||
|
.values[0];
|
||||||
|
var controlLetter2 = jsPsych.data.get().last(1).select("controlLetter2")
|
||||||
|
.values[0];
|
||||||
|
|
||||||
|
var controlLetter3 = jsPsych.data.get().last(1).select("controlLetter3")
|
||||||
|
.values[0];
|
||||||
|
|
||||||
|
if (responses.Q1 == controlLetter && responses.Q2 == controlLetter2 && responses.Q3 == controlLetter3) {
|
||||||
|
document.getElementById("caption").innerText = "Correct!";
|
||||||
|
document.getElementById("info-text").innerText =
|
||||||
|
"While searching for control letters, remember that rating the cloud quality is the top priority.";
|
||||||
|
document.getElementById("end-trial").innerText = "Let's go!";
|
||||||
|
} else {
|
||||||
|
document.getElementById("caption").innerText =
|
||||||
|
"Incorrect! You selected the wrong letter.";
|
||||||
|
document.getElementById("info-text").innerText =
|
||||||
|
"Don't worry, you can try again!";
|
||||||
|
document.getElementById("end-trial").innerText = "Restart";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
74
PCSurvey/PCstatic/html/feedback_no_emphasis_quality.html
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8" />
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||||
|
<title>Document</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
width: 20%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #bc0ba8;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
button:not(:disabled):hover {
|
||||||
|
background: #5d0570;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<section>
|
||||||
|
<h1 id="caption">Incorrect! You selected the wrong letter.</h1>
|
||||||
|
<h3 id="info-text">Don't worry, you can try again!</h3>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<button id="end-trial">Restart</button>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
var responses = JSON.parse(
|
||||||
|
jsPsych.data.get().last(1).select("responses").values
|
||||||
|
);
|
||||||
|
var controlLetter = jsPsych.data.get().last(1).select("controlLetter1")
|
||||||
|
.values[0];
|
||||||
|
|
||||||
|
if (responses.Q1 == controlLetter) {
|
||||||
|
document.getElementById("caption").innerText = "Correct!";
|
||||||
|
document.getElementById("info-text").innerText =
|
||||||
|
"You selected the correct letter! Now you can proceed to the study.";
|
||||||
|
document.getElementById("end-trial").innerText = "Let's go!";
|
||||||
|
} else {
|
||||||
|
document.getElementById("caption").innerText =
|
||||||
|
"Incorrect! You selected the wrong letter.";
|
||||||
|
document.getElementById("info-text").innerText =
|
||||||
|
"Don't worry, you can try again!";
|
||||||
|
document.getElementById("end-trial").innerText = "Restart";
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
44
PCSurvey/PCstatic/html/instructions.html
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
||||||
|
<!-- <link rel="stylesheet" href="https://use.typekit.net/hpq3bof.css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Lancelot" rel="stylesheet"> -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="intro_text">
|
||||||
|
<header>
|
||||||
|
<h1>Test Instructions</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<section>
|
||||||
|
<h2>Your Task</h2>
|
||||||
|
<p>You will first see a picture in original quality (left).</p>
|
||||||
|
<div>
|
||||||
|
<img id="Bsp1" style="width:420px;height:280px;margin:10px" src="PCstatic/img/Text/Text-OR-G-E.png" />
|
||||||
|
<img id="Bsp2" style="width:420px;height:280px;margin:10px" src="PCstatic/img/Text/Text-OC-V8-G-H.png" />
|
||||||
|
</div>
|
||||||
|
<p>After that you see a picture of a reduced quality (right).</p>
|
||||||
|
<p>Your Task:</p>
|
||||||
|
<ul>
|
||||||
|
<li>Rate the quality of the picture.</li>
|
||||||
|
<ul>
|
||||||
|
<li><b>Good quality</b> is given if the surfaces of objects are smooth and easily recognisable.</li>
|
||||||
|
<li>A picture of <b>bad quality</b> has less recognisable surfaces.</li>
|
||||||
|
</ul>
|
||||||
|
<li>Rate the difference in quality between the original picture and the reduced picture.</li>
|
||||||
|
<li>In addition on each picture there will be a red letter in the top right corner. Memorize it and Tick/Check the corresponding box your rating.</li>
|
||||||
|
</ul>
|
||||||
|
<p></p>
|
||||||
|
<p>Further informations on the topic are at the end of the survey.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
<button type="jspsych-btn" id="consent">I agree to take part in this study.</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<!-- Cache served by Simple Cache - Last modified: Thu, 05 Jul 2018 02:27:42 GMT -->
|
||||||
150
PCSurvey/PCstatic/html/instructions_P0.html
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Point Clouds and VR: Research Introduction</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #333;
|
||||||
|
text-align: center;
|
||||||
|
border-bottom: 2px solid #333;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
}
|
||||||
|
h2 {
|
||||||
|
font-size: 20px;
|
||||||
|
color: #444;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
display: block;
|
||||||
|
margin: 20px auto;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
width: 20%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #bc0ba8;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
button:disabled {
|
||||||
|
background: #ccc;
|
||||||
|
color: #666;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:disabled):hover {
|
||||||
|
background: #5d0570;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
.highlight {
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border-left: 4px solid #4a4a4a;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px 0;
|
||||||
|
}
|
||||||
|
.important-note {
|
||||||
|
background-color: #e6e6e6;
|
||||||
|
border: 1px solid #4a4a4a;
|
||||||
|
border-radius: 3px;
|
||||||
|
padding: 15px;
|
||||||
|
margin-top: 20px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<section>
|
||||||
|
<h1>Point Clouds and Virtual Reality: Essential Research Introduction</h1>
|
||||||
|
|
||||||
|
<div class="important-note">
|
||||||
|
Please read the following introduction as it can be helpful for understanding the research.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>What is a Point Cloud?</h2>
|
||||||
|
<p>A point cloud is a set of data points in 3D space, typically representing the external surface of an object or environment. Each point has X, Y, and Z coordinates and may include additional information like color or intensity.</p>
|
||||||
|
|
||||||
|
<div class="highlight">
|
||||||
|
<strong>Key Features of Point Clouds:</strong>
|
||||||
|
<ul>
|
||||||
|
<li>Detailed 3D representation of objects and environments</li>
|
||||||
|
<li>Created using 3D scanners or LiDAR technology</li>
|
||||||
|
<li>Can contain millions of points for high-resolution models</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<img src="PCstatic/img/pointcloud_example.png" alt="Point Cloud Visualization">
|
||||||
|
|
||||||
|
<h2>Connection to Virtual Reality (VR)</h2>
|
||||||
|
<p>Point clouds play a crucial role in creating immersive VR experiences by bridging the gap between physical and virtual worlds.</p>
|
||||||
|
|
||||||
|
<div class="highlight">
|
||||||
|
<strong>How Point Clouds Enhance VR:</strong>
|
||||||
|
<ul>
|
||||||
|
<li>Create detailed and accurate 3D models of real-world environments</li>
|
||||||
|
<li>Enable the generation of immersive VR experiences</li>
|
||||||
|
<li>Allow users to explore digitally recreated spaces</li>
|
||||||
|
<li>Provide a data-driven foundation for realistic environmental representations</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<p>By utilizing point clouds in VR, researchers and developers can create highly realistic and interactive virtual environments, revolutionizing fields such as architecture, gaming, virtual tourism, and more.</p>
|
||||||
|
|
||||||
|
<p>Understanding these concepts is essential for delving into advanced research topics in 3D visualization, computer vision, and virtual reality applications.</p>
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<button type="button" id="consent" disabled="true"></button>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
var timerElement = document.getElementById('consent');
|
||||||
|
var timeLeft = 10;
|
||||||
|
|
||||||
|
var countdown = setInterval(() => {
|
||||||
|
if (timeLeft <= 0) {
|
||||||
|
clearInterval(countdown);
|
||||||
|
timerElement.textContent = "Continue";
|
||||||
|
timerElement.disabled = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
timerElement.textContent = timeLeft;
|
||||||
|
timeLeft--;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
155
PCSurvey/PCstatic/html/instructions_P1.html
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Instructions</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
border: 2px solid black;
|
||||||
|
display: block;
|
||||||
|
margin: 20px auto;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
width: 20%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #bc0ba8;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 20px auto; /* Zentriert den Button */
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
button:disabled {
|
||||||
|
background: #ccc;
|
||||||
|
color: #666;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:disabled):hover {
|
||||||
|
background: #5d0570;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
background-color: #f9e6f8;
|
||||||
|
border-left: 4px solid #bc0ba8;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
.step {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.step-number {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #bc0ba8;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>Research Experiment: Point Cloud Quality Evaluation</h1>
|
||||||
|
|
||||||
|
<div class="highlight">
|
||||||
|
<p><strong>Key Focus:</strong> Evaluate the <strong>QUALITY</strong> of point clouds in virtual reality environments.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Experiment Structure</h2>
|
||||||
|
<p>You will participate in 4 blocks of evaluations. Each block consists of the following:</p>
|
||||||
|
<ol>
|
||||||
|
<li>Viewing and evaluating an initial point cloud</li>
|
||||||
|
<li>Viewing and evaluating a second point cloud</li>
|
||||||
|
<li>Rating the difference between the two point clouds</li>
|
||||||
|
</ol>
|
||||||
|
<h2>Your Task</h2>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">1.</span>
|
||||||
|
<span>You will be immersed in a point cloud environment.</span>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">2.</span>
|
||||||
|
<span>Explore the point cloud to familiarize yourself with it for later evaluation.</span>
|
||||||
|
</div>
|
||||||
|
<img width="640" height="360" src="PCstatic/img/pointcloud.png" alt="Point Cloud Image">
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">3.</span>
|
||||||
|
<span>As a control measure, there are <b>three letters/numbers</b> hidden in the cloud which you must identify. You will be asked about it later during the evaluation.</span>
|
||||||
|
</div>
|
||||||
|
<img width="640" height="360" src="PCstatic/img/letter_pointcloud.png" alt="Letter Point Cloud Image">
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">4.</span>
|
||||||
|
<span>Please rate the <b>quality</b> of the point cloud on a scale and enter the corresponding control <b>letters/numbers</b> that you observed.</span>
|
||||||
|
</div>
|
||||||
|
<img width="680" height="360" src="PCstatic/img/seq_1.png" alt="Rating Scale Image">
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">5.</span>
|
||||||
|
<span>You will then experience a second point cloud.</span>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">6.</span>
|
||||||
|
<span>Repeat steps 2 and 3 for the new cloud, then rate its <b>quality</b>, enter the control <b>letters/numbers</b> from the cloud, and <b>assess the difference in quality</b> compared to the previous one.</span>
|
||||||
|
</div>
|
||||||
|
<img width="640" height="360" src="PCstatic/img/seq_2.png" alt="Different Compression Settings Image">
|
||||||
|
|
||||||
|
<div class="highlight">
|
||||||
|
<p><strong>Important:</strong> While finding the hidden letters/numbers is part of the mechanism to validate the interaction, the primary focus is on evaluating the overall quality of the point cloud.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p>This sequence of two point clouds and their evaluations will be repeated 4 times (4 blocks).</p>
|
||||||
|
<p>After completing all blocks, you will have the opportunity to provide feedback, which we greatly appreciate for further improvement of our research.</p>
|
||||||
|
<p>To help you familiarize yourself with the survey, you will complete a trial run beforehand.</p>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<button type="button" id="consent" disabled="true"></button>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
var timerElement = document.getElementById('consent');
|
||||||
|
var timeLeft = 10;
|
||||||
|
|
||||||
|
var countdown = setInterval(() => {
|
||||||
|
if (timeLeft <= 0) {
|
||||||
|
clearInterval(countdown);
|
||||||
|
timerElement.textContent = "I Agree";
|
||||||
|
timerElement.disabled = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
timerElement.textContent = timeLeft;
|
||||||
|
timeLeft--;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
151
PCSurvey/PCstatic/html/instructions_P1_no_ emphasis_quality.html
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Instructions</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
border: 2px solid black;
|
||||||
|
display: block;
|
||||||
|
margin: 20px auto;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
width: 20%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #bc0ba8;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 20px auto; /* Zentriert den Button */
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
button:disabled {
|
||||||
|
background: #ccc;
|
||||||
|
color: #666;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:disabled):hover {
|
||||||
|
background: #5d0570;
|
||||||
|
}
|
||||||
|
|
||||||
|
.highlight {
|
||||||
|
background-color: #f9e6f8;
|
||||||
|
border-left: 4px solid #bc0ba8;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 15px 0;
|
||||||
|
}
|
||||||
|
.step {
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border: 1px solid #e0e0e0;
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
|
||||||
|
}
|
||||||
|
.step-number {
|
||||||
|
font-weight: bold;
|
||||||
|
color: #bc0ba8;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
|
||||||
|
<section>
|
||||||
|
<h1>Research Experiment: Point Cloud Quality Evaluation</h1>
|
||||||
|
|
||||||
|
<div class="highlight">
|
||||||
|
<p><strong>Key Focus:</strong> Evaluate the <strong>QUALITY</strong> of point clouds in virtual reality environments.</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<h2>Experiment Structure</h2>
|
||||||
|
<p>You will participate in 4 blocks of evaluations. Each block consists of the following:</p>
|
||||||
|
<ol>
|
||||||
|
<li>Viewing and evaluating an initial point cloud</li>
|
||||||
|
<li>Viewing and evaluating a second point cloud</li>
|
||||||
|
<li>Rating the difference between the two point clouds</li>
|
||||||
|
</ol>
|
||||||
|
<h2>Your Task</h2>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">1.</span>
|
||||||
|
<span>You will be immersed in a point cloud environment.</span>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">2.</span>
|
||||||
|
<span>Explore the point cloud to familiarize yourself with it for later evaluation.</span>
|
||||||
|
</div>
|
||||||
|
<img width="640" height="360" src="PCstatic/img/pointcloud.png" alt="Point Cloud Image">
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">3.</span>
|
||||||
|
<span>As a control measure, there are <b>one letter/number</b> hidden in the cloud which you must identify. You will be asked about it later during the evaluation.</span>
|
||||||
|
</div>
|
||||||
|
<img width="640" height="360" src="PCstatic/img/letter_pointcloud.png" alt="Letter Point Cloud Image">
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">4.</span>
|
||||||
|
<span>Please rate the <b>quality</b> of the point cloud on a scale and enter the corresponding control <b>letter/number</b> that you observed.</span>
|
||||||
|
</div>
|
||||||
|
<img width="680" height="360" src="PCstatic/img/seq_1.png" alt="Rating Scale Image">
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">5.</span>
|
||||||
|
<span>You will then experience a second point cloud.</span>
|
||||||
|
</div>
|
||||||
|
<div class="step">
|
||||||
|
<span class="step-number">6.</span>
|
||||||
|
<span>Repeat steps 2 and 3 for the new cloud, then rate its <b>quality</b>, enter the control <b>letter/number</b> from the cloud, and <b>assess the difference in quality</b> compared to the previous one.</span>
|
||||||
|
</div>
|
||||||
|
<img width="640" height="360" src="PCstatic/img/seq_2.png" alt="Different Compression Settings Image">
|
||||||
|
|
||||||
|
<p>This sequence of two point clouds and their evaluations will be repeated 4 times (4 blocks).</p>
|
||||||
|
<p>After completing all blocks, you will have the opportunity to provide feedback, which we greatly appreciate for further improvement of our research.</p>
|
||||||
|
<p>To help you familiarize yourself with the survey, you will complete a trial run beforehand.</p>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<button type="button" id="consent" disabled="true"></button>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
var timerElement = document.getElementById('consent');
|
||||||
|
var timeLeft = 10;
|
||||||
|
|
||||||
|
var countdown = setInterval(() => {
|
||||||
|
if (timeLeft <= 0) {
|
||||||
|
clearInterval(countdown);
|
||||||
|
timerElement.textContent = "I Agree";
|
||||||
|
timerElement.disabled = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
timerElement.textContent = timeLeft;
|
||||||
|
timeLeft--;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
109
PCSurvey/PCstatic/html/instructions_P2.html
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Instructions</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 24px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
p, ul {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
ul li {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
border: 2px solid black;
|
||||||
|
display: block;
|
||||||
|
margin: 20px auto;
|
||||||
|
max-width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
width: auto;
|
||||||
|
padding: 10px 20px;
|
||||||
|
background: #bc0ba8;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 20px auto;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-bottom: 50px;
|
||||||
|
}
|
||||||
|
button:disabled {
|
||||||
|
background: #ccc;
|
||||||
|
color: #666;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:disabled):hover {
|
||||||
|
background: #5d0570;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<section>
|
||||||
|
<h1>Controls</h1>
|
||||||
|
<p>Hold the left mouse button and move the mouse to adjust your perspective.</p>
|
||||||
|
<img src="PCstatic/img/perspective.gif" width="640" height="640" alt="">
|
||||||
|
<p>Use the W, A, S, and D keys to change your position:</p>
|
||||||
|
<ul>
|
||||||
|
<li><b>W</b> - Move forward</li>
|
||||||
|
<li><b>S</b> - Move backward</li>
|
||||||
|
<li><b>D</b> - Move right</li>
|
||||||
|
<li><b>A</b> - Move left</li>
|
||||||
|
</ul>
|
||||||
|
<img src="PCstatic/img/position.gif" width="640" height="640" alt="">
|
||||||
|
<p>Combine mouse and keyboard controls to navigate through the cloud.</p>
|
||||||
|
<img src="PCstatic/img/movement.gif" width="640" height="640" alt="">
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
<button type="button" id="consent" disabled="true"></button>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
var timerElement = document.getElementById('consent');
|
||||||
|
var timeLeft = 3;
|
||||||
|
|
||||||
|
var countdown = setInterval(() => {
|
||||||
|
if (timeLeft <= 0) {
|
||||||
|
clearInterval(countdown);
|
||||||
|
timerElement.textContent = "Let's try!";
|
||||||
|
timerElement.disabled = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
timerElement.textContent = timeLeft;
|
||||||
|
timeLeft--;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
47
PCSurvey/PCstatic/html/instructions_V.html
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
||||||
|
<!-- <link rel="stylesheet" href="https://use.typekit.net/hpq3bof.css">
|
||||||
|
<link href="https://fonts.googleapis.com/css?family=Lancelot" rel="stylesheet"> -->
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="intro_text">
|
||||||
|
<header>
|
||||||
|
<h1>Test Instructions</h1>
|
||||||
|
</header>
|
||||||
|
<main>
|
||||||
|
<section>
|
||||||
|
<h2>Your Task</h2>
|
||||||
|
<p>You will first see a video in original quality:</p>
|
||||||
|
<div style="block">
|
||||||
|
<img id="Bsp1" style="width:420px;height:280px;margin:10px" src="PCstatic/img/Text/Text-OR-G-E.png" />
|
||||||
|
</div>
|
||||||
|
<p>After that, you see the same video in reduced quality:</p>
|
||||||
|
<div style="block">
|
||||||
|
<img id="Bsp2" style="width:420px;height:280px;margin:10px" src="PCstatic/img/Text/Text-OC-V8-G-H.png" />
|
||||||
|
</div>
|
||||||
|
<p>Your Task:</p>
|
||||||
|
<ul class="instructions">
|
||||||
|
<li>Rate the quality of the videos.</li>
|
||||||
|
<ul class="insturcuions">
|
||||||
|
<li><b>Good quality</b> is given if the surfaces of objects are smooth and easily recognisable.</li>
|
||||||
|
<li>A video of <b>bad quality</b> has less recognisable surfaces.</li>
|
||||||
|
</ul>
|
||||||
|
<li>Rate the difference in quality between the original video and the reduced video.</li>
|
||||||
|
<li>Even in the original video you might see areas that are not fully scanned (Areas are missing e.g. a roof). This should not influence your rating!</li>
|
||||||
|
<li>In addition at the end of each video there will be a red letter in the top right corner. Memorize it and tick/check the corresponding box below your rating.</li>
|
||||||
|
</ul>
|
||||||
|
<p></p>
|
||||||
|
<p>Further informations on the topic are at the end of the survey.</p>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</main>
|
||||||
|
</div>
|
||||||
|
<button type="jspsych-btn" id="consent">I agree to take part in this study.</button>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
<!-- Cache served by Simple Cache - Last modified: Thu, 05 Jul 2018 02:27:42 GMT -->
|
||||||
98
PCSurvey/PCstatic/html/welcome.html
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="ie=edge"/>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 20px;
|
||||||
|
background-color: #f4f4f4;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
section {
|
||||||
|
background: #fff;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
h2, h3 {
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
p, ul {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding-left: 20px;
|
||||||
|
}
|
||||||
|
ul li {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
button {
|
||||||
|
display: block;
|
||||||
|
width: 20%;
|
||||||
|
padding: 10px;
|
||||||
|
background: #bc0ba8;
|
||||||
|
color: #fff;
|
||||||
|
border: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-size: 16px;
|
||||||
|
margin-top: 20px;
|
||||||
|
}
|
||||||
|
button:disabled {
|
||||||
|
background: #ccc;
|
||||||
|
color: #666;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
button:not(:disabled):hover {
|
||||||
|
background: #5d0570;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<div>
|
||||||
|
<section>
|
||||||
|
<h3>Thank you for your participation in this Survey.</h3>
|
||||||
|
<p>Before starting the survey, please read the test instructions on the next page carefully.</p>
|
||||||
|
<br>
|
||||||
|
<h1>Important!</h1>
|
||||||
|
<b>Please follow the following rules to ensure your participation is rated as successful:</b>
|
||||||
|
<ul>
|
||||||
|
<li>Please do <b>NOT Switch</b> tabs or programs during the test.</li>
|
||||||
|
<li>Please do <b>NOT Zoom</b> in or out during the test.</li>
|
||||||
|
<li>Please do <b>NOT Reload</b> the page once you have begun the test.</li>
|
||||||
|
</ul>
|
||||||
|
</section>
|
||||||
|
<button type="jspsych-btn" id="consent" disabled="true"></button>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
var timerElement = document.getElementById('consent');
|
||||||
|
var timeLeft = 5;
|
||||||
|
|
||||||
|
var countdown = setInterval(() => {
|
||||||
|
if (timeLeft <= 0) {
|
||||||
|
clearInterval(countdown);
|
||||||
|
timerElement.textContent = "Continue";
|
||||||
|
timerElement.disabled = false;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
timerElement.textContent = timeLeft;
|
||||||
|
timeLeft--;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
|
</script>
|
||||||
|
</html>
|
||||||
BIN
PCSurvey/PCstatic/img/Octree.png
Normal file
|
After Width: | Height: | Size: 24 KiB |
BIN
PCSurvey/PCstatic/img/letter_pointcloud.png
Normal file
|
After Width: | Height: | Size: 900 KiB |
BIN
PCSurvey/PCstatic/img/movement.gif
Normal file
|
After Width: | Height: | Size: 48 MiB |
BIN
PCSurvey/PCstatic/img/perspective.gif
Normal file
|
After Width: | Height: | Size: 20 MiB |
BIN
PCSurvey/PCstatic/img/pointcloud.png
Normal file
|
After Width: | Height: | Size: 1000 KiB |
BIN
PCSurvey/PCstatic/img/pointcloud_example.png
Normal file
|
After Width: | Height: | Size: 3.4 MiB |
BIN
PCSurvey/PCstatic/img/position.gif
Normal file
|
After Width: | Height: | Size: 37 MiB |
BIN
PCSurvey/PCstatic/img/seq_1.png
Normal file
|
After Width: | Height: | Size: 8.6 KiB |
BIN
PCSurvey/PCstatic/img/seq_2.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
1
PCSurvey/PCstatic/js/external/json2.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
if(!this.JSON){this.JSON={}}(function(){function f(n){return n<10?"0"+n:n}if(typeof Date.prototype.toJSON!=="function"){Date.prototype.toJSON=function(key){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf()}}var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b","\t":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==="string"?c:"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+string+'"'}function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==="object"&&typeof value.toJSON==="function"){value=value.toJSON(key)}if(typeof rep==="function"){value=rep.call(holder,key,value)}switch(typeof value){case"string":return quote(value);case"number":return isFinite(value)?String(value):"null";case"boolean":case"null":return String(value);case"object":if(!value){return"null"}gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==="[object Array]"){length=value.length;for(i=0;i<length;i+=1){partial[i]=str(i,value)||"null"}v=partial.length===0?"[]":gap?"[\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"]":"["+partial.join(",")+"]";gap=mind;return v}if(rep&&typeof rep==="object"){length=rep.length;for(i=0;i<length;i+=1){k=rep[i];if(typeof k==="string"){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}else{for(k in value){if(Object.hasOwnProperty.call(value,k)){v=str(k,value);if(v){partial.push(quote(k)+(gap?": ":":")+v)}}}}v=partial.length===0?"{}":gap?"{\n"+gap+partial.join(",\n"+gap)+"\n"+mind+"}":"{"+partial.join(",")+"}";gap=mind;return v}}if(typeof JSON.stringify!=="function"){JSON.stringify=function(value,replacer,space){var i;gap="";indent="";if(typeof space==="number"){for(i=0;i<space;i+=1){indent+=" "}}else{if(typeof space==="string"){indent=space}}rep=replacer;if(replacer&&typeof replacer!=="function"&&(typeof replacer!=="object"||typeof replacer.length!=="number")){throw new Error("JSON.stringify")}return str("",{"":value})}}if(typeof JSON.parse!=="function"){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==="object"){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v}else{delete value[k]}}}}return reviver.call(holder,key,value)}cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return"\\u"+("0000"+a.charCodeAt(0).toString(16)).slice(-4)})}if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,""))){j=eval("("+text+")");return typeof reviver==="function"?walk({"":j},""):j}throw new SyntaxError("JSON.parse")}}}());
|
||||||
2721
PCSurvey/PCstatic/js/external/jspsych.js
vendored
Normal file
2
PCSurvey/PCstatic/js/external/jstat.min.js
vendored
Normal file
2
PCSurvey/PCstatic/js/external/load.min.js
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/*! evtrack -- Load module */
|
||||||
|
(function(){function a(m){var l=document.createElement("script");l.type="text/javascript";l.src=m;return l}var d=document.getElementsByTagName("script");var c=d[d.length-1];var j=c.src.split("/");j.splice(j.length-1,1);var k=j.join("/");var b=j[j.length-1]=="src"?".js":".min.js";function i(l,n){var m=a(k+"/"+l+b);c.parentNode.insertBefore(m,c);m.onload=function(){n()}}var h;window.TrackUI={record:function(l){h=function(){window.TrackUI.record(l)}}};var f=["json2","tracklib","trackui"];for(var g in f){i(f[g],e)}function e(){f.shift();if(f.length===0){c.parentNode.removeChild(c);if(typeof h==="function"){h()}}}})();
|
||||||
9
PCSurvey/PCstatic/js/external/sha256.min.js
vendored
Normal file
2
PCSurvey/PCstatic/js/external/tracklib.min.js
vendored
Normal file
223
PCSurvey/PCstatic/js/external/trackui.min.js
vendored
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/*! evtrack -- UI module */
|
||||||
|
(function(f) {
|
||||||
|
var g = f.document;
|
||||||
|
var c = "mousedown mouseup mousemove mouseover mouseout mousewheel ";
|
||||||
|
c += "touchstart touchend touchmove keydown keyup keypress ";
|
||||||
|
c += "click dblclick scroll change select submit reset contextmenu cut copy paste";
|
||||||
|
var d = "load unload beforeunload blur focus resize error online offline";
|
||||||
|
c = c.split(" ");
|
||||||
|
d = d.split(" ");
|
||||||
|
var a = c.concat(d);
|
||||||
|
var b = " "
|
||||||
|
, e = "|||";
|
||||||
|
var h = 0
|
||||||
|
, k = 0
|
||||||
|
, j = [];
|
||||||
|
var i = {
|
||||||
|
settings: {
|
||||||
|
postServer: "//my.server.org/save.script",
|
||||||
|
postInterval: 30,
|
||||||
|
regularEvents: "*",
|
||||||
|
pollingEvents: "",
|
||||||
|
pollingMs: 150,
|
||||||
|
taskName: "evtrack",
|
||||||
|
callback: null,
|
||||||
|
saveAttributes: true,
|
||||||
|
layoutType: "liquid",
|
||||||
|
debug: false
|
||||||
|
},
|
||||||
|
record: function(l) {
|
||||||
|
k = new Date().getTime();
|
||||||
|
for (var m in i.settings) {
|
||||||
|
if (l.hasOwnProperty(m) && l[m] !== null) {
|
||||||
|
i.settings[m] = l[m]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
i.log("Recording starts...", k, i.settings);
|
||||||
|
i.addEventListeners();
|
||||||
|
setTimeout(function() {
|
||||||
|
i.initNewData(true)
|
||||||
|
}, i.settings.postInterval * 1000)
|
||||||
|
},
|
||||||
|
addEventListeners: function() {
|
||||||
|
if (i.settings.regularEvents == "*") {
|
||||||
|
i.addCustomEventListeners(a)
|
||||||
|
} else {
|
||||||
|
i.log("Settings regular events...");
|
||||||
|
i.settings.regularEvents = i.settings.regularEvents.split(" ");
|
||||||
|
i.addCustomEventListeners(i.settings.regularEvents)
|
||||||
|
}
|
||||||
|
if (i.settings.pollingEvents == "*") {
|
||||||
|
i.addCustomEventListeners(a)
|
||||||
|
} else {
|
||||||
|
i.log("Settings polling events...");
|
||||||
|
i.settings.pollingEvents = i.settings.pollingEvents.split(" ");
|
||||||
|
i.addCustomEventListeners(i.settings.pollingEvents)
|
||||||
|
}
|
||||||
|
var l = (typeof f.onbeforeunload === "function") ? "beforeunload" : "unload";
|
||||||
|
TrackLib.Events.add(f, l, i.flush)
|
||||||
|
},
|
||||||
|
addCustomEventListeners: function(n) {
|
||||||
|
i.log("Adding event listeners:", n);
|
||||||
|
for (var l = 0; l < n.length; ++l) {
|
||||||
|
var m = n[l];
|
||||||
|
if (!m) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if (c.indexOf(m) > -1) {
|
||||||
|
TrackLib.Events.add(g, m, i.docHandler);
|
||||||
|
i.log("Adding document event:", m);
|
||||||
|
if (g.attachEvent) {
|
||||||
|
if (m == "focus") {
|
||||||
|
TrackLib.Events.add(g.body, "focusin", i.winHandler)
|
||||||
|
}
|
||||||
|
if (m == "blur") {
|
||||||
|
TrackLib.Events.add(g.body, "focusout", i.winHandler)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (d.indexOf(m) > -1) {
|
||||||
|
TrackLib.Events.add(f, m, i.winHandler);
|
||||||
|
i.log("Adding window event:", m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
initNewData: function(l) {
|
||||||
|
var o = TrackLib.Dimension.getWindowSize()
|
||||||
|
, n = TrackLib.Dimension.getDocumentSize()
|
||||||
|
, m = "url=" + encodeURIComponent(f.location.href);
|
||||||
|
m += "&screenw=" + screen.width;
|
||||||
|
m += "&screenh=" + screen.height;
|
||||||
|
m += "&winw=" + o.width;
|
||||||
|
m += "&winh=" + o.height;
|
||||||
|
m += "&docw=" + n.width;
|
||||||
|
m += "&doch=" + n.height;
|
||||||
|
m += "&info=" + encodeURIComponent(j.join(e));
|
||||||
|
m += "&task=" + encodeURIComponent(i.settings.taskName);
|
||||||
|
m += "&action=init";
|
||||||
|
i.send({
|
||||||
|
async: l,
|
||||||
|
postdata: m,
|
||||||
|
callback: i.setUserId
|
||||||
|
});
|
||||||
|
j = []
|
||||||
|
},
|
||||||
|
setUserId: function(l) {
|
||||||
|
h = parseInt(l.responseText);
|
||||||
|
i.log("setUserId:", h);
|
||||||
|
if (h) {
|
||||||
|
setInterval(function() {
|
||||||
|
i.appendData(true)
|
||||||
|
}, i.settings.postInterval * 1000)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
appendData: function(l) {
|
||||||
|
var m = "uid=" + h;
|
||||||
|
m += "&info=" + encodeURIComponent(j.join(e));
|
||||||
|
m += "&task=" + encodeURIComponent(i.settings.taskName);
|
||||||
|
m += "&action=append";
|
||||||
|
i.send({
|
||||||
|
async: l,
|
||||||
|
postdata: m
|
||||||
|
});
|
||||||
|
j = []
|
||||||
|
},
|
||||||
|
send: function(l) {
|
||||||
|
l.url = i.settings.postServer;
|
||||||
|
TrackLib.XHR.sendAjaxRequest(l)
|
||||||
|
},
|
||||||
|
docHandler: function(l) {
|
||||||
|
if (l.type.indexOf("touch") > -1) {
|
||||||
|
i.touchHandler(l)
|
||||||
|
} else {
|
||||||
|
i.eventHandler(l)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
winHandler: function(l) {
|
||||||
|
i.eventHandler(l)
|
||||||
|
},
|
||||||
|
eventHandler: function(q) {
|
||||||
|
q = TrackLib.Events.fix(q);
|
||||||
|
var n = new Date().getTime()
|
||||||
|
, m = q.type
|
||||||
|
, o = true;
|
||||||
|
if (i.settings.pollingMs > 0 && i.settings.pollingEvents.indexOf(m) > -1) {
|
||||||
|
o = (n - k >= i.settings.pollingMs)
|
||||||
|
}
|
||||||
|
if (o) {
|
||||||
|
var s = i.getMousePos(q)
|
||||||
|
, r = TrackLib.XPath.getXPath(q.target)
|
||||||
|
, l = i.settings.saveAttributes ? TrackLib.Util.serializeAttrs(q.target) : "{}"
|
||||||
|
, p = {};
|
||||||
|
if (typeof i.settings.callback === "function") {
|
||||||
|
p = i.settings.callback(q)
|
||||||
|
}
|
||||||
|
i.fillInfo(q.id, n, s.x, s.y, m, r, l, JSON.stringify(p));
|
||||||
|
k = n
|
||||||
|
}
|
||||||
|
},
|
||||||
|
touchHandler: function(n) {
|
||||||
|
n = TrackLib.Events.fix(n);
|
||||||
|
var m = n.changedTouches;
|
||||||
|
if (m) {
|
||||||
|
for (var l = 0, o; l < m.length; ++l) {
|
||||||
|
o = m[l];
|
||||||
|
o.type = n.type;
|
||||||
|
i.eventHandler(o)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
getMousePos: function(m) {
|
||||||
|
m = TrackLib.Events.fix(m);
|
||||||
|
var l = 0
|
||||||
|
, n = 0;
|
||||||
|
if (m.pageX || m.pageY) {
|
||||||
|
l = m.pageX;
|
||||||
|
n = m.pageY
|
||||||
|
} else {
|
||||||
|
if (m.clientX || m.clientY) {
|
||||||
|
l = m.clientX + g.body.scrollLeft + g.documentElement.scrollLeft;
|
||||||
|
n = m.clientY + g.body.scrollTop + g.documentElement.scrollTop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!l || l < 0) {
|
||||||
|
l = 0
|
||||||
|
}
|
||||||
|
if (!n || n < 0) {
|
||||||
|
n = 0
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
x: l,
|
||||||
|
y: n
|
||||||
|
}
|
||||||
|
},
|
||||||
|
fillInfo: function() {
|
||||||
|
var l = [].slice.apply(arguments);
|
||||||
|
j.push(l.join(b));
|
||||||
|
i.log(l)
|
||||||
|
},
|
||||||
|
flush: function(m) {
|
||||||
|
i.log("Flushing data...", h);
|
||||||
|
var l;
|
||||||
|
for (l = 0; l < c.length; ++l) {
|
||||||
|
TrackLib.Events.remove(g, c[l], i.docHandler)
|
||||||
|
}
|
||||||
|
for (l = 0; l < d.length; ++l) {
|
||||||
|
TrackLib.Events.remove(f, d[l], i.winHandler)
|
||||||
|
}
|
||||||
|
if (h) {
|
||||||
|
i.appendData(false)
|
||||||
|
} else {
|
||||||
|
i.initNewData(false)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
log: function() {
|
||||||
|
if (i.settings.debug && typeof console.log === "function") {
|
||||||
|
console.log.apply(console, arguments)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
f.TrackUI = i
|
||||||
|
}
|
||||||
|
)(this);
|
||||||
2
PCSurvey/PCstatic/js/jquery.js
vendored
Normal file
2724
PCSurvey/PCstatic/js/jspsych.js
Normal file
2
PCSurvey/PCstatic/js/jstat.min.js
vendored
Normal file
39
PCSurvey/PCstatic/js/pik.js
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
// ******
|
||||||
|
// Please define your load animation in the configuration variable.
|
||||||
|
// Note that each page needs to have a (hidden) button called #end-trial that will
|
||||||
|
// be used to close the trial and move on to the user rating task
|
||||||
|
// ******
|
||||||
|
|
||||||
|
//$('#b1').on('click', function() {
|
||||||
|
// $('#launch').addClass('display_toggle');
|
||||||
|
//
|
||||||
|
// if (jsPsych.data.getURLVariable('debug') === 'true') {
|
||||||
|
// $('.debug').css({'display': 'block'});
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
var reloads = 0;
|
||||||
|
|
||||||
|
document.getElementById("end-trial").style.display = "none"
|
||||||
|
|
||||||
|
document.getElementById("timer").innerHTML = picDuration;
|
||||||
|
|
||||||
|
var distance = picDuration - 1;
|
||||||
|
|
||||||
|
var x = setInterval(function() {
|
||||||
|
|
||||||
|
// Time calculations for days, hours, minutes and seconds
|
||||||
|
var seconds = distance;
|
||||||
|
distance--;
|
||||||
|
|
||||||
|
// If the count down is finished, write some text
|
||||||
|
if (seconds <= 0) {
|
||||||
|
document.getElementById("timer").innerHTML = "";
|
||||||
|
document.getElementById("end-trial").style.display = ""
|
||||||
|
clearInterval(x);
|
||||||
|
} else {
|
||||||
|
// Display the result in the element with id="demo"
|
||||||
|
document.getElementById("timer").innerHTML = seconds;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
46
PCSurvey/PCstatic/js/pik_V.js
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
// ******
|
||||||
|
// Please define your load animation in the configuration variable.
|
||||||
|
// Note that each page needs to have a (hidden) button called #end-trial that will
|
||||||
|
// be used to close the trial and move on to the user rating task
|
||||||
|
// ******
|
||||||
|
|
||||||
|
//$('#b1').on('click', function() {
|
||||||
|
// $('#launch').addClass('display_toggle');
|
||||||
|
//
|
||||||
|
// if (jsPsych.data.getURLVariable('debug') === 'true') {
|
||||||
|
// $('.debug').css({'display': 'block'});
|
||||||
|
// }
|
||||||
|
//});
|
||||||
|
|
||||||
|
var reloads = 0;
|
||||||
|
|
||||||
|
function replayVideo(){
|
||||||
|
document.getElementById("vid").load();
|
||||||
|
reloads = reloads + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById("end-trial").style.display = "none"
|
||||||
|
document.getElementById("replay").style.display = "none"
|
||||||
|
|
||||||
|
document.getElementById("timer").innerHTML = picDuration;
|
||||||
|
|
||||||
|
var distance = picDuration - 1;
|
||||||
|
|
||||||
|
var x = setInterval(function() {
|
||||||
|
|
||||||
|
// Time calculations for days, hours, minutes and seconds
|
||||||
|
var seconds = distance;
|
||||||
|
distance--;
|
||||||
|
|
||||||
|
// If the count down is finished, write some text
|
||||||
|
if (seconds <= 0) {
|
||||||
|
document.getElementById("timer").innerHTML = "";
|
||||||
|
document.getElementById("end-trial").style.display = ""
|
||||||
|
document.getElementById("replay").style.display = ""
|
||||||
|
clearInterval(x);
|
||||||
|
} else {
|
||||||
|
// Display the result in the element with id="demo"
|
||||||
|
document.getElementById("timer").innerHTML = seconds;
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
154
PCSurvey/PCstatic/js/plugins/jspsych-animation.js
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
/**
|
||||||
|
* jsPsych plugin for showing animations and recording keyboard responses
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins.animation = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('animation', 'stimuli', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'animation',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimuli: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Stimuli',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'The images to be displayed.'
|
||||||
|
},
|
||||||
|
frame_time: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Frame time',
|
||||||
|
default: 250,
|
||||||
|
description: 'Duration to display each image.'
|
||||||
|
},
|
||||||
|
frame_isi: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Frame gap',
|
||||||
|
default: 0,
|
||||||
|
description: 'Length of gap to be shown between each image.'
|
||||||
|
},
|
||||||
|
sequence_reps: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Sequence repetitions',
|
||||||
|
default: 1,
|
||||||
|
description: 'Number of times to show entire sequence.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
array: true,
|
||||||
|
description: 'Keys subject uses to respond to stimuli.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below stimulus.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var interval_time = trial.frame_time + trial.frame_isi;
|
||||||
|
var animate_frame = -1;
|
||||||
|
var reps = 0;
|
||||||
|
var startTime = performance.now();
|
||||||
|
var animation_sequence = [];
|
||||||
|
var responses = [];
|
||||||
|
var current_stim = "";
|
||||||
|
|
||||||
|
var animate_interval = setInterval(function() {
|
||||||
|
var showImage = true;
|
||||||
|
display_element.innerHTML = ''; // clear everything
|
||||||
|
animate_frame++;
|
||||||
|
if (animate_frame == trial.stimuli.length) {
|
||||||
|
animate_frame = 0;
|
||||||
|
reps++;
|
||||||
|
if (reps >= trial.sequence_reps) {
|
||||||
|
endTrial();
|
||||||
|
clearInterval(animate_interval);
|
||||||
|
showImage = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (showImage) {
|
||||||
|
show_next_frame();
|
||||||
|
}
|
||||||
|
}, interval_time);
|
||||||
|
|
||||||
|
function show_next_frame() {
|
||||||
|
// show image
|
||||||
|
display_element.innerHTML = '<img src="'+trial.stimuli[animate_frame]+'" id="jspsych-animation-image"></img>';
|
||||||
|
|
||||||
|
current_stim = trial.stimuli[animate_frame];
|
||||||
|
|
||||||
|
// record when image was shown
|
||||||
|
animation_sequence.push({
|
||||||
|
"stimulus": trial.stimuli[animate_frame],
|
||||||
|
"time": performance.now() - startTime
|
||||||
|
});
|
||||||
|
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
display_element.innerHTML += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.frame_isi > 0) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-animation-image').style.visibility = 'hidden';
|
||||||
|
current_stim = 'blank';
|
||||||
|
// record when blank image was shown
|
||||||
|
animation_sequence.push({
|
||||||
|
"stimulus": 'blank',
|
||||||
|
"time": performance.now() - startTime
|
||||||
|
});
|
||||||
|
}, trial.frame_time);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
responses.push({
|
||||||
|
key_press: info.key,
|
||||||
|
rt: info.rt,
|
||||||
|
stimulus: current_stim
|
||||||
|
});
|
||||||
|
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-animation-image').className += ' responded';
|
||||||
|
}
|
||||||
|
|
||||||
|
// hold the jspsych response listener object in memory
|
||||||
|
// so that we can turn off the response collection when
|
||||||
|
// the trial ends
|
||||||
|
var response_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: true,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(response_listener);
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
"animation_sequence": JSON.stringify(animation_sequence),
|
||||||
|
"responses": JSON.stringify(responses)
|
||||||
|
};
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
216
PCSurvey/PCstatic/js/plugins/jspsych-audio-button-response.js
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-audio-button-response
|
||||||
|
* Kristin Diep
|
||||||
|
*
|
||||||
|
* plugin for playing an audio file and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["audio-button-response"] = (function() {
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('audio-button-response', 'stimulus', 'audio');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'audio-button-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.AUDIO,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The audio to be played.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'The button labels.'
|
||||||
|
},
|
||||||
|
button_html: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Button HTML',
|
||||||
|
default: '<button class="jspsych-btn">%choice%</button>',
|
||||||
|
array: true,
|
||||||
|
description: 'Custom button. Can make your own style.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'The maximum duration to wait for a response.'
|
||||||
|
},
|
||||||
|
margin_vertical: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Margin vertical',
|
||||||
|
default: '0px',
|
||||||
|
description: 'Vertical margin of button.'
|
||||||
|
},
|
||||||
|
margin_horizontal: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Margin horizontal',
|
||||||
|
default: '8px',
|
||||||
|
description: 'Horizontal margin of button.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the trial will end when user makes a response.'
|
||||||
|
},
|
||||||
|
trial_ends_after_audio: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Trial ends after audio',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, then the trial will end as soon as the audio file finishes playing.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// setup stimulus
|
||||||
|
var context = jsPsych.pluginAPI.audioContext();
|
||||||
|
if(context !== null){
|
||||||
|
var source = context.createBufferSource();
|
||||||
|
source.buffer = jsPsych.pluginAPI.getAudioBuffer(trial.stimulus);
|
||||||
|
source.connect(context.destination);
|
||||||
|
} else {
|
||||||
|
var audio = jsPsych.pluginAPI.getAudioBuffer(trial.stimulus);
|
||||||
|
audio.currentTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up end event if trial needs it
|
||||||
|
if(trial.trial_ends_after_audio){
|
||||||
|
if(context !== null){
|
||||||
|
source.onended = function() {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
audio.addEventListener('ended', end_trial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//display buttons
|
||||||
|
var buttons = [];
|
||||||
|
if (Array.isArray(trial.button_html)) {
|
||||||
|
if (trial.button_html.length == trial.choices.length) {
|
||||||
|
buttons = trial.button_html;
|
||||||
|
} else {
|
||||||
|
console.error('Error in image-button-response plugin. The length of the button_html array does not equal the length of the choices array');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
buttons.push(trial.button_html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = '<div id="jspsych-audio-button-response-btngroup">';
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
var str = buttons[i].replace(/%choice%/g, trial.choices[i]);
|
||||||
|
html += '<div class="jspsych-audio-button-response-button" style="cursor: pointer; display: inline-block; margin:'+trial.margin_vertical+' '+trial.margin_horizontal+'" id="jspsych-audio-button-response-button-' + i +'" data-choice="'+i+'">'+str+'</div>';
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
//show prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
display_element.querySelector('#jspsych-audio-button-response-button-' + i).addEventListener('click', function(e){
|
||||||
|
var choice = e.currentTarget.getAttribute('data-choice'); // don't use dataset for jsdom compatibility
|
||||||
|
after_response(choice);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
button: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
function after_response(choice) {
|
||||||
|
|
||||||
|
// measure rt
|
||||||
|
var end_time = performance.now();
|
||||||
|
var rt = end_time - start_time;
|
||||||
|
response.button = choice;
|
||||||
|
response.rt = rt;
|
||||||
|
|
||||||
|
// disable all the buttons after a response
|
||||||
|
var btns = document.querySelectorAll('.jspsych-audio-button-response-button button');
|
||||||
|
for(var i=0; i<btns.length; i++){
|
||||||
|
//btns[i].removeEventListener('click');
|
||||||
|
btns[i].setAttribute('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
function end_trial() {
|
||||||
|
|
||||||
|
// stop the audio file if it is playing
|
||||||
|
// remove end event listeners if they exist
|
||||||
|
if(context !== null){
|
||||||
|
source.stop();
|
||||||
|
source.onended = function() { }
|
||||||
|
} else {
|
||||||
|
audio.pause();
|
||||||
|
audio.removeEventListener('ended', end_trial);
|
||||||
|
}
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"button_pressed": response.button
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// start time
|
||||||
|
var start_time = performance.now();
|
||||||
|
|
||||||
|
// start audio
|
||||||
|
if(context !== null){
|
||||||
|
startTime = context.currentTime;
|
||||||
|
source.start(startTime);
|
||||||
|
} else {
|
||||||
|
audio.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
185
PCSurvey/PCstatic/js/plugins/jspsych-audio-keyboard-response.js
Normal file
@@ -0,0 +1,185 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-audio-keyboard-response
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for playing an audio file and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["audio-keyboard-response"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('audio-keyboard-response', 'stimulus', 'audio');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'audio-keyboard-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.AUDIO,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The audio to be played.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
array: true,
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
description: 'The keys the subject is allowed to press to respond to the stimulus.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'The maximum duration to wait for a response.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the trial will end when user makes a response.'
|
||||||
|
},
|
||||||
|
trial_ends_after_audio: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Trial ends after audio',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, then the trial will end as soon as the audio file finishes playing.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// setup stimulus
|
||||||
|
var context = jsPsych.pluginAPI.audioContext();
|
||||||
|
if(context !== null){
|
||||||
|
var source = context.createBufferSource();
|
||||||
|
source.buffer = jsPsych.pluginAPI.getAudioBuffer(trial.stimulus);
|
||||||
|
source.connect(context.destination);
|
||||||
|
} else {
|
||||||
|
var audio = jsPsych.pluginAPI.getAudioBuffer(trial.stimulus);
|
||||||
|
audio.currentTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up end event if trial needs it
|
||||||
|
|
||||||
|
if(trial.trial_ends_after_audio){
|
||||||
|
if(context !== null){
|
||||||
|
source.onended = function() {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
audio.addEventListener('ended', end_trial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// show prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
display_element.innerHTML = trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
key: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
function end_trial() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// stop the audio file if it is playing
|
||||||
|
// remove end event listeners if they exist
|
||||||
|
if(context !== null){
|
||||||
|
source.stop();
|
||||||
|
source.onended = function() { }
|
||||||
|
} else {
|
||||||
|
audio.pause();
|
||||||
|
audio.removeEventListener('ended', end_trial);
|
||||||
|
}
|
||||||
|
|
||||||
|
// kill keyboard listeners
|
||||||
|
jsPsych.pluginAPI.cancelAllKeyboardResponses();
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
if(context !== null && response.rt !== null){
|
||||||
|
response.rt = Math.round(response.rt * 1000);
|
||||||
|
}
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"key_press": response.key
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// only record the first response
|
||||||
|
if (response.key == null) {
|
||||||
|
response = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// start audio
|
||||||
|
if(context !== null){
|
||||||
|
startTime = context.currentTime;
|
||||||
|
source.start(startTime);
|
||||||
|
} else {
|
||||||
|
audio.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
// start the response listener
|
||||||
|
if(context !== null) {
|
||||||
|
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'audio',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false,
|
||||||
|
audio_context: context,
|
||||||
|
audio_context_start_time: startTime
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
214
PCSurvey/PCstatic/js/plugins/jspsych-audio-slider-response.js
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
jsPsych.plugins['audio-slider-response'] = (function() {
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('audio-slider-response', 'stimulus', 'audio');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'audio-slider-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.AUDIO,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The image to be displayed'
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Min slider',
|
||||||
|
default: 0,
|
||||||
|
description: 'Sets the minimum value of the slider.'
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Max slider',
|
||||||
|
default: 100,
|
||||||
|
description: 'Sets the maximum value of the slider',
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Slider starting value',
|
||||||
|
default: 50,
|
||||||
|
description: 'Sets the starting value of the slider',
|
||||||
|
},
|
||||||
|
step: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Step',
|
||||||
|
default: 1,
|
||||||
|
description: 'Sets the step of the slider'
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name:'Labels',
|
||||||
|
default: [],
|
||||||
|
array: true,
|
||||||
|
description: 'Labels of the slider.',
|
||||||
|
},
|
||||||
|
slider_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name:'Slider width',
|
||||||
|
default: null,
|
||||||
|
description: 'Width of the slider in pixels.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
array: false,
|
||||||
|
description: 'Label of the button to advance.'
|
||||||
|
},
|
||||||
|
require_movement: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Require movement',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the participant will have to move the slider before continuing.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the slider.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, trial will end when user makes a response.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// setup stimulus
|
||||||
|
var context = jsPsych.pluginAPI.audioContext();
|
||||||
|
if(context !== null){
|
||||||
|
var source = context.createBufferSource();
|
||||||
|
source.buffer = jsPsych.pluginAPI.getAudioBuffer(trial.stimulus);
|
||||||
|
source.connect(context.destination);
|
||||||
|
} else {
|
||||||
|
var audio = jsPsych.pluginAPI.getAudioBuffer(trial.stimulus);
|
||||||
|
audio.currentTime = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up end event if trial needs it
|
||||||
|
if(trial.trial_ends_after_audio){
|
||||||
|
if(context !== null){
|
||||||
|
source.onended = function() {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
audio.addEventListener('ended', end_trial);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = '<div id="jspsych-audio-slider-response-wrapper" style="margin: 100px 0px;">';
|
||||||
|
html += '<div class="jspsych-audio-slider-response-container" style="position:relative; margin: 0 auto 3em auto; ';
|
||||||
|
if(trial.slider_width !== null){
|
||||||
|
html += 'width:'+trial.slider_width+'px;';
|
||||||
|
}
|
||||||
|
html += '">';
|
||||||
|
html += '<input type="range" value="'+trial.start+'" min="'+trial.min+'" max="'+trial.max+'" step="'+trial.step+'" style="width: 100%;" id="jspsych-audio-slider-response-response"></input>';
|
||||||
|
html += '<div>'
|
||||||
|
for(var j=0; j < trial.labels.length; j++){
|
||||||
|
var width = 100/(trial.labels.length-1);
|
||||||
|
var left_offset = (j * (100 /(trial.labels.length - 1))) - (width/2);
|
||||||
|
html += '<div style="display: inline-block; position: absolute; left:'+left_offset+'%; text-align: center; width: '+width+'%;">';
|
||||||
|
html += '<span style="text-align: center; font-size: 80%;">'+trial.labels[j]+'</span>';
|
||||||
|
html += '</div>'
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
if (trial.prompt !== null){
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
html += '<button id="jspsych-audio-slider-response-next" class="jspsych-btn" '+ (trial.require_movement ? "disabled" : "") + '>'+trial.button_label+'</button>';
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
response: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if(trial.require_movement){
|
||||||
|
display_element.querySelector('#jspsych-audio-slider-response-response').addEventListener('change', function(){
|
||||||
|
display_element.querySelector('#jspsych-audio-slider-response-next').disabled = false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-audio-slider-response-next').addEventListener('click', function() {
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
var rt = endTime - startTime;
|
||||||
|
if(context !== null){
|
||||||
|
endTime = context.currentTime;
|
||||||
|
rt = Math.round((endTime - startTime) * 1000);
|
||||||
|
}
|
||||||
|
response.rt = rt;
|
||||||
|
response.response = display_element.querySelector('#jspsych-audio-slider-response-response').value;
|
||||||
|
|
||||||
|
if(trial.response_ends_trial){
|
||||||
|
end_trial();
|
||||||
|
} else {
|
||||||
|
display_element.querySelector('#jspsych-audio-slider-response-next').disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function end_trial(){
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
if(context !== null){
|
||||||
|
source.stop();
|
||||||
|
source.onended = function() { }
|
||||||
|
} else {
|
||||||
|
audio.pause();
|
||||||
|
audio.removeEventListener('ended', end_trial);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save data
|
||||||
|
var trialdata = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"response": response.response
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trialdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
// start audio
|
||||||
|
if(context !== null){
|
||||||
|
startTime = context.currentTime;
|
||||||
|
source.start(startTime);
|
||||||
|
} else {
|
||||||
|
audio.play();
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if trial_duration is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
58
PCSurvey/PCstatic/js/plugins/jspsych-call-function.js
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-call-function
|
||||||
|
* plugin for calling an arbitrary function during a jspsych experiment
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins['call-function'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'call-function',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
func: {
|
||||||
|
type: jsPsych.plugins.parameterType.FUNCTION,
|
||||||
|
pretty_name: 'Function',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Function to call'
|
||||||
|
},
|
||||||
|
async: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Asynchronous',
|
||||||
|
default: false,
|
||||||
|
description: 'Is the function call asynchronous?'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
trial.post_trial_gap = 0;
|
||||||
|
var return_val;
|
||||||
|
|
||||||
|
if(trial.async){
|
||||||
|
var done = function(data){
|
||||||
|
return_val = data;
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
trial.func(done);
|
||||||
|
} else {
|
||||||
|
return_val = trial.func();
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
|
||||||
|
function end_trial(){
|
||||||
|
var trial_data = {
|
||||||
|
value: return_val
|
||||||
|
};
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
200
PCSurvey/PCstatic/js/plugins/jspsych-categorize-animation.js
Normal file
@@ -0,0 +1,200 @@
|
|||||||
|
/**
|
||||||
|
* jspsych plugin for categorization trials with feedback and animated stimuli
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins["categorize-animation"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('categorize-animation', 'stimuli', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'categorize-animation',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimuli: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimuli',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Array of paths to image files.'
|
||||||
|
},
|
||||||
|
key_answer: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key answer',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The key to indicate correct response'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
array: true,
|
||||||
|
description: 'The keys subject is allowed to press to respond to stimuli.'
|
||||||
|
},
|
||||||
|
text_answer: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Text answer',
|
||||||
|
default: null,
|
||||||
|
description: 'Text to describe correct answer.'
|
||||||
|
},
|
||||||
|
correct_text: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Correct text',
|
||||||
|
default: 'Correct.',
|
||||||
|
description: 'String to show when subject gives correct answer'
|
||||||
|
},
|
||||||
|
incorrect_text: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Incorrect text',
|
||||||
|
default: 'Wrong.',
|
||||||
|
description: 'String to show when subject gives incorrect answer.'
|
||||||
|
},
|
||||||
|
frame_time: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Frame time',
|
||||||
|
default: 500,
|
||||||
|
description: 'Duration to display each image.'
|
||||||
|
},
|
||||||
|
sequence_reps: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Sequence repetitions',
|
||||||
|
default: 1,
|
||||||
|
description: 'How many times to display entire sequence.'
|
||||||
|
},
|
||||||
|
allow_response_before_complete: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Allow response before complete',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, subject can response before the animation sequence finishes'
|
||||||
|
},
|
||||||
|
feedback_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Feedback duration',
|
||||||
|
default: 2000,
|
||||||
|
description: 'How long to show feedback'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var animate_frame = -1;
|
||||||
|
var reps = 0;
|
||||||
|
|
||||||
|
var showAnimation = true;
|
||||||
|
|
||||||
|
var responded = false;
|
||||||
|
var timeoutSet = false;
|
||||||
|
var correct;
|
||||||
|
|
||||||
|
// show animation
|
||||||
|
var animate_interval = setInterval(function() {
|
||||||
|
display_element.innerHTML = ''; // clear everything
|
||||||
|
animate_frame++;
|
||||||
|
if (animate_frame == trial.stimuli.length) {
|
||||||
|
animate_frame = 0;
|
||||||
|
reps++;
|
||||||
|
// check if reps complete //
|
||||||
|
if (trial.sequence_reps != -1 && reps >= trial.sequence_reps) {
|
||||||
|
// done with animation
|
||||||
|
showAnimation = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (showAnimation) {
|
||||||
|
display_element.innerHTML += '<img src="'+trial.stimuli[animate_frame]+'" class="jspsych-categorize-animation-stimulus"></img>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!responded && trial.allow_response_before_complete) {
|
||||||
|
// in here if the user can respond before the animation is done
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
display_element.innerHTML += trial.prompt;
|
||||||
|
}
|
||||||
|
} else if (!responded) {
|
||||||
|
// in here if the user has to wait to respond until animation is done.
|
||||||
|
// if this is the case, don't show the prompt until the animation is over.
|
||||||
|
if (!showAnimation) {
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
display_element.innerHTML += trial.prompt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// user has responded if we get here.
|
||||||
|
|
||||||
|
// show feedback
|
||||||
|
var feedback_text = "";
|
||||||
|
if (correct) {
|
||||||
|
feedback_text = trial.correct_text.replace("%ANS%", trial.text_answer);
|
||||||
|
} else {
|
||||||
|
feedback_text = trial.incorrect_text.replace("%ANS%", trial.text_answer);
|
||||||
|
}
|
||||||
|
display_element.innerHTML += feedback_text;
|
||||||
|
|
||||||
|
// set timeout to clear feedback
|
||||||
|
if (!timeoutSet) {
|
||||||
|
timeoutSet = true;
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
endTrial();
|
||||||
|
}, trial.feedback_duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}, trial.frame_time);
|
||||||
|
|
||||||
|
|
||||||
|
var keyboard_listener;
|
||||||
|
var trial_data = {};
|
||||||
|
|
||||||
|
var after_response = function(info) {
|
||||||
|
// ignore the response if animation is playing and subject
|
||||||
|
// not allowed to respond before it is complete
|
||||||
|
if (!trial.allow_response_before_complete && showAnimation) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
correct = false;
|
||||||
|
if (trial.key_answer == info.key) {
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
responded = true;
|
||||||
|
|
||||||
|
trial_data = {
|
||||||
|
"stimulus": JSON.stringify(trial.stimuli),
|
||||||
|
"rt": info.rt,
|
||||||
|
"correct": correct,
|
||||||
|
"key_press": info.key
|
||||||
|
};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(keyboard_listener);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: true,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
clearInterval(animate_interval); // stop animation!
|
||||||
|
display_element.innerHTML = ''; // clear everything
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
220
PCSurvey/PCstatic/js/plugins/jspsych-categorize-html.js
Normal file
@@ -0,0 +1,220 @@
|
|||||||
|
/**
|
||||||
|
* jspsych plugin for categorization trials with feedback
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['categorize-html'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'categorize-html',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The HTML content to be displayed.'
|
||||||
|
},
|
||||||
|
key_answer: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key answer',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The key to indicate the correct response.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
array: true,
|
||||||
|
description: 'The keys the subject is allowed to press to respond to the stimulus.'
|
||||||
|
},
|
||||||
|
text_answer: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Text answer',
|
||||||
|
default: null,
|
||||||
|
description: 'Label that is associated with the correct answer.'
|
||||||
|
},
|
||||||
|
correct_text: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Correct text',
|
||||||
|
default: "<p class='feedback'>Correct</p>",
|
||||||
|
description: 'String to show when correct answer is given.'
|
||||||
|
},
|
||||||
|
incorrect_text: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Incorrect text',
|
||||||
|
default: "<p class='feedback'>Incorrect</p>",
|
||||||
|
description: 'String to show when incorrect answer is given.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
force_correct_button_press: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Force correct button press',
|
||||||
|
default: false,
|
||||||
|
description: 'If set to true, then the subject must press the correct response key after feedback in order to advance to next trial.'
|
||||||
|
},
|
||||||
|
show_stim_with_feedback: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
default: true,
|
||||||
|
no_function: false,
|
||||||
|
description: ''
|
||||||
|
},
|
||||||
|
show_feedback_on_timeout: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Show feedback on timeout',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, stimulus will be shown during feedback. If false, only the text feedback will be displayed during feedback.'
|
||||||
|
},
|
||||||
|
timeout_message: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Timeout message',
|
||||||
|
default: "<p>Please respond faster.</p>",
|
||||||
|
description: 'The message displayed on a timeout non-response.'
|
||||||
|
},
|
||||||
|
stimulus_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to hide stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show trial'
|
||||||
|
},
|
||||||
|
feedback_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Feedback duration',
|
||||||
|
default: 2000,
|
||||||
|
description: 'How long to show feedback.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
display_element.innerHTML = '<div id="jspsych-categorize-html-stimulus" class="jspsych-categorize-html-stimulus">'+trial.stimulus+'</div>';
|
||||||
|
|
||||||
|
// hide image after time if the timing parameter is set
|
||||||
|
if (trial.stimulus_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-categorize-html-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.stimulus_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if prompt is set, show prompt
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
display_element.innerHTML += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trial_data = {};
|
||||||
|
|
||||||
|
// create response function
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// clear keyboard listener
|
||||||
|
jsPsych.pluginAPI.cancelAllKeyboardResponses();
|
||||||
|
|
||||||
|
var correct = false;
|
||||||
|
if (trial.key_answer == info.key) {
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save data
|
||||||
|
trial_data = {
|
||||||
|
"rt": info.rt,
|
||||||
|
"correct": correct,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"key_press": info.key
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
var timeout = info.rt == null;
|
||||||
|
doFeedback(correct, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
after_response({
|
||||||
|
key: null,
|
||||||
|
rt: null
|
||||||
|
});
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doFeedback(correct, timeout) {
|
||||||
|
|
||||||
|
if (timeout && !trial.show_feedback_on_timeout) {
|
||||||
|
display_element.innerHTML += trial.timeout_message;
|
||||||
|
} else {
|
||||||
|
// show image during feedback if flag is set
|
||||||
|
if (trial.show_stim_with_feedback) {
|
||||||
|
display_element.innerHTML = '<div id="jspsych-categorize-html-stimulus" class="jspsych-categorize-html-stimulus">'+trial.stimulus+'</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// substitute answer in feedback string.
|
||||||
|
var atext = "";
|
||||||
|
if (correct) {
|
||||||
|
atext = trial.correct_text.replace("%ANS%", trial.text_answer);
|
||||||
|
} else {
|
||||||
|
atext = trial.incorrect_text.replace("%ANS%", trial.text_answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// show the feedback
|
||||||
|
display_element.innerHTML += atext;
|
||||||
|
}
|
||||||
|
// check if force correct button press is set
|
||||||
|
if (trial.force_correct_button_press && correct === false && ((timeout && trial.show_feedback_on_timeout) || !timeout)) {
|
||||||
|
|
||||||
|
var after_forced_response = function(info) {
|
||||||
|
endTrial();
|
||||||
|
}
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_forced_response,
|
||||||
|
valid_responses: [trial.key_answer],
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
endTrial();
|
||||||
|
}, trial.feedback_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
222
PCSurvey/PCstatic/js/plugins/jspsych-categorize-image.js
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
/**
|
||||||
|
* jspsych plugin for categorization trials with feedback
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['categorize-image'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('categorize-image', 'stimulus', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'categorize-image',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The image content to be displayed.'
|
||||||
|
},
|
||||||
|
key_answer: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key answer',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The key to indicate the correct response.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
array: true,
|
||||||
|
description: 'The keys the subject is allowed to press to respond to the stimulus.'
|
||||||
|
},
|
||||||
|
text_answer: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Text answer',
|
||||||
|
default: null,
|
||||||
|
description: 'Label that is associated with the correct answer.'
|
||||||
|
},
|
||||||
|
correct_text: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Correct text',
|
||||||
|
default: "<p class='feedback'>Correct</p>",
|
||||||
|
description: 'String to show when correct answer is given.'
|
||||||
|
},
|
||||||
|
incorrect_text: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Incorrect text',
|
||||||
|
default: "<p class='feedback'>Incorrect</p>",
|
||||||
|
description: 'String to show when incorrect answer is given.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
force_correct_button_press: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Force correct button press',
|
||||||
|
default: false,
|
||||||
|
description: 'If set to true, then the subject must press the correct response key after feedback in order to advance to next trial.'
|
||||||
|
},
|
||||||
|
show_stim_with_feedback: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
default: true,
|
||||||
|
no_function: false,
|
||||||
|
description: ''
|
||||||
|
},
|
||||||
|
show_feedback_on_timeout: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Show feedback on timeout',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, stimulus will be shown during feedback. If false, only the text feedback will be displayed during feedback.'
|
||||||
|
},
|
||||||
|
timeout_message: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Timeout message',
|
||||||
|
default: "<p>Please respond faster.</p>",
|
||||||
|
description: 'The message displayed on a timeout non-response.'
|
||||||
|
},
|
||||||
|
stimulus_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to hide stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show trial'
|
||||||
|
},
|
||||||
|
feedback_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Feedback duration',
|
||||||
|
default: 2000,
|
||||||
|
description: 'How long to show feedback.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
display_element.innerHTML = '<img id="jspsych-categorize-image-stimulus" class="jspsych-categorize-image-stimulus" src="'+trial.stimulus+'"></img>';
|
||||||
|
|
||||||
|
// hide image after time if the timing parameter is set
|
||||||
|
if (trial.stimulus_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-categorize-image-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.stimulus_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if prompt is set, show prompt
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
display_element.innerHTML += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trial_data = {};
|
||||||
|
|
||||||
|
// create response function
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// clear keyboard listener
|
||||||
|
jsPsych.pluginAPI.cancelAllKeyboardResponses();
|
||||||
|
|
||||||
|
var correct = false;
|
||||||
|
if (trial.key_answer == info.key) {
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// save data
|
||||||
|
trial_data = {
|
||||||
|
"rt": info.rt,
|
||||||
|
"correct": correct,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"key_press": info.key
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
var timeout = info.rt == null;
|
||||||
|
doFeedback(correct, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
after_response({
|
||||||
|
key: null,
|
||||||
|
rt: null
|
||||||
|
});
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function doFeedback(correct, timeout) {
|
||||||
|
|
||||||
|
if (timeout && !trial.show_feedback_on_timeout) {
|
||||||
|
display_element.innerHTML += trial.timeout_message;
|
||||||
|
} else {
|
||||||
|
// show image during feedback if flag is set
|
||||||
|
if (trial.show_stim_with_feedback) {
|
||||||
|
display_element.innerHTML = '<img id="jspsych-categorize-image-stimulus" class="jspsych-categorize-image-stimulus" src="'+trial.stimulus+'"></img>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// substitute answer in feedback string.
|
||||||
|
var atext = "";
|
||||||
|
if (correct) {
|
||||||
|
atext = trial.correct_text.replace("%ANS%", trial.text_answer);
|
||||||
|
} else {
|
||||||
|
atext = trial.incorrect_text.replace("%ANS%", trial.text_answer);
|
||||||
|
}
|
||||||
|
|
||||||
|
// show the feedback
|
||||||
|
display_element.innerHTML += atext;
|
||||||
|
}
|
||||||
|
// check if force correct button press is set
|
||||||
|
if (trial.force_correct_button_press && correct === false && ((timeout && trial.show_feedback_on_timeout) || !timeout)) {
|
||||||
|
|
||||||
|
var after_forced_response = function(info) {
|
||||||
|
endTrial();
|
||||||
|
}
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_forced_response,
|
||||||
|
valid_responses: [trial.key_answer],
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
} else {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
endTrial();
|
||||||
|
}, trial.feedback_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
112
PCSurvey/PCstatic/js/plugins/jspsych-cloze.js
Normal file
@@ -0,0 +1,112 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-cloze
|
||||||
|
* Philipp Sprengholz
|
||||||
|
*
|
||||||
|
* Plugin for displaying a cloze test and checking participants answers against a correct solution.
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins['cloze'] = (function () {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'cloze',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
text: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Cloze text',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The cloze text to be displayed. Blanks are indicated by %% signs and automatically replaced by input fields. If there is a correct answer you want the system to check against, it must be typed between the two percentage signs (i.e. %solution%).'
|
||||||
|
},
|
||||||
|
button_text: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button text',
|
||||||
|
default: 'OK',
|
||||||
|
description: 'Text of the button participants have to press for finishing the cloze test.'
|
||||||
|
},
|
||||||
|
check_answers: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Check answers',
|
||||||
|
default: false,
|
||||||
|
description: 'Boolean value indicating if the answers given by participants should be compared against a correct solution given in the text (between % signs) after the button was clicked.'
|
||||||
|
},
|
||||||
|
mistake_fn: {
|
||||||
|
type: jsPsych.plugins.parameterType.FUNCTION,
|
||||||
|
pretty_name: 'Mistake function',
|
||||||
|
default: function () {},
|
||||||
|
description: 'Function called if check_answers is set to TRUE and there is a difference between the participants answers and the correct solution provided in the text.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
plugin.trial = function (display_element, trial) {
|
||||||
|
|
||||||
|
var html = '<div class="cloze">';
|
||||||
|
var elements = trial.text.split('%');
|
||||||
|
var solutions = [];
|
||||||
|
|
||||||
|
for (i=0; i<elements.length; i++)
|
||||||
|
{
|
||||||
|
if (i%2 === 0)
|
||||||
|
{
|
||||||
|
html += elements[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
solutions.push(elements[i].trim());
|
||||||
|
html += '<input type="text" id="input'+(solutions.length-1)+'" value="">';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
var check = function() {
|
||||||
|
|
||||||
|
var answers = [];
|
||||||
|
var answers_correct = true;
|
||||||
|
|
||||||
|
for (i=0; i<solutions.length; i++)
|
||||||
|
{
|
||||||
|
var field = document.getElementById('input'+i);
|
||||||
|
answers.push(field.value.trim());
|
||||||
|
|
||||||
|
if (trial.check_answers)
|
||||||
|
{
|
||||||
|
if (answers[i] !== solutions[i])
|
||||||
|
{
|
||||||
|
field.style.color = 'red';
|
||||||
|
answers_correct = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
field.style.color = 'black';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!trial.check_answers || (trial.check_answers && answers_correct))
|
||||||
|
{
|
||||||
|
var trial_data = {
|
||||||
|
'answers' : answers
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trial.mistake_fn();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML += '<br><button class="jspsych-html-button-response-button" type="button" id="finish_cloze_button">'+trial.button_text+'</button>';
|
||||||
|
display_element.querySelector('#finish_cloze_button').addEventListener('click', check);
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
108
PCSurvey/PCstatic/js/plugins/jspsych-external-html.js
Normal file
@@ -0,0 +1,108 @@
|
|||||||
|
/** (July 2012, Erik Weitnauer)
|
||||||
|
The html-plugin will load and display an external html pages. To proceed to the next, the
|
||||||
|
user might either press a button on the page or a specific key. Afterwards, the page get hidden and
|
||||||
|
the plugin will wait of a specified time before it proceeds.
|
||||||
|
|
||||||
|
documentation: docs.jspsych.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins['external-html'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'external-html',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
url: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'URL',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The url of the external html page'
|
||||||
|
},
|
||||||
|
cont_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Continue key',
|
||||||
|
default: null,
|
||||||
|
description: 'The key to continue to the next page.'
|
||||||
|
},
|
||||||
|
cont_btn: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Continue button',
|
||||||
|
default: null,
|
||||||
|
description: 'The button to continue to the next page.'
|
||||||
|
},
|
||||||
|
check_fn: {
|
||||||
|
type: jsPsych.plugins.parameterType.FUNCTION,
|
||||||
|
pretty_name: 'Check function',
|
||||||
|
default: function() { return true; },
|
||||||
|
description: ''
|
||||||
|
},
|
||||||
|
force_refresh: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Force refresh',
|
||||||
|
default: false,
|
||||||
|
description: 'Refresh page.'
|
||||||
|
},
|
||||||
|
executeScript: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Execute scripts',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, execute scripts on the external html file.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var url = trial.url;
|
||||||
|
if (trial.force_refresh) {
|
||||||
|
url = trial.url + "?time=" + (new Date().getTime());
|
||||||
|
}
|
||||||
|
|
||||||
|
load(display_element, url, function() {
|
||||||
|
var t0 = (new Date()).getTime();
|
||||||
|
var finish = function() {
|
||||||
|
if (trial.check_fn && !trial.check_fn(display_element)) { return };
|
||||||
|
if (trial.cont_key) { document.removeEventListener('keydown', key_listener); }
|
||||||
|
var trial_data = {
|
||||||
|
rt: (new Date()).getTime() - t0,
|
||||||
|
url: trial.url
|
||||||
|
};
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (trial.executeScript) {
|
||||||
|
for (const scriptEl of display_element.getElementsByTagName("script")) {
|
||||||
|
const relocatedScript = document.createElement("script");
|
||||||
|
relocatedScript.text = scriptEl.text;
|
||||||
|
scriptEl.parentNode.replaceChild(relocatedScript, scriptEl);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.cont_btn) { display_element.querySelector('#'+trial.cont_btn).addEventListener('click', finish); }
|
||||||
|
if (trial.cont_key) {
|
||||||
|
var key_listener = function(e) {
|
||||||
|
if (e.which == trial.cont_key) finish();
|
||||||
|
};
|
||||||
|
display_element.addEventListener('keydown', key_listener);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
// helper to load via XMLHttpRequest
|
||||||
|
function load(element, file, callback){
|
||||||
|
var xmlhttp = new XMLHttpRequest();
|
||||||
|
xmlhttp.open("GET", file, true);
|
||||||
|
xmlhttp.onload = function(){
|
||||||
|
if(xmlhttp.status == 200 || xmlhttp.status == 0){ //Check if loaded
|
||||||
|
element.innerHTML = xmlhttp.responseText;
|
||||||
|
callback();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
xmlhttp.send();
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
194
PCSurvey/PCstatic/js/plugins/jspsych-free-sort.js
Normal file
@@ -0,0 +1,194 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-free-sort
|
||||||
|
* plugin for drag-and-drop sorting of a collection of images
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['free-sort'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('free-sort', 'stimuli', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'free-sort',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimuli: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Stimuli',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'Images to be displayed.'
|
||||||
|
},
|
||||||
|
stim_height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus height',
|
||||||
|
default: 100,
|
||||||
|
description: 'Height of images in pixels.'
|
||||||
|
},
|
||||||
|
stim_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus width',
|
||||||
|
default: 100,
|
||||||
|
description: 'Width of images in pixels'
|
||||||
|
},
|
||||||
|
sort_area_height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Sort area height',
|
||||||
|
default: 800,
|
||||||
|
description: 'The height of the container that subjects can move the stimuli in.'
|
||||||
|
},
|
||||||
|
sort_area_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Sort area width',
|
||||||
|
default: 800,
|
||||||
|
description: 'The width of the container that subjects can move the stimuli in.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'It can be used to provide a reminder about the action the subject is supposed to take.'
|
||||||
|
},
|
||||||
|
prompt_location: {
|
||||||
|
type: jsPsych.plugins.parameterType.SELECT,
|
||||||
|
pretty_name: 'Prompt location',
|
||||||
|
options: ['above','below'],
|
||||||
|
default: 'above',
|
||||||
|
description: 'Indicates whether to show prompt "above" or "below" the sorting area.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
description: 'The text that appears on the button to continue to the next trial.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var start_time = performance.now();
|
||||||
|
|
||||||
|
var html = "";
|
||||||
|
// check if there is a prompt and if it is shown above
|
||||||
|
if (trial.prompt !== null && trial.prompt_location == "above") {
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '<div '+
|
||||||
|
'id="jspsych-free-sort-arena" '+
|
||||||
|
'class="jspsych-free-sort-arena" '+
|
||||||
|
'style="position: relative; width:'+trial.sort_area_width+'px; height:'+trial.sort_area_height+'px; border:2px solid #444;"'+
|
||||||
|
'></div>';
|
||||||
|
|
||||||
|
// check if prompt exists and if it is shown below
|
||||||
|
if (trial.prompt !== null && trial.prompt_location == "below") {
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
// store initial location data
|
||||||
|
var init_locations = [];
|
||||||
|
|
||||||
|
for (var i = 0; i < trial.stimuli.length; i++) {
|
||||||
|
var coords = random_coordinate(trial.sort_area_width - trial.stim_width, trial.sort_area_height - trial.stim_height);
|
||||||
|
|
||||||
|
display_element.querySelector("#jspsych-free-sort-arena").innerHTML += '<img '+
|
||||||
|
'src="'+trial.stimuli[i]+'" '+
|
||||||
|
'data-src="'+trial.stimuli[i]+'" '+
|
||||||
|
'class="jspsych-free-sort-draggable" '+
|
||||||
|
'draggable="false" '+
|
||||||
|
'style="position: absolute; cursor: move; width:'+trial.stim_width+'px; height:'+trial.stim_height+'px; top:'+coords.y+'px; left:'+coords.x+'px;">'+
|
||||||
|
'</img>';
|
||||||
|
|
||||||
|
init_locations.push({
|
||||||
|
"src": trial.stimuli[i],
|
||||||
|
"x": coords.x,
|
||||||
|
"y": coords.y
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML += '<button id="jspsych-free-sort-done-btn" class="jspsych-btn">'+trial.button_label+'</button>';
|
||||||
|
|
||||||
|
var maxz = 1;
|
||||||
|
|
||||||
|
var moves = [];
|
||||||
|
|
||||||
|
var draggables = display_element.querySelectorAll('.jspsych-free-sort-draggable');
|
||||||
|
|
||||||
|
for(var i=0;i<draggables.length; i++){
|
||||||
|
draggables[i].addEventListener('mousedown', function(event){
|
||||||
|
var x = event.pageX - event.currentTarget.offsetLeft;
|
||||||
|
var y = event.pageY - event.currentTarget.offsetTop - window.scrollY;
|
||||||
|
var elem = event.currentTarget;
|
||||||
|
elem.style.zIndex = ++maxz;
|
||||||
|
|
||||||
|
var mousemoveevent = function(e){
|
||||||
|
elem.style.top = Math.min(trial.sort_area_height - trial.stim_height, Math.max(0,(e.clientY - y))) + 'px';
|
||||||
|
elem.style.left = Math.min(trial.sort_area_width - trial.stim_width, Math.max(0,(e.clientX - x))) + 'px';
|
||||||
|
}
|
||||||
|
document.addEventListener('mousemove', mousemoveevent);
|
||||||
|
|
||||||
|
var mouseupevent = function(e){
|
||||||
|
document.removeEventListener('mousemove', mousemoveevent);
|
||||||
|
moves.push({
|
||||||
|
"src": elem.dataset.src,
|
||||||
|
"x": elem.offsetLeft,
|
||||||
|
"y": elem.offsetTop
|
||||||
|
});
|
||||||
|
document.removeEventListener('mouseup', mouseupevent);
|
||||||
|
}
|
||||||
|
document.addEventListener('mouseup', mouseupevent);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-free-sort-done-btn').addEventListener('click', function(){
|
||||||
|
|
||||||
|
var end_time = performance.now();
|
||||||
|
var rt = end_time - start_time;
|
||||||
|
// gather data
|
||||||
|
// get final position of all objects
|
||||||
|
var final_locations = [];
|
||||||
|
var matches = display_element.querySelectorAll('.jspsych-free-sort-draggable');
|
||||||
|
for(var i=0; i<matches.length; i++){
|
||||||
|
final_locations.push({
|
||||||
|
"src": matches[i].dataset.src,
|
||||||
|
"x": parseInt(matches[i].style.left),
|
||||||
|
"y": parseInt(matches[i].style.top)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
"init_locations": JSON.stringify(init_locations),
|
||||||
|
"moves": JSON.stringify(moves),
|
||||||
|
"final_locations": JSON.stringify(final_locations),
|
||||||
|
"rt": rt
|
||||||
|
};
|
||||||
|
|
||||||
|
// advance to next part
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
});
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// helper functions
|
||||||
|
|
||||||
|
function random_coordinate(max_width, max_height) {
|
||||||
|
var rnd_x = Math.floor(Math.random() * (max_width - 1));
|
||||||
|
var rnd_y = Math.floor(Math.random() * (max_height - 1));
|
||||||
|
|
||||||
|
return {
|
||||||
|
x: rnd_x,
|
||||||
|
y: rnd_y
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
104
PCSurvey/PCstatic/js/plugins/jspsych-fullscreen.js
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/* jspsych-fullscreen.js
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* toggle fullscreen mode in the browser
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins.fullscreen = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'fullscreen',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
fullscreen_mode: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Fullscreen mode',
|
||||||
|
default: true,
|
||||||
|
array: false,
|
||||||
|
description: 'If true, experiment will enter fullscreen mode. If false, the browser will exit fullscreen mode.'
|
||||||
|
},
|
||||||
|
message: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Message',
|
||||||
|
default: '<p>The experiment will switch to full screen mode when you press the button below</p>',
|
||||||
|
array: false,
|
||||||
|
description: 'HTML content to display above the button to enter fullscreen mode.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
array: false,
|
||||||
|
description: 'The text that appears on the button to enter fullscreen.'
|
||||||
|
},
|
||||||
|
delay_after: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Delay after',
|
||||||
|
default: 1000,
|
||||||
|
array: false,
|
||||||
|
description: 'The length of time to delay after entering fullscreen mode before ending the trial.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// check if keys are allowed in fullscreen mode
|
||||||
|
var keyboardNotAllowed = typeof Element !== 'undefined' && 'ALLOW_KEYBOARD_INPUT' in Element;
|
||||||
|
if (keyboardNotAllowed) {
|
||||||
|
// This is Safari, and keyboard events will be disabled. Don't allow fullscreen here.
|
||||||
|
// do something else?
|
||||||
|
endTrial();
|
||||||
|
} else {
|
||||||
|
if(trial.fullscreen_mode){
|
||||||
|
display_element.innerHTML = trial.message + '<button id="jspsych-fullscreen-btn" class="jspsych-btn">'+trial.button_label+'</button>';
|
||||||
|
var listener = display_element.querySelector('#jspsych-fullscreen-btn').addEventListener('click', function() {
|
||||||
|
var element = document.documentElement;
|
||||||
|
if (element.requestFullscreen) {
|
||||||
|
element.requestFullscreen();
|
||||||
|
} else if (element.mozRequestFullScreen) {
|
||||||
|
element.mozRequestFullScreen();
|
||||||
|
} else if (element.webkitRequestFullscreen) {
|
||||||
|
element.webkitRequestFullscreen();
|
||||||
|
} else if (element.msRequestFullscreen) {
|
||||||
|
element.msRequestFullscreen();
|
||||||
|
}
|
||||||
|
endTrial();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
if (document.exitFullscreen) {
|
||||||
|
document.exitFullscreen();
|
||||||
|
} else if (document.msExitFullscreen) {
|
||||||
|
document.msExitFullscreen();
|
||||||
|
} else if (document.mozCancelFullScreen) {
|
||||||
|
document.mozCancelFullScreen();
|
||||||
|
} else if (document.webkitExitFullscreen) {
|
||||||
|
document.webkitExitFullscreen();
|
||||||
|
}
|
||||||
|
endTrial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.setTimeout(function(){
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
success: !keyboardNotAllowed
|
||||||
|
};
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
|
||||||
|
}, trial.delay_after);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
188
PCSurvey/PCstatic/js/plugins/jspsych-html-button-response.js
Normal file
@@ -0,0 +1,188 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-html-button-response
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for displaying a stimulus and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["html-button-response"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'html-button-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The HTML string to be displayed'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'The labels for the buttons.'
|
||||||
|
},
|
||||||
|
button_html: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button HTML',
|
||||||
|
default: '<button class="jspsych-btn">%choice%</button>',
|
||||||
|
array: true,
|
||||||
|
description: 'The html of the button. Can create own style.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed under the button.'
|
||||||
|
},
|
||||||
|
stimulus_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to hide the stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial.'
|
||||||
|
},
|
||||||
|
margin_vertical: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Margin vertical',
|
||||||
|
default: '0px',
|
||||||
|
description: 'The vertical margin of the button.'
|
||||||
|
},
|
||||||
|
margin_horizontal: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Margin horizontal',
|
||||||
|
default: '8px',
|
||||||
|
description: 'The horizontal margin of the button.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, then trial will end when user responds.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// display stimulus
|
||||||
|
var html = '<div id="jspsych-html-button-response-stimulus">'+trial.stimulus+'</div>';
|
||||||
|
|
||||||
|
//display buttons
|
||||||
|
var buttons = [];
|
||||||
|
if (Array.isArray(trial.button_html)) {
|
||||||
|
if (trial.button_html.length == trial.choices.length) {
|
||||||
|
buttons = trial.button_html;
|
||||||
|
} else {
|
||||||
|
console.error('Error in html-button-response plugin. The length of the button_html array does not equal the length of the choices array');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
buttons.push(trial.button_html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html += '<div id="jspsych-html-button-response-btngroup">';
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
var str = buttons[i].replace(/%choice%/g, trial.choices[i]);
|
||||||
|
html += '<div class="jspsych-html-button-response-button" style="display: inline-block; margin:'+trial.margin_vertical+' '+trial.margin_horizontal+'" id="jspsych-html-button-response-button-' + i +'" data-choice="'+i+'">'+str+'</div>';
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
//show prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
// start time
|
||||||
|
var start_time = performance.now();
|
||||||
|
|
||||||
|
// add event listeners to buttons
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
display_element.querySelector('#jspsych-html-button-response-button-' + i).addEventListener('click', function(e){
|
||||||
|
var choice = e.currentTarget.getAttribute('data-choice'); // don't use dataset for jsdom compatibility
|
||||||
|
after_response(choice);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
button: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
function after_response(choice) {
|
||||||
|
|
||||||
|
// measure rt
|
||||||
|
var end_time = performance.now();
|
||||||
|
var rt = end_time - start_time;
|
||||||
|
response.button = choice;
|
||||||
|
response.rt = rt;
|
||||||
|
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-html-button-response-stimulus').className += ' responded';
|
||||||
|
|
||||||
|
// disable all the buttons after a response
|
||||||
|
var btns = document.querySelectorAll('.jspsych-html-button-response-button button');
|
||||||
|
for(var i=0; i<btns.length; i++){
|
||||||
|
//btns[i].removeEventListener('click');
|
||||||
|
btns[i].setAttribute('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
function end_trial() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"button_pressed": response.button
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// hide image if timing is set
|
||||||
|
if (trial.stimulus_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-html-button-response-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.stimulus_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
149
PCSurvey/PCstatic/js/plugins/jspsych-html-keyboard-response.js
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-html-keyboard-response
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for displaying a stimulus and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins["html-keyboard-response"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'html-keyboard-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The HTML string to be displayed'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
array: true,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
description: 'The keys the subject is allowed to press to respond to the stimulus.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
stimulus_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to hide the stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show trial before it ends.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, trial will end when subject makes a response.'
|
||||||
|
},
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var new_html = '<div id="jspsych-html-keyboard-response-stimulus">'+trial.stimulus+'</div>';
|
||||||
|
|
||||||
|
// add prompt
|
||||||
|
if(trial.prompt !== null){
|
||||||
|
new_html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw
|
||||||
|
display_element.innerHTML = new_html;
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
key: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
var end_trial = function() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// kill keyboard listeners
|
||||||
|
if (typeof keyboardListener !== 'undefined') {
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"key_press": response.key
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-html-keyboard-response-stimulus').className += ' responded';
|
||||||
|
|
||||||
|
// only record the first response
|
||||||
|
if (response.key == null) {
|
||||||
|
response = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// start the response listener
|
||||||
|
if (trial.choices != jsPsych.NO_KEYS) {
|
||||||
|
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide stimulus if stimulus_duration is set
|
||||||
|
if (trial.stimulus_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-html-keyboard-response-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.stimulus_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if trial_duration is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
193
PCSurvey/PCstatic/js/plugins/jspsych-html-slider-response.js
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-html-slider-response
|
||||||
|
* a jspsych plugin for free response survey questions
|
||||||
|
*
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['html-slider-response'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'html-slider-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The HTML string to be displayed'
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Min slider',
|
||||||
|
default: 0,
|
||||||
|
description: 'Sets the minimum value of the slider.'
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Max slider',
|
||||||
|
default: 100,
|
||||||
|
description: 'Sets the maximum value of the slider',
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Slider starting value',
|
||||||
|
default: 50,
|
||||||
|
description: 'Sets the starting value of the slider',
|
||||||
|
},
|
||||||
|
step: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Step',
|
||||||
|
default: 1,
|
||||||
|
description: 'Sets the step of the slider'
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name:'Labels',
|
||||||
|
default: [],
|
||||||
|
array: true,
|
||||||
|
description: 'Labels of the slider.',
|
||||||
|
},
|
||||||
|
slider_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name:'Slider width',
|
||||||
|
default: null,
|
||||||
|
description: 'Width of the slider in pixels.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
array: false,
|
||||||
|
description: 'Label of the button to advance.'
|
||||||
|
},
|
||||||
|
require_movement: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Require movement',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the participant will have to move the slider before continuing.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the slider.'
|
||||||
|
},
|
||||||
|
stimulus_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to hide the stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, trial will end when user makes a response.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var html = '<div id="jspsych-html-slider-response-wrapper" style="margin: 100px 0px;">';
|
||||||
|
html += '<div id="jspsych-html-slider-response-stimulus">' + trial.stimulus + '</div>';
|
||||||
|
html += '<div class="jspsych-html-slider-response-container" style="position:relative; margin: 0 auto 3em auto; ';
|
||||||
|
if(trial.slider_width !== null){
|
||||||
|
html += 'width:'+trial.slider_width+'px;';
|
||||||
|
}
|
||||||
|
html += '">';
|
||||||
|
html += '<input type="range" value="'+trial.start+'" min="'+trial.min+'" max="'+trial.max+'" step="'+trial.step+'" style="width: 100%;" id="jspsych-html-slider-response-response"></input>';
|
||||||
|
html += '<div>'
|
||||||
|
for(var j=0; j < trial.labels.length; j++){
|
||||||
|
var width = 100/(trial.labels.length-1);
|
||||||
|
var left_offset = (j * (100 /(trial.labels.length - 1))) - (width/2);
|
||||||
|
html += '<div style="display: inline-block; position: absolute; left:'+left_offset+'%; text-align: center; width: '+width+'%;">';
|
||||||
|
html += '<span style="text-align: center; font-size: 80%;">'+trial.labels[j]+'</span>';
|
||||||
|
html += '</div>'
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
if (trial.prompt !== null){
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
html += '<button id="jspsych-html-slider-response-next" class="jspsych-btn" '+ (trial.require_movement ? "disabled" : "") + '>'+trial.button_label+'</button>';
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
response: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if(trial.require_movement){
|
||||||
|
display_element.querySelector('#jspsych-html-slider-response-response').addEventListener('change', function(){
|
||||||
|
display_element.querySelector('#jspsych-html-slider-response-next').disabled = false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-html-slider-response-next').addEventListener('click', function() {
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
response.rt = endTime - startTime;
|
||||||
|
response.response = display_element.querySelector('#jspsych-html-slider-response-response').value;
|
||||||
|
|
||||||
|
if(trial.response_ends_trial){
|
||||||
|
end_trial();
|
||||||
|
} else {
|
||||||
|
display_element.querySelector('#jspsych-html-slider-response-next').disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function end_trial(){
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// save data
|
||||||
|
var trialdata = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"response": response.response,
|
||||||
|
"stimulus": trial.stimulus
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trialdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.stimulus_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-html-slider-response-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.stimulus_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if trial_duration is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
284
PCSurvey/PCstatic/js/plugins/jspsych-iat-html.js
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-iat
|
||||||
|
* Kristin Diep
|
||||||
|
*
|
||||||
|
* plugin for displaying a stimulus and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['iat-html'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'iat-html',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The HTML string to be displayed.'
|
||||||
|
},
|
||||||
|
left_category_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Left category key',
|
||||||
|
default: 'E',
|
||||||
|
description: 'Key press that is associated with the left category label.'
|
||||||
|
},
|
||||||
|
right_category_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Right category key',
|
||||||
|
default: 'I',
|
||||||
|
description: 'Key press that is associated with the right category label.'
|
||||||
|
},
|
||||||
|
left_category_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Left category label',
|
||||||
|
array: true,
|
||||||
|
default: ['left'],
|
||||||
|
description: 'The label that is associated with the stimulus. Aligned to the left side of page.'
|
||||||
|
},
|
||||||
|
right_category_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Right category label',
|
||||||
|
array: true,
|
||||||
|
default: ['right'],
|
||||||
|
description: 'The label that is associated with the stimulus. Aligned to the right side of the page.'
|
||||||
|
},
|
||||||
|
key_to_move_forward: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key to move forward',
|
||||||
|
array: true,
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
description: 'The keys that allow the user to advance to the next trial if their key press was incorrect.'
|
||||||
|
},
|
||||||
|
display_feedback: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Display feedback',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, then html when wrong will be displayed when user makes an incorrect key press.'
|
||||||
|
},
|
||||||
|
html_when_wrong: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'HTML when wrong',
|
||||||
|
default: '<span style="color: red; font-size: 80px">X</span>',
|
||||||
|
description: 'The image to display when a user presses the wrong key.'
|
||||||
|
},
|
||||||
|
bottom_instructions: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Bottom instructions',
|
||||||
|
default: '<p>If you press the wrong key, a red X will appear. Press any key to continue.</p>',
|
||||||
|
description: 'Instructions shown at the bottom of the page.'
|
||||||
|
},
|
||||||
|
force_correct_key_press: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Force correct key press',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, in order to advance to the next trial after a wrong key press the user will be forced to press the correct key.'
|
||||||
|
},
|
||||||
|
stim_key_association: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Stimulus key association',
|
||||||
|
options: ['left', 'right'],
|
||||||
|
default: 'undefined',
|
||||||
|
description: 'Stimulus will be associated with eight "left" or "right".'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, trial will end when user makes a response.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var html_str = "";
|
||||||
|
|
||||||
|
html_str += "<div style='position: absolute; height: 20%; width: 100%; margin-left: auto; margin-right: auto; top: 42%; left: 0; right: 0'><p id='jspsych-iat-stim'>" + trial.stimulus + "</p></div>";
|
||||||
|
|
||||||
|
html_str += "<div id='trial_left_align' style='position: absolute; top: 18%; left: 20%'>";
|
||||||
|
|
||||||
|
if(trial.left_category_label.length == 1) {
|
||||||
|
html_str += "<p>Press " + trial.left_category_key + " for:<br> " +
|
||||||
|
trial.left_category_label[0].bold() + "</p></div>";
|
||||||
|
} else {
|
||||||
|
html_str += "<p>Press " + trial.left_category_key + " for:<br> " +
|
||||||
|
trial.left_category_label[0].bold() + "<br>" + "or<br>" +
|
||||||
|
trial.left_category_label[1].bold() + "</p></div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
html_str += "<div id='trial_right_align' style='position: absolute; top: 18%; right: 20%'>";
|
||||||
|
|
||||||
|
if(trial.right_category_label.length == 1) {
|
||||||
|
html_str += "<p>Press " + trial.right_category_key + " for:<br> " +
|
||||||
|
trial.right_category_label[0].bold() + '</p></div>';
|
||||||
|
} else {
|
||||||
|
html_str += "<p>Press " + trial.right_category_key + " for:<br> " +
|
||||||
|
trial.right_category_label[0].bold() + "<br>" + "or<br>" +
|
||||||
|
trial.right_category_label[1].bold() + "</p></div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
html_str += "<div id='wrongImgID' style='position:relative; top: 300px; margin-left: auto; margin-right: auto; left: 0; right: 0'>";
|
||||||
|
|
||||||
|
if(trial.display_feedback === true) {
|
||||||
|
html_str += "<div id='wrongImgContainer' style='visibility: hidden; position: absolute; top: -75px; margin-left: auto; margin-right: auto; left: 0; right: 0'><p>"+trial.html_when_wrong+"</p></div>";
|
||||||
|
html_str += "<div>"+trial.bottom_instructions+"</div>";
|
||||||
|
} else {
|
||||||
|
html_str += "<div>"+trial.bottom_instructions+"</div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
html_str += "</div>";
|
||||||
|
|
||||||
|
display_element.innerHTML = html_str;
|
||||||
|
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
key: null,
|
||||||
|
correct: false
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
var end_trial = function() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// kill keyboard listeners
|
||||||
|
if (typeof keyboardListener !== 'undefined') {
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"key_press": response.key,
|
||||||
|
"correct": response.correct
|
||||||
|
};
|
||||||
|
|
||||||
|
// clears the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
var leftKeyCode = jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.left_category_key);
|
||||||
|
var rightKeyCode = jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.right_category_key);
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
var after_response = function(info) {
|
||||||
|
var wImg = document.getElementById("wrongImgContainer");
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-iat-stim').className += ' responded';
|
||||||
|
|
||||||
|
// only record the first response
|
||||||
|
if (response.key == null ) {
|
||||||
|
response = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.stim_key_association == "right") {
|
||||||
|
if(response.rt !== null && response.key == rightKeyCode) {
|
||||||
|
response.correct = true;
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.correct = false;
|
||||||
|
if(!trial.response_ends_trial && trial.display_feedback == true) {
|
||||||
|
wImg.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
if (trial.response_ends_trial && trial.display_feedback == true) {
|
||||||
|
wImg.style.visibility = "visible";
|
||||||
|
if(trial.force_correct_key_press) {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: [trial.right_category_key]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: trial.key_to_move_forward
|
||||||
|
});}
|
||||||
|
} else if(trial.response_ends_trial && trial.display_feedback != true) {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: [jsPsych.ALL_KEYS]
|
||||||
|
});
|
||||||
|
} else if(!trial.response_ends_trial && trial.display_feedback != true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(trial.stim_key_association == "left") {
|
||||||
|
if(response.rt !== null && response.key == leftKeyCode) {
|
||||||
|
response.correct = true;
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.correct = false;
|
||||||
|
if(!trial.response_ends_trial && trial.display_feedback == true) {
|
||||||
|
wImg.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
if (trial.response_ends_trial && trial.display_feedback == true) {
|
||||||
|
wImg.style.visibility = "visible";
|
||||||
|
if(trial.force_correct_key_press) {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: [trial.left_category_key]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: trial.key_to_move_forward
|
||||||
|
});}
|
||||||
|
} else if(trial.response_ends_trial && trial.display_feedback != true) {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: [jsPsych.ALL_KEYS]
|
||||||
|
});
|
||||||
|
} else if(!trial.response_ends_trial && trial.display_feedback != true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// start the response listener
|
||||||
|
if (trial.left_category_key != jsPsych.NO_KEYS && trial.right_category_key != jsPsych.NO_KEYS) {
|
||||||
|
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: [trial.left_category_key, trial.right_category_key],
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null && trial.response_ends_trial != true) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
286
PCSurvey/PCstatic/js/plugins/jspsych-iat-image.js
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-iat
|
||||||
|
* Kristin Diep
|
||||||
|
*
|
||||||
|
* plugin for displaying a stimulus and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['iat-image'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('iat-image', 'stimulus', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'iat-image',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The image to be displayed'
|
||||||
|
},
|
||||||
|
left_category_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Left category key',
|
||||||
|
default: 'E',
|
||||||
|
description: 'Key press that is associated with the left category label.'
|
||||||
|
},
|
||||||
|
right_category_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Right category key',
|
||||||
|
default: 'I',
|
||||||
|
description: 'Key press that is associated with the right category label.'
|
||||||
|
},
|
||||||
|
left_category_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Left category label',
|
||||||
|
array: true,
|
||||||
|
default: ['left'],
|
||||||
|
description: 'The label that is associated with the stimulus. Aligned to the left side of page.'
|
||||||
|
},
|
||||||
|
right_category_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Right category label',
|
||||||
|
array: true,
|
||||||
|
default: ['right'],
|
||||||
|
description: 'The label that is associated with the stimulus. Aligned to the right side of the page.'
|
||||||
|
},
|
||||||
|
key_to_move_forward: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key to move forward',
|
||||||
|
array: true,
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
description: 'The keys that allow the user to advance to the next trial if their key press was incorrect.'
|
||||||
|
},
|
||||||
|
display_feedback: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Display feedback',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, then html when wrong will be displayed when user makes an incorrect key press.'
|
||||||
|
},
|
||||||
|
html_when_wrong: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'HTML when wrong',
|
||||||
|
default: '<span style="color: red; font-size: 80px">X</span>',
|
||||||
|
description: 'The image to display when a user presses the wrong key.'
|
||||||
|
},
|
||||||
|
bottom_instructions: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Bottom instructions',
|
||||||
|
default: '<p>If you press the wrong key, a red X will appear. Press any key to continue.</p>',
|
||||||
|
description: 'Instructions shown at the bottom of the page.'
|
||||||
|
},
|
||||||
|
force_correct_key_press: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Force correct key press',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, in order to advance to the next trial after a wrong key press the user will be forced to press the correct key.'
|
||||||
|
},
|
||||||
|
stim_key_association: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Stimulus key association',
|
||||||
|
options: ['left', 'right'],
|
||||||
|
default: 'undefined',
|
||||||
|
description: 'Stimulus will be associated with eight "left" or "right".'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, trial will end when user makes a response.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var html_str = "";
|
||||||
|
|
||||||
|
html_str += "<div style='position: absolute; height: 20%; width: 100%; margin-left: auto; margin-right: auto; top: 42%; left: 0; right: 0'><img src='"+trial.stimulus+"' id='jspsych-iat-stim'></img></div>";
|
||||||
|
|
||||||
|
html_str += "<div id='trial_left_align' style='position: absolute; top: 18%; left: 20%'>";
|
||||||
|
|
||||||
|
if(trial.left_category_label.length == 1) {
|
||||||
|
html_str += "<p>Press " + trial.left_category_key + " for:<br> " +
|
||||||
|
trial.left_category_label[0].bold() + "</p></div>";
|
||||||
|
} else {
|
||||||
|
html_str += "<p>Press " + trial.left_category_key + " for:<br> " +
|
||||||
|
trial.left_category_label[0].bold() + "<br>" + "or<br>" +
|
||||||
|
trial.left_category_label[1].bold() + "</p></div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
html_str += "<div id='trial_right_align' style='position: absolute; top: 18%; right: 20%'>";
|
||||||
|
|
||||||
|
if(trial.right_category_label.length == 1) {
|
||||||
|
html_str += "<p>Press " + trial.right_category_key + " for:<br> " +
|
||||||
|
trial.right_category_label[0].bold() + '</p></div>';
|
||||||
|
} else {
|
||||||
|
html_str += "<p>Press " + trial.right_category_key + " for:<br> " +
|
||||||
|
trial.right_category_label[0].bold() + "<br>" + "or<br>" +
|
||||||
|
trial.right_category_label[1].bold() + "</p></div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
html_str += "<div id='wrongImgID' style='position:relative; top: 300px; margin-left: auto; margin-right: auto; left: 0; right: 0'>";
|
||||||
|
|
||||||
|
if(trial.display_feedback === true) {
|
||||||
|
html_str += "<div id='wrongImgContainer' style='visibility: hidden; position: absolute; top: -75px; margin-left: auto; margin-right: auto; left: 0; right: 0'><p>"+trial.html_when_wrong+"</p></div>";
|
||||||
|
html_str += "<div>"+trial.bottom_instructions+"</div>";
|
||||||
|
} else {
|
||||||
|
html_str += "<div>"+trial.bottom_instructions+"</div>";
|
||||||
|
}
|
||||||
|
|
||||||
|
html_str += "</div>";
|
||||||
|
|
||||||
|
display_element.innerHTML = html_str;
|
||||||
|
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
key: null,
|
||||||
|
correct: false
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
var end_trial = function() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// kill keyboard listeners
|
||||||
|
if (typeof keyboardListener !== 'undefined') {
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"key_press": response.key,
|
||||||
|
"correct": response.correct
|
||||||
|
};
|
||||||
|
|
||||||
|
// clears the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
var leftKeyCode = jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.left_category_key);
|
||||||
|
var rightKeyCode = jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.right_category_key);
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
var after_response = function(info) {
|
||||||
|
var wImg = document.getElementById("wrongImgContainer");
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-iat-stim').className += ' responded';
|
||||||
|
|
||||||
|
// only record the first response
|
||||||
|
if (response.key == null ) {
|
||||||
|
response = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.stim_key_association == "right") {
|
||||||
|
if(response.rt !== null && response.key == rightKeyCode) {
|
||||||
|
response.correct = true;
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.correct = false;
|
||||||
|
if(!trial.response_ends_trial && trial.display_feedback == true) {
|
||||||
|
wImg.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
if (trial.response_ends_trial && trial.display_feedback == true) {
|
||||||
|
wImg.style.visibility = "visible";
|
||||||
|
if(trial.force_correct_key_press) {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: [trial.right_category_key]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: trial.key_to_move_forward
|
||||||
|
});}
|
||||||
|
} else if(trial.response_ends_trial && trial.display_feedback != true) {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: [jsPsych.ALL_KEYS]
|
||||||
|
});
|
||||||
|
} else if(!trial.response_ends_trial && trial.display_feedback != true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if(trial.stim_key_association == "left") {
|
||||||
|
if(response.rt !== null && response.key == leftKeyCode) {
|
||||||
|
response.correct = true;
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
response.correct = false;
|
||||||
|
if(!trial.response_ends_trial && trial.display_feedback == true) {
|
||||||
|
wImg.style.visibility = "visible";
|
||||||
|
}
|
||||||
|
if (trial.response_ends_trial && trial.display_feedback == true) {
|
||||||
|
wImg.style.visibility = "visible";
|
||||||
|
if(trial.force_correct_key_press) {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: [trial.left_category_key]
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: trial.key_to_move_forward
|
||||||
|
});}
|
||||||
|
} else if(trial.response_ends_trial && trial.display_feedback != true) {
|
||||||
|
var keyListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: end_trial,
|
||||||
|
valid_responses: [jsPsych.ALL_KEYS]
|
||||||
|
});
|
||||||
|
} else if(!trial.response_ends_trial && trial.display_feedback != true) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// start the response listener
|
||||||
|
if (trial.left_category_key != jsPsych.NO_KEYS && trial.right_category_key != jsPsych.NO_KEYS) {
|
||||||
|
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: [trial.left_category_key, trial.right_category_key],
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null && trial.response_ends_trial != true) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
224
PCSurvey/PCstatic/js/plugins/jspsych-image-button-response.js
Normal file
@@ -0,0 +1,224 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-image-button-response
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for displaying a stimulus and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["image-button-response"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('image-button-response', 'stimulus', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'image-button-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The image to be displayed'
|
||||||
|
},
|
||||||
|
stimulus_height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Image height',
|
||||||
|
default: null,
|
||||||
|
description: 'Set the image height in pixels'
|
||||||
|
},
|
||||||
|
stimulus_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Image width',
|
||||||
|
default: null,
|
||||||
|
description: 'Set the image width in pixels'
|
||||||
|
},
|
||||||
|
maintain_aspect_ratio: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Maintain aspect ratio',
|
||||||
|
default: true,
|
||||||
|
description: 'Maintain the aspect ratio after setting width or height'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'The labels for the buttons.'
|
||||||
|
},
|
||||||
|
button_html: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button HTML',
|
||||||
|
default: '<button class="jspsych-btn">%choice%</button>',
|
||||||
|
array: true,
|
||||||
|
description: 'The html of the button. Can create own style.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed under the button.'
|
||||||
|
},
|
||||||
|
stimulus_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to hide the stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial.'
|
||||||
|
},
|
||||||
|
margin_vertical: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Margin vertical',
|
||||||
|
default: '0px',
|
||||||
|
description: 'The vertical margin of the button.'
|
||||||
|
},
|
||||||
|
margin_horizontal: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Margin horizontal',
|
||||||
|
default: '8px',
|
||||||
|
description: 'The horizontal margin of the button.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, then trial will end when user responds.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// display stimulus
|
||||||
|
var html = '<img src="'+trial.stimulus+'" id="jspsych-image-button-response-stimulus" style="';
|
||||||
|
if(trial.stimulus_height !== null){
|
||||||
|
html += 'height:'+trial.stimulus_height+'px; '
|
||||||
|
if(trial.stimulus_width == null && trial.maintain_aspect_ratio){
|
||||||
|
html += 'width: auto; ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(trial.stimulus_width !== null){
|
||||||
|
html += 'width:'+trial.stimulus_width+'px; '
|
||||||
|
if(trial.stimulus_height == null && trial.maintain_aspect_ratio){
|
||||||
|
html += 'height: auto; ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html +='"></img>';
|
||||||
|
|
||||||
|
//display buttons
|
||||||
|
var buttons = [];
|
||||||
|
if (Array.isArray(trial.button_html)) {
|
||||||
|
if (trial.button_html.length == trial.choices.length) {
|
||||||
|
buttons = trial.button_html;
|
||||||
|
} else {
|
||||||
|
console.error('Error in image-button-response plugin. The length of the button_html array does not equal the length of the choices array');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
buttons.push(trial.button_html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html += '<div id="jspsych-image-button-response-btngroup">';
|
||||||
|
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
var str = buttons[i].replace(/%choice%/g, trial.choices[i]);
|
||||||
|
html += '<div class="jspsych-image-button-response-button" style="display: inline-block; margin:'+trial.margin_vertical+' '+trial.margin_horizontal+'" id="jspsych-image-button-response-button-' + i +'" data-choice="'+i+'">'+str+'</div>';
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
//show prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
// start timing
|
||||||
|
var start_time = performance.now();
|
||||||
|
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
display_element.querySelector('#jspsych-image-button-response-button-' + i).addEventListener('click', function(e){
|
||||||
|
var choice = e.currentTarget.getAttribute('data-choice'); // don't use dataset for jsdom compatibility
|
||||||
|
after_response(choice);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
button: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
function after_response(choice) {
|
||||||
|
|
||||||
|
// measure rt
|
||||||
|
var end_time = performance.now();
|
||||||
|
var rt = end_time - start_time;
|
||||||
|
response.button = choice;
|
||||||
|
response.rt = rt;
|
||||||
|
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-image-button-response-stimulus').className += ' responded';
|
||||||
|
|
||||||
|
// disable all the buttons after a response
|
||||||
|
var btns = document.querySelectorAll('.jspsych-image-button-response-button button');
|
||||||
|
for(var i=0; i<btns.length; i++){
|
||||||
|
//btns[i].removeEventListener('click');
|
||||||
|
btns[i].setAttribute('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
function end_trial() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"button_pressed": response.button
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// hide image if timing is set
|
||||||
|
if (trial.stimulus_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-image-button-response-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.stimulus_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
182
PCSurvey/PCstatic/js/plugins/jspsych-image-keyboard-response.js
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-image-keyboard-response
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for displaying a stimulus and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins["image-keyboard-response"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('image-keyboard-response', 'stimulus', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'image-keyboard-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The image to be displayed'
|
||||||
|
},
|
||||||
|
stimulus_height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Image height',
|
||||||
|
default: null,
|
||||||
|
description: 'Set the image height in pixels'
|
||||||
|
},
|
||||||
|
stimulus_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Image width',
|
||||||
|
default: null,
|
||||||
|
description: 'Set the image width in pixels'
|
||||||
|
},
|
||||||
|
maintain_aspect_ratio: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Maintain aspect ratio',
|
||||||
|
default: true,
|
||||||
|
description: 'Maintain the aspect ratio after setting width or height'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
array: true,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
description: 'The keys the subject is allowed to press to respond to the stimulus.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
stimulus_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to hide the stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show trial before it ends.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, trial will end when subject makes a response.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// display stimulus
|
||||||
|
var html = '<img src="'+trial.stimulus+'" id="jspsych-image-keyboard-response-stimulus" style="';
|
||||||
|
if(trial.stimulus_height !== null){
|
||||||
|
html += 'height:'+trial.stimulus_height+'px; '
|
||||||
|
if(trial.stimulus_width == null && trial.maintain_aspect_ratio){
|
||||||
|
html += 'width: auto; ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(trial.stimulus_width !== null){
|
||||||
|
html += 'width:'+trial.stimulus_width+'px; '
|
||||||
|
if(trial.stimulus_height == null && trial.maintain_aspect_ratio){
|
||||||
|
html += 'height: auto; ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html +='"></img>';
|
||||||
|
|
||||||
|
// add prompt
|
||||||
|
if (trial.prompt !== null){
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// render
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
key: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
var end_trial = function() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// kill keyboard listeners
|
||||||
|
if (typeof keyboardListener !== 'undefined') {
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"key_press": response.key
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-image-keyboard-response-stimulus').className += ' responded';
|
||||||
|
|
||||||
|
// only record the first response
|
||||||
|
if (response.key == null) {
|
||||||
|
response = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// start the response listener
|
||||||
|
if (trial.choices != jsPsych.NO_KEYS) {
|
||||||
|
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// hide stimulus if stimulus_duration is set
|
||||||
|
if (trial.stimulus_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-image-keyboard-response-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.stimulus_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if trial_duration is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
227
PCSurvey/PCstatic/js/plugins/jspsych-image-slider-response.js
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-image-slider-response
|
||||||
|
* a jspsych plugin for free response survey questions
|
||||||
|
*
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['image-slider-response'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('image-slider-response', 'stimulus', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'image-slider-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimulus: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimulus',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The image to be displayed'
|
||||||
|
},
|
||||||
|
stimulus_height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Image height',
|
||||||
|
default: null,
|
||||||
|
description: 'Set the image height in pixels'
|
||||||
|
},
|
||||||
|
stimulus_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Image width',
|
||||||
|
default: null,
|
||||||
|
description: 'Set the image width in pixels'
|
||||||
|
},
|
||||||
|
maintain_aspect_ratio: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Maintain aspect ratio',
|
||||||
|
default: true,
|
||||||
|
description: 'Maintain the aspect ratio after setting width or height'
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Min slider',
|
||||||
|
default: 0,
|
||||||
|
description: 'Sets the minimum value of the slider.'
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Max slider',
|
||||||
|
default: 100,
|
||||||
|
description: 'Sets the maximum value of the slider',
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Slider starting value',
|
||||||
|
default: 50,
|
||||||
|
description: 'Sets the starting value of the slider',
|
||||||
|
},
|
||||||
|
step: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Step',
|
||||||
|
default: 1,
|
||||||
|
description: 'Sets the step of the slider'
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name:'Labels',
|
||||||
|
default: [],
|
||||||
|
array: true,
|
||||||
|
description: 'Labels of the slider.',
|
||||||
|
},
|
||||||
|
slider_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name:'Slider width',
|
||||||
|
default: null,
|
||||||
|
description: 'Width of the slider in pixels.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
array: false,
|
||||||
|
description: 'Label of the button to advance.'
|
||||||
|
},
|
||||||
|
require_movement: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Require movement',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the participant will have to move the slider before continuing.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the slider.'
|
||||||
|
},
|
||||||
|
stimulus_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Stimulus duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to hide the stimulus.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, trial will end when user makes a response.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var html = '<div id="jspsych-image-slider-response-wrapper" style="margin: 100px 0px;">';
|
||||||
|
html += '<div id="jspsych-image-slider-response-stimulus">';
|
||||||
|
html += '<img src="'+trial.stimulus+'" style="';
|
||||||
|
if(trial.stimulus_height !== null){
|
||||||
|
html += 'height:'+trial.stimulus_height+'px; '
|
||||||
|
if(trial.stimulus_width == null && trial.maintain_aspect_ratio){
|
||||||
|
html += 'width: auto; ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(trial.stimulus_width !== null){
|
||||||
|
html += 'width:'+trial.stimulus_width+'px; '
|
||||||
|
if(trial.stimulus_height == null && trial.maintain_aspect_ratio){
|
||||||
|
html += 'height: auto; ';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
html += '"></img>';
|
||||||
|
html += '</div>';
|
||||||
|
html += '<div class="jspsych-image-slider-response-container" style="position:relative; margin: 0 auto 3em auto; ';
|
||||||
|
if(trial.slider_width !== null){
|
||||||
|
html += 'width:'+trial.slider_width+'px;';
|
||||||
|
}
|
||||||
|
html += '">';
|
||||||
|
html += '<input type="range" value="'+trial.start+'" min="'+trial.min+'" max="'+trial.max+'" step="'+trial.step+'" style="width: 100%;" id="jspsych-image-slider-response-response"></input>';
|
||||||
|
html += '<div>'
|
||||||
|
for(var j=0; j < trial.labels.length; j++){
|
||||||
|
var width = 100/(trial.labels.length-1);
|
||||||
|
var left_offset = (j * (100 /(trial.labels.length - 1))) - (width/2);
|
||||||
|
html += '<div style="display: inline-block; position: absolute; left:'+left_offset+'%; text-align: center; width: '+width+'%;">';
|
||||||
|
html += '<span style="text-align: center; font-size: 80%;">'+trial.labels[j]+'</span>';
|
||||||
|
html += '</div>'
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
if (trial.prompt !== null){
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
html += '<button id="jspsych-image-slider-response-next" class="jspsych-btn" '+ (trial.require_movement ? "disabled" : "") + '>'+trial.button_label+'</button>';
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
response: null
|
||||||
|
};
|
||||||
|
|
||||||
|
if(trial.require_movement){
|
||||||
|
display_element.querySelector('#jspsych-image-slider-response-response').addEventListener('change', function(){
|
||||||
|
display_element.querySelector('#jspsych-image-slider-response-next').disabled = false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-image-slider-response-next').addEventListener('click', function() {
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
response.rt = endTime - startTime;
|
||||||
|
response.response = display_element.querySelector('#jspsych-image-slider-response-response').value;
|
||||||
|
|
||||||
|
if(trial.response_ends_trial){
|
||||||
|
end_trial();
|
||||||
|
} else {
|
||||||
|
display_element.querySelector('#jspsych-image-slider-response-next').disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
function end_trial(){
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// save data
|
||||||
|
var trialdata = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"response": response.response
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trialdata);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.stimulus_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('#jspsych-image-slider-response-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.stimulus_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if trial_duration is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
203
PCSurvey/PCstatic/js/plugins/jspsych-instructions.js
Normal file
@@ -0,0 +1,203 @@
|
|||||||
|
/* jspsych-text.js
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* This plugin displays text (including HTML formatted strings) during the experiment.
|
||||||
|
* Use it to show instructions, provide performance feedback, etc...
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins.instructions = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'instructions',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
pages: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Pages',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'Each element of the array is the content for a single page.'
|
||||||
|
},
|
||||||
|
key_forward: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key forward',
|
||||||
|
default: 'rightarrow',
|
||||||
|
description: 'The key the subject can press in order to advance to the next page.'
|
||||||
|
},
|
||||||
|
key_backward: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key backward',
|
||||||
|
default: 'leftarrow',
|
||||||
|
description: 'The key that the subject can press to return to the previous page.'
|
||||||
|
},
|
||||||
|
allow_backward: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Allow backward',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the subject can return to the previous page of the instructions.'
|
||||||
|
},
|
||||||
|
allow_keys: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Allow keys',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the subject can use keyboard keys to navigate the pages.'
|
||||||
|
},
|
||||||
|
show_clickable_nav: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Show clickable nav',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, then a "Previous" and "Next" button will be displayed beneath the instructions.'
|
||||||
|
},
|
||||||
|
button_label_previous: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label previous',
|
||||||
|
default: 'Previous',
|
||||||
|
description: 'The text that appears on the button to go backwards.'
|
||||||
|
},
|
||||||
|
button_label_next: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label next',
|
||||||
|
default: 'Next',
|
||||||
|
description: 'The text that appears on the button to go forwards.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var current_page = 0;
|
||||||
|
|
||||||
|
var view_history = [];
|
||||||
|
|
||||||
|
var start_time = (new Date()).getTime();
|
||||||
|
|
||||||
|
var last_page_update_time = start_time;
|
||||||
|
|
||||||
|
function btnListener(evt){
|
||||||
|
evt.target.removeEventListener('click', btnListener);
|
||||||
|
if(this.id === "jspsych-instructions-back"){
|
||||||
|
back();
|
||||||
|
}
|
||||||
|
else if(this.id === 'jspsych-instructions-next'){
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_current_page() {
|
||||||
|
display_element.innerHTML = trial.pages[current_page];
|
||||||
|
|
||||||
|
if (trial.show_clickable_nav) {
|
||||||
|
|
||||||
|
var nav_html = "<div class='jspsych-instructions-nav' style='padding: 10px 0px;'>";
|
||||||
|
if (current_page != 0 && trial.allow_backward) {
|
||||||
|
nav_html += "<button id='jspsych-instructions-back' class='jspsych-btn' style='margin-right: 5px;'>< "+trial.button_label_previous+"</button>";
|
||||||
|
}
|
||||||
|
nav_html += "<button id='jspsych-instructions-next' class='jspsych-btn' style='margin-left: 5px;'>"+trial.button_label_next+" ></button></div>"
|
||||||
|
|
||||||
|
display_element.innerHTML += nav_html;
|
||||||
|
|
||||||
|
if (current_page != 0 && trial.allow_backward) {
|
||||||
|
display_element.querySelector('#jspsych-instructions-back').addEventListener('click', btnListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-instructions-next').addEventListener('click', btnListener);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function next() {
|
||||||
|
|
||||||
|
add_current_page_to_view_history()
|
||||||
|
|
||||||
|
current_page++;
|
||||||
|
|
||||||
|
// if done, finish up...
|
||||||
|
if (current_page >= trial.pages.length) {
|
||||||
|
endTrial();
|
||||||
|
} else {
|
||||||
|
show_current_page();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function back() {
|
||||||
|
|
||||||
|
add_current_page_to_view_history()
|
||||||
|
|
||||||
|
current_page--;
|
||||||
|
|
||||||
|
show_current_page();
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_current_page_to_view_history() {
|
||||||
|
|
||||||
|
var current_time = (new Date()).getTime();
|
||||||
|
|
||||||
|
var page_view_time = current_time - last_page_update_time;
|
||||||
|
|
||||||
|
view_history.push({
|
||||||
|
page_index: current_page,
|
||||||
|
viewing_time: page_view_time
|
||||||
|
});
|
||||||
|
|
||||||
|
last_page_update_time = current_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
|
||||||
|
if (trial.allow_keys) {
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(keyboard_listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
"view_history": JSON.stringify(view_history),
|
||||||
|
"rt": (new Date()).getTime() - start_time
|
||||||
|
};
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// have to reinitialize this instead of letting it persist to prevent accidental skips of pages by holding down keys too long
|
||||||
|
keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: [trial.key_forward, trial.key_backward],
|
||||||
|
rt_method: 'date',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
// check if key is forwards or backwards and update page
|
||||||
|
if (info.key === trial.key_backward || info.key === jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_backward)) {
|
||||||
|
if (current_page !== 0 && trial.allow_backward) {
|
||||||
|
back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.key === trial.key_forward || info.key === jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_forward)) {
|
||||||
|
next();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
show_current_page();
|
||||||
|
|
||||||
|
if (trial.allow_keys) {
|
||||||
|
var keyboard_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: [trial.key_forward, trial.key_backward],
|
||||||
|
rt_method: 'date',
|
||||||
|
persist: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
1369
PCSurvey/PCstatic/js/plugins/jspsych-rdk.js
Normal file
134
PCSurvey/PCstatic/js/plugins/jspsych-reconstruction.js
Normal file
@@ -0,0 +1,134 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-reconstruction
|
||||||
|
* a jspsych plugin for a reconstruction task where the subject recreates
|
||||||
|
* a stimulus from memory
|
||||||
|
*
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['reconstruction'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'reconstruction',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stim_function: {
|
||||||
|
type: jsPsych.plugins.parameterType.FUNCTION,
|
||||||
|
pretty_name: 'Stimulus function',
|
||||||
|
default: undefined,
|
||||||
|
description: 'A function with a single parameter that returns an HTML-formatted string representing the stimulus.'
|
||||||
|
},
|
||||||
|
starting_value: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Starting value',
|
||||||
|
default: 0.5,
|
||||||
|
description: 'The starting value of the stimulus parameter.'
|
||||||
|
},
|
||||||
|
step_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Step size',
|
||||||
|
default: 0.05,
|
||||||
|
description: 'The change in the stimulus parameter caused by pressing one of the modification keys.'
|
||||||
|
},
|
||||||
|
key_increase: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key increase',
|
||||||
|
default: 'h',
|
||||||
|
description: 'The key to press for increasing the parameter value.'
|
||||||
|
},
|
||||||
|
key_decrease: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Key decrease',
|
||||||
|
default: 'g',
|
||||||
|
description: 'The key to press for decreasing the parameter value.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
description: 'The text that appears on the button to finish the trial.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// current param level
|
||||||
|
var param = trial.starting_value;
|
||||||
|
|
||||||
|
// set-up key listeners
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
//console.log('fire');
|
||||||
|
|
||||||
|
var key_i = (typeof trial.key_increase == 'string') ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_increase) : trial.key_increase;
|
||||||
|
var key_d = (typeof trial.key_decrease == 'string') ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.key_decrease) : trial.key_decrease;
|
||||||
|
|
||||||
|
// get new param value
|
||||||
|
if (info.key == key_i) {
|
||||||
|
param = param + trial.step_size;
|
||||||
|
} else if (info.key == key_d) {
|
||||||
|
param = param - trial.step_size;
|
||||||
|
}
|
||||||
|
param = Math.max(Math.min(1, param), 0);
|
||||||
|
|
||||||
|
// refresh the display
|
||||||
|
draw(param);
|
||||||
|
}
|
||||||
|
|
||||||
|
// listen for responses
|
||||||
|
var key_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: [trial.key_increase, trial.key_decrease],
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: true,
|
||||||
|
allow_held_key: true
|
||||||
|
});
|
||||||
|
// draw first iteration
|
||||||
|
draw(param);
|
||||||
|
|
||||||
|
function draw(param) {
|
||||||
|
|
||||||
|
//console.log(param);
|
||||||
|
|
||||||
|
display_element.innerHTML = '<div id="jspsych-reconstruction-stim-container">'+trial.stim_function(param)+'</div>';
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
display_element.innerHTML += '<button id="jspsych-reconstruction-next" class="jspsych-btn jspsych-reconstruction">'+trial.button_label+'</button>';
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-reconstruction-next').addEventListener('click', endTrial);
|
||||||
|
}
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
// measure response time
|
||||||
|
var endTime =performance.now();
|
||||||
|
var response_time = endTime - startTime;
|
||||||
|
|
||||||
|
// clear keyboard response
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(key_listener);
|
||||||
|
|
||||||
|
// save data
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response_time,
|
||||||
|
"final_value": param,
|
||||||
|
"start_value": trial.starting_value
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
166
PCSurvey/PCstatic/js/plugins/jspsych-resize.js
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-resize
|
||||||
|
* Steve Chao
|
||||||
|
*
|
||||||
|
* plugin for controlling the real world size of the display
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["resize"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'resize',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
item_height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Item height',
|
||||||
|
default: 1,
|
||||||
|
description: 'The height of the item to be measured.'
|
||||||
|
},
|
||||||
|
item_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Item width',
|
||||||
|
default: 1,
|
||||||
|
description: 'The width of the item to be measured.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'The content displayed below the resizable box and above the button.'
|
||||||
|
},
|
||||||
|
pixels_per_unit: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Pixels per unit',
|
||||||
|
default: 100,
|
||||||
|
description: 'After the scaling factor is applied, this many pixels will equal one unit of measurement.'
|
||||||
|
},
|
||||||
|
starting_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Starting size',
|
||||||
|
default: 100,
|
||||||
|
description: 'The initial size of the box, in pixels, along the larget dimension.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
description: 'Label to display on the button to complete calibration.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var aspect_ratio = trial.item_width / trial.item_height;
|
||||||
|
|
||||||
|
// variables to determine div size
|
||||||
|
if(trial.item_width >= trial.item_height){
|
||||||
|
var start_div_width = trial.starting_size;
|
||||||
|
var start_div_height = Math.round(trial.starting_size / aspect_ratio);
|
||||||
|
} else {
|
||||||
|
var start_div_height = trial.starting_size;
|
||||||
|
var start_div_width = Math.round(trial.starting_size * aspect_ratio);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create html for display
|
||||||
|
var html ='<div id="jspsych-resize-div" style="border: 2px solid steelblue; height: '+start_div_height+'px; width:'+start_div_width+'px; margin: 7px auto; background-color: lightsteelblue; position: relative;">';
|
||||||
|
html += '<div id="jspsych-resize-handle" style="cursor: nwse-resize; background-color: steelblue; width: 10px; height: 10px; border: 2px solid lightsteelblue; position: absolute; bottom: 0; right: 0;"></div>';
|
||||||
|
html += '</div>';
|
||||||
|
if (trial.prompt !== null){
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
html += '<a class="jspsych-btn" id="jspsych-resize-btn">'+trial.button_label+'</a>';
|
||||||
|
|
||||||
|
// render
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
// listens for the click
|
||||||
|
document.getElementById("jspsych-resize-btn").addEventListener('click', function() {
|
||||||
|
scale();
|
||||||
|
end_trial();
|
||||||
|
});
|
||||||
|
|
||||||
|
var dragging = false;
|
||||||
|
var origin_x, origin_y;
|
||||||
|
var cx, cy;
|
||||||
|
|
||||||
|
var mousedownevent = function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
dragging = true;
|
||||||
|
origin_x = e.pageX;
|
||||||
|
origin_y = e.pageY;
|
||||||
|
cx = parseInt(scale_div.style.width);
|
||||||
|
cy = parseInt(scale_div.style.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-resize-handle').addEventListener('mousedown', mousedownevent);
|
||||||
|
|
||||||
|
var mouseupevent = function(e){
|
||||||
|
dragging = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('mouseup', mouseupevent);
|
||||||
|
|
||||||
|
var scale_div = display_element.querySelector('#jspsych-resize-div');
|
||||||
|
|
||||||
|
var resizeevent = function(e){
|
||||||
|
if(dragging){
|
||||||
|
var dx = (e.pageX - origin_x);
|
||||||
|
var dy = (e.pageY - origin_y);
|
||||||
|
|
||||||
|
if(Math.abs(dx) >= Math.abs(dy)){
|
||||||
|
scale_div.style.width = Math.round(Math.max(20, cx+dx*2)) + "px";
|
||||||
|
scale_div.style.height = Math.round(Math.max(20, cx+dx*2) / aspect_ratio ) + "px";
|
||||||
|
} else {
|
||||||
|
scale_div.style.height = Math.round(Math.max(20, cy+dy*2)) + "px";
|
||||||
|
scale_div.style.width = Math.round(aspect_ratio * Math.max(20, cy+dy*2)) + "px";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('mousemove', resizeevent);
|
||||||
|
|
||||||
|
// scales the stimulus
|
||||||
|
var scale_factor;
|
||||||
|
var final_height_px, final_width_px;
|
||||||
|
function scale() {
|
||||||
|
final_width_px = scale_div.offsetWidth;
|
||||||
|
//final_height_px = scale_div.offsetHeight;
|
||||||
|
|
||||||
|
var pixels_unit_screen = final_width_px / trial.item_width;
|
||||||
|
|
||||||
|
scale_factor = pixels_unit_screen / trial.pixels_per_unit;
|
||||||
|
document.getElementById("jspsych-content").style.transform = "scale(" + scale_factor + ")";
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// function to end trial
|
||||||
|
function end_trial() {
|
||||||
|
|
||||||
|
// clear document event listeners
|
||||||
|
document.removeEventListener('mousemove', resizeevent);
|
||||||
|
document.removeEventListener('mouseup', mouseupevent);
|
||||||
|
|
||||||
|
// clear the screen
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// finishes trial
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
'final_height_px': final_height_px,
|
||||||
|
'final_width_px': final_width_px,
|
||||||
|
'scale_factor': scale_factor
|
||||||
|
}
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
168
PCSurvey/PCstatic/js/plugins/jspsych-same-different-html.js
Normal file
@@ -0,0 +1,168 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-same-different
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for showing two stimuli sequentially and getting a same / different judgment
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins['same-different-html'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'same-different-html',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimuli: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'Stimuli',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'The HTML content to be displayed.'
|
||||||
|
},
|
||||||
|
answer: {
|
||||||
|
type: jsPsych.plugins.parameterType.SELECT,
|
||||||
|
pretty_name: 'Answer',
|
||||||
|
options: ['same', 'different'],
|
||||||
|
default: 75,
|
||||||
|
description: 'Either "same" or "different".'
|
||||||
|
},
|
||||||
|
same_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Same key',
|
||||||
|
default: 'Q',
|
||||||
|
description: ''
|
||||||
|
},
|
||||||
|
different_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Different key',
|
||||||
|
default: 'P',
|
||||||
|
description: 'The key that subjects should press to indicate that the two stimuli are the same.'
|
||||||
|
},
|
||||||
|
first_stim_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'First stimulus duration',
|
||||||
|
default: 1000,
|
||||||
|
description: 'How long to show the first stimulus for in milliseconds.'
|
||||||
|
},
|
||||||
|
gap_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Gap duration',
|
||||||
|
default: 500,
|
||||||
|
description: 'How long to show a blank screen in between the two stimuli.'
|
||||||
|
},
|
||||||
|
second_stim_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Second stimulus duration',
|
||||||
|
default: 1000,
|
||||||
|
description: 'How long to show the second stimulus for in milliseconds.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
display_element.innerHTML = '<div class="jspsych-same-different-stimulus">'+trial.stimuli[0]+'</div>';
|
||||||
|
|
||||||
|
var first_stim_info;
|
||||||
|
if (trial.first_stim_duration > 0) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
showBlankScreen();
|
||||||
|
}, trial.first_stim_duration);
|
||||||
|
} else {
|
||||||
|
function afterKeyboardResponse(info) {
|
||||||
|
first_stim_info = info;
|
||||||
|
showBlankScreen();
|
||||||
|
}
|
||||||
|
jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: afterKeyboardResponse,
|
||||||
|
valid_responses: trial.advance_key,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showBlankScreen() {
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
showSecondStim();
|
||||||
|
}, trial.gap_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSecondStim() {
|
||||||
|
|
||||||
|
var html = '<div class="jspsych-same-different-stimulus">'+trial.stimuli[1]+'</div>';
|
||||||
|
//show prompt here
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
if (trial.second_stim_duration > 0) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('.jspsych-same-different-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.second_stim_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
var correct = false;
|
||||||
|
|
||||||
|
var skey = typeof trial.same_key == 'string' ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.same_key) : trial.same_key;
|
||||||
|
var dkey = typeof trial.different_key == 'string' ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.different_key) : trial.different_key;
|
||||||
|
|
||||||
|
if (info.key == skey && trial.answer == 'same') {
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.key == dkey && trial.answer == 'different') {
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
"rt": info.rt,
|
||||||
|
"answer": trial.answer,
|
||||||
|
"correct": correct,
|
||||||
|
"stimulus": JSON.stringify([trial.stimuli[0], trial.stimuli[1]]),
|
||||||
|
"key_press": info.key
|
||||||
|
};
|
||||||
|
if (first_stim_info) {
|
||||||
|
trial_data["rt_stim1"] = first_stim_info.rt;
|
||||||
|
trial_data["key_press_stim1"] = first_stim_info.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: [trial.same_key, trial.different_key],
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
169
PCSurvey/PCstatic/js/plugins/jspsych-same-different-image.js
Normal file
@@ -0,0 +1,169 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-same-different
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for showing two stimuli sequentially and getting a same / different judgment
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins['same-different-image'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('same-different-image', 'stimuli', 'image')
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'same-different-image',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimuli: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimuli',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'The images to be displayed.'
|
||||||
|
},
|
||||||
|
answer: {
|
||||||
|
type: jsPsych.plugins.parameterType.SELECT,
|
||||||
|
pretty_name: 'Answer',
|
||||||
|
options: ['same', 'different'],
|
||||||
|
default: 75,
|
||||||
|
description: 'Either "same" or "different".'
|
||||||
|
},
|
||||||
|
same_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Same key',
|
||||||
|
default: 'Q',
|
||||||
|
description: ''
|
||||||
|
},
|
||||||
|
different_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Different key',
|
||||||
|
default: 'P',
|
||||||
|
description: 'The key that subjects should press to indicate that the two stimuli are the same.'
|
||||||
|
},
|
||||||
|
first_stim_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'First stimulus duration',
|
||||||
|
default: 1000,
|
||||||
|
description: 'How long to show the first stimulus for in milliseconds.'
|
||||||
|
},
|
||||||
|
gap_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Gap duration',
|
||||||
|
default: 500,
|
||||||
|
description: 'How long to show a blank screen in between the two stimuli.'
|
||||||
|
},
|
||||||
|
second_stim_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Second stimulus duration',
|
||||||
|
default: 1000,
|
||||||
|
description: 'How long to show the second stimulus for in milliseconds.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
display_element.innerHTML = '<img class="jspsych-same-different-stimulus" src="'+trial.stimuli[0]+'"></img>';
|
||||||
|
|
||||||
|
var first_stim_info;
|
||||||
|
if (trial.first_stim_duration > 0) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
showBlankScreen();
|
||||||
|
}, trial.first_stim_duration);
|
||||||
|
} else {
|
||||||
|
function afterKeyboardResponse(info) {
|
||||||
|
first_stim_info = info;
|
||||||
|
showBlankScreen();
|
||||||
|
}
|
||||||
|
jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: afterKeyboardResponse,
|
||||||
|
valid_responses: trial.advance_key,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function showBlankScreen() {
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
showSecondStim();
|
||||||
|
}, trial.gap_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function showSecondStim() {
|
||||||
|
|
||||||
|
var html = '<img class="jspsych-same-different-stimulus" src="'+trial.stimuli[1]+'"></img>';
|
||||||
|
//show prompt
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
if (trial.second_stim_duration > 0) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
display_element.querySelector('.jspsych-same-different-stimulus').style.visibility = 'hidden';
|
||||||
|
}, trial.second_stim_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
var correct = false;
|
||||||
|
|
||||||
|
var skey = typeof trial.same_key == 'string' ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.same_key) : trial.same_key;
|
||||||
|
var dkey = typeof trial.different_key == 'string' ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.different_key) : trial.different_key;
|
||||||
|
|
||||||
|
if (info.key == skey && trial.answer == 'same') {
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (info.key == dkey && trial.answer == 'different') {
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
"rt": info.rt,
|
||||||
|
"answer": trial.answer,
|
||||||
|
"correct": correct,
|
||||||
|
"stimulus": JSON.stringify([trial.stimuli[0], trial.stimuli[1]]),
|
||||||
|
"key_press": info.key
|
||||||
|
};
|
||||||
|
if (first_stim_info) {
|
||||||
|
trial_data["rt_stim1"] = first_stim_info.rt;
|
||||||
|
trial_data["key_press_stim1"] = first_stim_info.key;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: [trial.same_key, trial.different_key],
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
@@ -0,0 +1,213 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-serial-reaction-time
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for running a serial reaction time task
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["serial-reaction-time-mouse"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'serial-reaction-time-mouse',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
target: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Target',
|
||||||
|
array: true,
|
||||||
|
default: undefined,
|
||||||
|
description: 'The location of the target. The array should be the [row, column] of the target.'
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Grid',
|
||||||
|
array: true,
|
||||||
|
default: [[1,1,1,1]],
|
||||||
|
description: 'This array represents the grid of boxes shown on the screen.'
|
||||||
|
},
|
||||||
|
grid_square_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Grid square size',
|
||||||
|
default: 100,
|
||||||
|
description: 'The width and height in pixels of each square in the grid.'
|
||||||
|
},
|
||||||
|
target_color: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Target color',
|
||||||
|
default: "#999",
|
||||||
|
description: 'The color of the target square.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the trial ends after a key press.'
|
||||||
|
},
|
||||||
|
pre_target_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Pre-target duration',
|
||||||
|
default: 0,
|
||||||
|
description: 'The number of milliseconds to display the grid before the target changes color.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial'
|
||||||
|
},
|
||||||
|
fade_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Fade duration',
|
||||||
|
default: null,
|
||||||
|
description: 'If a positive number, the target will progressively change color at the start of the trial, with the transition lasting this many milliseconds.'
|
||||||
|
},
|
||||||
|
allow_nontarget_responses: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Allow nontarget response',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, then user can make nontarget response.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var startTime = -1;
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
row: null,
|
||||||
|
column: null
|
||||||
|
}
|
||||||
|
|
||||||
|
// display stimulus
|
||||||
|
var stimulus = this.stimulus(trial.grid, trial.grid_square_size);
|
||||||
|
display_element.innerHTML = stimulus;
|
||||||
|
|
||||||
|
|
||||||
|
if(trial.pre_target_duration <= 0){
|
||||||
|
showTarget();
|
||||||
|
} else {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function(){
|
||||||
|
showTarget();
|
||||||
|
}, trial.pre_target_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
//show prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
display_element.innerHTML += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
function showTarget(){
|
||||||
|
var resp_targets;
|
||||||
|
if(!trial.allow_nontarget_responses){
|
||||||
|
resp_targets = [display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+trial.target[0]+'-'+trial.target[1])]
|
||||||
|
} else {
|
||||||
|
resp_targets = display_element.querySelectorAll('.jspsych-serial-reaction-time-stimulus-cell');
|
||||||
|
}
|
||||||
|
for(var i=0; i<resp_targets.length; i++){
|
||||||
|
resp_targets[i].addEventListener('mousedown', function(e){
|
||||||
|
if(startTime == -1){
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
var info = {}
|
||||||
|
info.row = e.currentTarget.getAttribute('data-row');
|
||||||
|
info.column = e.currentTarget.getAttribute('data-column');
|
||||||
|
info.rt = performance.now() - startTime;
|
||||||
|
after_response(info);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime = performance.now();
|
||||||
|
|
||||||
|
if(trial.fade_duration == null){
|
||||||
|
display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+trial.target[0]+'-'+trial.target[1]).style.backgroundColor = trial.target_color;
|
||||||
|
} else {
|
||||||
|
display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+trial.target[0]+'-'+trial.target[1]).style.transition = "background-color "+trial.fade_duration;
|
||||||
|
display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+trial.target[0]+'-'+trial.target[1]).style.backgroundColor = trial.target_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.trial_duration !== null){
|
||||||
|
jsPsych.pluginAPI.setTimeout(endTrial, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"grid": JSON.stringify(trial.grid),
|
||||||
|
"target": JSON.stringify(trial.target),
|
||||||
|
"response_row": response.row,
|
||||||
|
"response_column": response.column,
|
||||||
|
"correct": response.row == trial.target[0] && response.column == trial.target[1]
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
function after_response(info) {
|
||||||
|
|
||||||
|
// only record first response
|
||||||
|
response = response.rt == null ? info : response;
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
endTrial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
plugin.stimulus = function(grid, square_size, target, target_color, labels) {
|
||||||
|
var stimulus = "<div id='jspsych-serial-reaction-time-stimulus' style='margin:auto; display: table; table-layout: fixed; border-spacing:"+square_size/4+"px'>";
|
||||||
|
for(var i=0; i<grid.length; i++){
|
||||||
|
stimulus += "<div class='jspsych-serial-reaction-time-stimulus-row' style='display:table-row;'>";
|
||||||
|
for(var j=0; j<grid[i].length; j++){
|
||||||
|
var classname = 'jspsych-serial-reaction-time-stimulus-cell';
|
||||||
|
|
||||||
|
stimulus += "<div class='"+classname+"' id='jspsych-serial-reaction-time-stimulus-cell-"+i+"-"+j+"' "+
|
||||||
|
"data-row="+i+" data-column="+j+" "+
|
||||||
|
"style='width:"+square_size+"px; height:"+square_size+"px; display:table-cell; vertical-align:middle; text-align: center; cursor: pointer; font-size:"+square_size/2+"px;";
|
||||||
|
if(grid[i][j] == 1){
|
||||||
|
stimulus += "border: 2px solid black;"
|
||||||
|
}
|
||||||
|
if(typeof target !== 'undefined' && target[0] == i && target[1] == j){
|
||||||
|
stimulus += "background-color: "+target_color+";"
|
||||||
|
}
|
||||||
|
stimulus += "'>";
|
||||||
|
if(typeof labels !=='undefined' && labels[i][j] !== false){
|
||||||
|
stimulus += labels[i][j]
|
||||||
|
}
|
||||||
|
stimulus += "</div>";
|
||||||
|
}
|
||||||
|
stimulus += "</div>";
|
||||||
|
}
|
||||||
|
stimulus += "</div>";
|
||||||
|
|
||||||
|
return stimulus
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
247
PCSurvey/PCstatic/js/plugins/jspsych-serial-reaction-time.js
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-serial-reaction-time
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for running a serial reaction time task
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["serial-reaction-time"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'serial-reaction-time',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
grid: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Grid',
|
||||||
|
array: true,
|
||||||
|
default: [[1,1,1,1]],
|
||||||
|
description: 'This array represents the grid of boxes shown on the screen.'
|
||||||
|
},
|
||||||
|
target: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Target',
|
||||||
|
array: true,
|
||||||
|
default: undefined,
|
||||||
|
description: 'The location of the target. The array should be the [row, column] of the target.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
array: true,
|
||||||
|
default: [['3','5','7','9']],
|
||||||
|
description: ' Each entry in this array is the key that should be pressed for that corresponding location in the grid.'
|
||||||
|
},
|
||||||
|
grid_square_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Grid square size',
|
||||||
|
default: 100,
|
||||||
|
description: 'The width and height in pixels of each square in the grid.'
|
||||||
|
},
|
||||||
|
target_color: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Target color',
|
||||||
|
default: "#999",
|
||||||
|
description: 'The color of the target square.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, trial ends when user makes a response.'
|
||||||
|
},
|
||||||
|
pre_target_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Pre-target duration',
|
||||||
|
default: 0,
|
||||||
|
description: 'The number of milliseconds to display the grid before the target changes color.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show the trial.'
|
||||||
|
},
|
||||||
|
show_response_feedback: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Show response feedback',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, show feedback indicating where the user responded and whether it was correct.'
|
||||||
|
},
|
||||||
|
feedback_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Feedback duration',
|
||||||
|
default: 200,
|
||||||
|
description: 'The length of time in milliseconds to show the feedback.'
|
||||||
|
},
|
||||||
|
fade_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Fade duration',
|
||||||
|
default: null,
|
||||||
|
description: 'If a positive number, the target will progressively change color at the start of the trial, with the transition lasting this many milliseconds.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
no_function: false,
|
||||||
|
description: ' Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// create a flattened version of the choices array
|
||||||
|
var flat_choices = jsPsych.utils.flatten(trial.choices);
|
||||||
|
while(flat_choices.indexOf('') > -1){
|
||||||
|
flat_choices.splice(flat_choices.indexOf(''),1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// display stimulus
|
||||||
|
var stimulus = this.stimulus(trial.grid, trial.grid_square_size);
|
||||||
|
display_element.innerHTML = stimulus;
|
||||||
|
|
||||||
|
if(trial.pre_target_duration <= 0){
|
||||||
|
showTarget();
|
||||||
|
} else {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function(){
|
||||||
|
showTarget();
|
||||||
|
}, trial.pre_target_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
//show prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
display_element.innerHTML += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
var keyboardListener = {};
|
||||||
|
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
key: false,
|
||||||
|
correct: false
|
||||||
|
}
|
||||||
|
|
||||||
|
function showTarget(){
|
||||||
|
if(trial.fade_duration == null){
|
||||||
|
display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+trial.target[0]+'-'+trial.target[1]).style.backgroundColor = trial.target_color;
|
||||||
|
} else {
|
||||||
|
display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+trial.target[0]+'-'+trial.target[1]).style.transition = "background-color "+trial.fade_duration;
|
||||||
|
display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+trial.target[0]+'-'+trial.target[1]).style.backgroundColor = trial.target_color;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: flat_choices,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
if(trial.trial_duration > null){
|
||||||
|
jsPsych.pluginAPI.setTimeout(showFeedback, trial.trial_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function showFeedback() {
|
||||||
|
if(response.rt == null || trial.show_response_feedback == false){
|
||||||
|
endTrial();
|
||||||
|
} else {
|
||||||
|
var color = response.correct ? '#0f0' : '#f00';
|
||||||
|
display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+response.responseLoc[0]+'-'+response.responseLoc[1]).style.transition = "";
|
||||||
|
display_element.querySelector('#jspsych-serial-reaction-time-stimulus-cell-'+response.responseLoc[0]+'-'+response.responseLoc[1]).style.backgroundColor = color;
|
||||||
|
jsPsych.pluginAPI.setTimeout(endTrial, trial.feedback_duration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// kill keyboard listeners
|
||||||
|
if (typeof keyboardListener !== 'undefined') {
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(keyboardListener);
|
||||||
|
}
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"key_press": response.key,
|
||||||
|
"correct": response.correct,
|
||||||
|
"grid": JSON.stringify(trial.grid),
|
||||||
|
"target": JSON.stringify(trial.target)
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
function after_response(info) {
|
||||||
|
|
||||||
|
// only record first response
|
||||||
|
response = response.rt == null ? info : response;
|
||||||
|
|
||||||
|
// check if the response is correct
|
||||||
|
var responseLoc = [];
|
||||||
|
for(var i=0; i<trial.choices.length; i++){
|
||||||
|
for(var j=0; j<trial.choices[i].length; j++){
|
||||||
|
var t = typeof trial.choices[i][j] == 'string' ? jsPsych.pluginAPI.convertKeyCharacterToKeyCode(trial.choices[i][j]) : trial.choices[i][j];
|
||||||
|
if(info.key == t){
|
||||||
|
responseLoc = [i,j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response.responseLoc = responseLoc;
|
||||||
|
response.correct = (JSON.stringify(responseLoc) == JSON.stringify(trial.target));
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
if (trial.show_response_feedback){
|
||||||
|
showFeedback(response.correct);
|
||||||
|
} else {
|
||||||
|
endTrial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
plugin.stimulus = function(grid, square_size, target, target_color, labels) {
|
||||||
|
var stimulus = "<div id='jspsych-serial-reaction-time-stimulus' style='margin:auto; display: table; table-layout: fixed; border-spacing:"+square_size/4+"px'>";
|
||||||
|
for(var i=0; i<grid.length; i++){
|
||||||
|
stimulus += "<div class='jspsych-serial-reaction-time-stimulus-row' style='display:table-row;'>";
|
||||||
|
for(var j=0; j<grid[i].length; j++){
|
||||||
|
stimulus += "<div class='jspsych-serial-reaction-time-stimulus-cell' id='jspsych-serial-reaction-time-stimulus-cell-"+i+"-"+j+"' "+
|
||||||
|
"style='width:"+square_size+"px; height:"+square_size+"px; display:table-cell; vertical-align:middle; text-align: center; font-size:"+square_size/2+"px;";
|
||||||
|
if(grid[i][j] == 1){
|
||||||
|
stimulus += "border: 2px solid black;"
|
||||||
|
}
|
||||||
|
if(typeof target !== 'undefined' && target[0] == i && target[1] == j){
|
||||||
|
stimulus += "background-color: "+target_color+";"
|
||||||
|
}
|
||||||
|
stimulus += "'>";
|
||||||
|
if(typeof labels !=='undefined' && labels[i][j] !== false){
|
||||||
|
stimulus += labels[i][j]
|
||||||
|
}
|
||||||
|
stimulus += "</div>";
|
||||||
|
}
|
||||||
|
stimulus += "</div>";
|
||||||
|
}
|
||||||
|
stimulus += "</div>";
|
||||||
|
|
||||||
|
return stimulus
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
144
PCSurvey/PCstatic/js/plugins/jspsych-survey-html-form.js
Normal file
@@ -0,0 +1,144 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-survey-html-form
|
||||||
|
* a jspsych plugin for free html forms
|
||||||
|
*
|
||||||
|
* Jan Simson
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins['survey-html-form'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'survey-html-form',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
html: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name: 'HTML',
|
||||||
|
default: null,
|
||||||
|
description: 'HTML formatted string containing all the input elements to display. Every element has to have its own distinctive name attribute. The <form> tag must not be included and is generated by the plugin.'
|
||||||
|
},
|
||||||
|
preamble: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Preamble',
|
||||||
|
default: null,
|
||||||
|
description: 'HTML formatted string to display at the top of the page above all the questions.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
description: 'The text that appears on the button to finish the trial.'
|
||||||
|
},
|
||||||
|
dataAsArray: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOLEAN,
|
||||||
|
pretty_name: 'Data As Array',
|
||||||
|
default: false,
|
||||||
|
description: 'Retrieve the data as an array e.g. [{name: "INPUT_NAME", value: "INPUT_VALUE"}, ...] instead of an object e.g. {INPUT_NAME: INPUT_VALUE, ...}.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
// show preamble text
|
||||||
|
if(trial.preamble !== null){
|
||||||
|
html += '<div id="jspsych-survey-html-form-preamble" class="jspsych-survey-html-form-preamble">'+trial.preamble+'</div>';
|
||||||
|
}
|
||||||
|
// start form
|
||||||
|
html += '<form id="jspsych-survey-html-form">'
|
||||||
|
|
||||||
|
// add form HTML / input elements
|
||||||
|
html += trial.html;
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
html += '<input type="submit" id="jspsych-survey-html-form-next" class="jspsych-btn jspsych-survey-html-form" value="'+trial.button_label+'"></input>';
|
||||||
|
|
||||||
|
html += '</form>'
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-survey-html-form').addEventListener('submit', function(event) {
|
||||||
|
// don't submit form
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
var response_time = endTime - startTime;
|
||||||
|
|
||||||
|
var question_data = serializeArray(this);
|
||||||
|
|
||||||
|
if (!trial.dataAsArray) {
|
||||||
|
question_data = objectifyForm(question_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save data
|
||||||
|
var trialdata = {
|
||||||
|
"rt": response_time,
|
||||||
|
"responses": JSON.stringify(question_data)
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trialdata);
|
||||||
|
});
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Serialize all form data into an array
|
||||||
|
* (c) 2018 Chris Ferdinandi, MIT License, https://gomakethings.com
|
||||||
|
* @param {Node} form The form to serialize
|
||||||
|
* @return {String} The serialized form data
|
||||||
|
*/
|
||||||
|
var serializeArray = function (form) {
|
||||||
|
// Setup our serialized data
|
||||||
|
var serialized = [];
|
||||||
|
|
||||||
|
// Loop through each field in the form
|
||||||
|
for (var i = 0; i < form.elements.length; i++) {
|
||||||
|
var field = form.elements[i];
|
||||||
|
|
||||||
|
// Don't serialize fields without a name, submits, buttons, file and reset inputs, and disabled fields
|
||||||
|
if (!field.name || field.disabled || field.type === 'file' || field.type === 'reset' || field.type === 'submit' || field.type === 'button') continue;
|
||||||
|
|
||||||
|
// If a multi-select, get all selections
|
||||||
|
if (field.type === 'select-multiple') {
|
||||||
|
for (var n = 0; n < field.options.length; n++) {
|
||||||
|
if (!field.options[n].selected) continue;
|
||||||
|
serialized.push({
|
||||||
|
name: field.name,
|
||||||
|
value: field.options[n].value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert field data to a query string
|
||||||
|
else if ((field.type !== 'checkbox' && field.type !== 'radio') || field.checked) {
|
||||||
|
serialized.push({
|
||||||
|
name: field.name,
|
||||||
|
value: field.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return serialized;
|
||||||
|
};
|
||||||
|
|
||||||
|
// from https://stackoverflow.com/questions/1184624/convert-form-data-to-javascript-object-with-jquery
|
||||||
|
function objectifyForm(formArray) {//serialize data function
|
||||||
|
var returnArray = {};
|
||||||
|
for (var i = 0; i < formArray.length; i++){
|
||||||
|
returnArray[formArray[i]['name']] = formArray[i]['value'];
|
||||||
|
}
|
||||||
|
return returnArray;
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
184
PCSurvey/PCstatic/js/plugins/jspsych-survey-likert.js
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-survey-likert
|
||||||
|
* a jspsych plugin for measuring items on a likert scale
|
||||||
|
*
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins['survey-likert'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'survey-likert',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
questions: {
|
||||||
|
type: jsPsych.plugins.parameterType.COMPLEX,
|
||||||
|
array: true,
|
||||||
|
pretty_name: 'Questions',
|
||||||
|
nested: {
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Questions that are associated with the slider.'
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
array: true,
|
||||||
|
pretty_name: 'Labels',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Labels to display for individual question.'
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Required',
|
||||||
|
default: false,
|
||||||
|
description: 'Makes answering the question required.'
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Question Name',
|
||||||
|
default: '',
|
||||||
|
description: 'Controls the name of data values associated with this question'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
randomize_question_order: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Randomize Question Order',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the order of the questions will be randomized'
|
||||||
|
},
|
||||||
|
preamble: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Preamble',
|
||||||
|
default: null,
|
||||||
|
description: 'String to display at top of the page.'
|
||||||
|
},
|
||||||
|
scale_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Scale width',
|
||||||
|
default: null,
|
||||||
|
description: 'Width of the likert scales in pixels.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
description: 'Label of the button.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
if(trial.scale_width !== null){
|
||||||
|
var w = trial.scale_width + 'px';
|
||||||
|
} else {
|
||||||
|
var w = '100%';
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = "";
|
||||||
|
// inject CSS for trial
|
||||||
|
html += '<style id="jspsych-survey-likert-css">';
|
||||||
|
html += ".jspsych-survey-likert-statement { display:block; font-size: 16px; padding-top: 40px; margin-bottom:10px; }"+
|
||||||
|
".jspsych-survey-likert-opts { list-style:none; width:"+w+"; margin:auto; padding:0 0 35px; display:block; font-size: 14px; line-height:1.1em; }"+
|
||||||
|
".jspsych-survey-likert-opt-label { line-height: 1.1em; color: #444; }"+
|
||||||
|
".jspsych-survey-likert-opts:before { content: ''; position:relative; top:11px; /*left:9.5%;*/ display:block; background-color:#efefef; height:4px; width:100%; }"+
|
||||||
|
".jspsych-survey-likert-opts:last-of-type { border-bottom: 0; }"+
|
||||||
|
".jspsych-survey-likert-opts li { display:inline-block; /*width:19%;*/ text-align:center; vertical-align: top; }"+
|
||||||
|
".jspsych-survey-likert-opts li input[type=radio] { display:block; position:relative; top:0; left:50%; margin-left:-6px; }"
|
||||||
|
html += '</style>';
|
||||||
|
|
||||||
|
// show preamble text
|
||||||
|
if(trial.preamble !== null){
|
||||||
|
html += '<div id="jspsych-survey-likert-preamble" class="jspsych-survey-likert-preamble">'+trial.preamble+'</div>';
|
||||||
|
}
|
||||||
|
html += '<form id="jspsych-survey-likert-form">';
|
||||||
|
|
||||||
|
// add likert scale questions ///
|
||||||
|
// generate question order. this is randomized here as opposed to randomizing the order of trial.questions
|
||||||
|
// so that the data are always associated with the same question regardless of order
|
||||||
|
var question_order = [];
|
||||||
|
for(var i=0; i<trial.questions.length; i++){
|
||||||
|
question_order.push(i);
|
||||||
|
}
|
||||||
|
if(trial.randomize_question_order){
|
||||||
|
question_order = jsPsych.randomization.shuffle(question_order);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (var i = 0; i < trial.questions.length; i++) {
|
||||||
|
var question = trial.questions[question_order[i]];
|
||||||
|
// add question
|
||||||
|
html += '<label class="jspsych-survey-likert-statement">' + question.prompt + '</label>';
|
||||||
|
// add options
|
||||||
|
var width = 100 / question.labels.length;
|
||||||
|
var options_string = '<ul class="jspsych-survey-likert-opts" data-name="'+question.name+'" data-radio-group="Q' + question_order[i] + '">';
|
||||||
|
for (var j = 0; j < question.labels.length; j++) {
|
||||||
|
options_string += '<li style="width:' + width + '%"><input type="radio" name="Q' + question_order[i] + '" value="' + j + '"';
|
||||||
|
if(question.required){
|
||||||
|
options_string += ' required';
|
||||||
|
}
|
||||||
|
options_string += '><label class="jspsych-survey-likert-opt-label">' + question.labels[j] + '</label></li>';
|
||||||
|
}
|
||||||
|
options_string += '</ul>';
|
||||||
|
html += options_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
html += '<input type="submit" id="jspsych-survey-likert-next" class="jspsych-survey-likert jspsych-btn" value="'+trial.button_label+'"></input>';
|
||||||
|
|
||||||
|
html += '</form>'
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-survey-likert-form').addEventListener('submit', function(e){
|
||||||
|
e.preventDefault();
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
var response_time = endTime - startTime;
|
||||||
|
|
||||||
|
// create object to hold responses
|
||||||
|
var question_data = {};
|
||||||
|
var matches = display_element.querySelectorAll('#jspsych-survey-likert-form .jspsych-survey-likert-opts');
|
||||||
|
for(var index = 0; index < matches.length; index++){
|
||||||
|
var id = matches[index].dataset['radioGroup'];
|
||||||
|
var el = display_element.querySelector('input[name="' + id + '"]:checked');
|
||||||
|
if (el === null) {
|
||||||
|
var response = "";
|
||||||
|
} else {
|
||||||
|
var response = parseInt(el.value);
|
||||||
|
}
|
||||||
|
var obje = {};
|
||||||
|
if(matches[index].attributes['data-name'].value !== ''){
|
||||||
|
var name = matches[index].attributes['data-name'].value;
|
||||||
|
} else {
|
||||||
|
var name = id;
|
||||||
|
}
|
||||||
|
obje[name] = response;
|
||||||
|
Object.assign(question_data, obje);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save data
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response_time,
|
||||||
|
"responses": JSON.stringify(question_data),
|
||||||
|
"question_order": JSON.stringify(question_order)
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
});
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
199
PCSurvey/PCstatic/js/plugins/jspsych-survey-multi-choice.js
Normal file
@@ -0,0 +1,199 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-survey-multi-choice
|
||||||
|
* a jspsych plugin for multiple choice survey questions
|
||||||
|
*
|
||||||
|
* Shane Martin
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['survey-multi-choice'] = (function() {
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'survey-multi-choice',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
questions: {
|
||||||
|
type: jsPsych.plugins.parameterType.COMPLEX,
|
||||||
|
array: true,
|
||||||
|
pretty_name: 'Questions',
|
||||||
|
nested: {
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The strings that will be associated with a group of options.'
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Options',
|
||||||
|
array: true,
|
||||||
|
default: undefined,
|
||||||
|
description: 'Displays options for an individual question.'
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Required',
|
||||||
|
default: false,
|
||||||
|
description: 'Subject will be required to pick an option for each question.'
|
||||||
|
},
|
||||||
|
horizontal: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Horizontal',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, then questions are centered and options are displayed horizontally.'
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Question Name',
|
||||||
|
default: '',
|
||||||
|
description: 'Controls the name of data values associated with this question'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
randomize_question_order: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Randomize Question Order',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the order of the questions will be randomized'
|
||||||
|
},
|
||||||
|
preamble: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Preamble',
|
||||||
|
default: null,
|
||||||
|
description: 'HTML formatted string to display at the top of the page above all the questions.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
description: 'Label of the button.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
var plugin_id_name = "jspsych-survey-multi-choice";
|
||||||
|
|
||||||
|
var html = "";
|
||||||
|
|
||||||
|
// inject CSS for trial
|
||||||
|
html += '<style id="jspsych-survey-multi-choice-css">';
|
||||||
|
html += ".jspsych-survey-multi-choice-question { margin-top: 2em; margin-bottom: 2em; text-align: left; }"+
|
||||||
|
".jspsych-survey-multi-choice-text span.required {color: darkred;}"+
|
||||||
|
".jspsych-survey-multi-choice-horizontal .jspsych-survey-multi-choice-text { text-align: center;}"+
|
||||||
|
".jspsych-survey-multi-choice-option { line-height: 2; }"+
|
||||||
|
".jspsych-survey-multi-choice-horizontal .jspsych-survey-multi-choice-option { display: inline-block; margin-left: 1em; margin-right: 1em; vertical-align: top;}"+
|
||||||
|
"label.jspsych-survey-multi-choice-text input[type='radio'] {margin-right: 1em;}";
|
||||||
|
html += '</style>';
|
||||||
|
|
||||||
|
// show preamble text
|
||||||
|
if(trial.preamble !== null){
|
||||||
|
html += '<div id="jspsych-survey-multi-choice-preamble" class="jspsych-survey-multi-choice-preamble">'+trial.preamble+'</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// form element
|
||||||
|
html += '<form id="jspsych-survey-multi-choice-form">';
|
||||||
|
|
||||||
|
// generate question order. this is randomized here as opposed to randomizing the order of trial.questions
|
||||||
|
// so that the data are always associated with the same question regardless of order
|
||||||
|
var question_order = [];
|
||||||
|
for(var i=0; i<trial.questions.length; i++){
|
||||||
|
question_order.push(i);
|
||||||
|
}
|
||||||
|
if(trial.randomize_question_order){
|
||||||
|
question_order = jsPsych.randomization.shuffle(question_order);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add multiple-choice questions
|
||||||
|
for (var i = 0; i < trial.questions.length; i++) {
|
||||||
|
|
||||||
|
// get question based on question_order
|
||||||
|
var question = trial.questions[question_order[i]];
|
||||||
|
var question_id = question_order[i];
|
||||||
|
|
||||||
|
// create question container
|
||||||
|
var question_classes = ['jspsych-survey-multi-choice-question'];
|
||||||
|
if (question.horizontal) {
|
||||||
|
question_classes.push('jspsych-survey-multi-choice-horizontal');
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '<div id="jspsych-survey-multi-choice-'+question_id+'" class="'+question_classes.join(' ')+'" data-name="'+question.name+'">';
|
||||||
|
|
||||||
|
// add question text
|
||||||
|
html += '<p class="jspsych-survey-multi-choice-text survey-multi-choice">' + question.prompt
|
||||||
|
if(question.required){
|
||||||
|
html += "<span class='required'>*</span>";
|
||||||
|
}
|
||||||
|
html += '</p>';
|
||||||
|
|
||||||
|
// create option radio buttons
|
||||||
|
for (var j = 0; j < question.options.length; j++) {
|
||||||
|
// add label and question text
|
||||||
|
var option_id_name = "jspsych-survey-multi-choice-option-"+question_id+"-"+j;
|
||||||
|
var input_name = 'jspsych-survey-multi-choice-response-'+question_id;
|
||||||
|
var input_id = 'jspsych-survey-multi-choice-response-'+question_id+'-'+j;
|
||||||
|
|
||||||
|
var required_attr = question.required ? 'required' : '';
|
||||||
|
|
||||||
|
// add radio button container
|
||||||
|
html += '<div id="'+option_id_name+'" class="jspsych-survey-multi-choice-option">';
|
||||||
|
html += '<label class="jspsych-survey-multi-choice-text" for="'+input_id+'">'+question.options[j]+'</label>';
|
||||||
|
html += '<input type="radio" name="'+input_name+'" id="'+input_id+'" value="'+question.options[j]+'" '+required_attr+'></input>';
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
html += '<input type="submit" id="'+plugin_id_name+'-next" class="'+plugin_id_name+' jspsych-btn"' + (trial.button_label ? ' value="'+trial.button_label + '"': '') + '></input>';
|
||||||
|
html += '</form>';
|
||||||
|
|
||||||
|
// render
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
document.querySelector('form').addEventListener('submit', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
var response_time = endTime - startTime;
|
||||||
|
|
||||||
|
// create object to hold responses
|
||||||
|
var question_data = {};
|
||||||
|
for(var i=0; i<trial.questions.length; i++){
|
||||||
|
var match = display_element.querySelector('#jspsych-survey-multi-choice-'+i);
|
||||||
|
var id = "Q" + i;
|
||||||
|
if(match.querySelector("input[type=radio]:checked") !== null){
|
||||||
|
var val = match.querySelector("input[type=radio]:checked").value;
|
||||||
|
} else {
|
||||||
|
var val = "";
|
||||||
|
}
|
||||||
|
var obje = {};
|
||||||
|
var name = id;
|
||||||
|
if(match.attributes['data-name'].value !== ''){
|
||||||
|
name = match.attributes['data-name'].value;
|
||||||
|
}
|
||||||
|
obje[name] = val;
|
||||||
|
Object.assign(question_data, obje);
|
||||||
|
}
|
||||||
|
// save data
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response_time,
|
||||||
|
"responses": JSON.stringify(question_data),
|
||||||
|
"question_order": JSON.stringify(question_order)//,
|
||||||
|
//"reloads": reloads
|
||||||
|
};
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
});
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
223
PCSurvey/PCstatic/js/plugins/jspsych-survey-multi-select.js
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-survey-multi-select
|
||||||
|
* a jspsych plugin for multiple choice survey questions
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['survey-multi-select'] = (function() {
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'survey-multi-select',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
questions: {
|
||||||
|
type: jsPsych.plugins.parameterType.COMPLEX,
|
||||||
|
array: true,
|
||||||
|
pretty_name: 'Questions',
|
||||||
|
nested: {
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The strings that will be associated with a group of options.'
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Options',
|
||||||
|
array: true,
|
||||||
|
default: undefined,
|
||||||
|
description: 'Displays options for an individual question.'
|
||||||
|
},
|
||||||
|
horizontal: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Horizontal',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, then questions are centered and options are displayed horizontally.'
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Required',
|
||||||
|
default: false,
|
||||||
|
description: 'Subject will be required to pick at least one option for this question.'
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Question Name',
|
||||||
|
default: '',
|
||||||
|
description: 'Controls the name of data values associated with this question'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
randomize_question_order: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Randomize Question Order',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the order of the questions will be randomized'
|
||||||
|
},
|
||||||
|
preamble: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Preamble',
|
||||||
|
default: null,
|
||||||
|
description: 'HTML formatted string to display at the top of the page above all the questions.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
description: 'Label of the button.'
|
||||||
|
},
|
||||||
|
required_message: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Required message',
|
||||||
|
default: 'You must choose at least one response for this question',
|
||||||
|
description: 'Message that will be displayed if required question is not answered.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
var plugin_id_name = "jspsych-survey-multi-select";
|
||||||
|
var plugin_id_selector = '#' + plugin_id_name;
|
||||||
|
var _join = function( /*args*/ ) {
|
||||||
|
var arr = Array.prototype.slice.call(arguments, _join.length);
|
||||||
|
return arr.join(separator = '-');
|
||||||
|
}
|
||||||
|
|
||||||
|
// inject CSS for trial
|
||||||
|
var cssstr = ".jspsych-survey-multi-select-question { margin-top: 2em; margin-bottom: 2em; text-align: left; }"+
|
||||||
|
".jspsych-survey-multi-select-text span.required {color: darkred;}"+
|
||||||
|
".jspsych-survey-multi-select-horizontal .jspsych-survey-multi-select-text { text-align: center;}"+
|
||||||
|
".jspsych-survey-multi-select-option { line-height: 2; }"+
|
||||||
|
".jspsych-survey-multi-select-horizontal .jspsych-survey-multi-select-option { display: inline-block; margin-left: 1em; margin-right: 1em; vertical-align: top;}"+
|
||||||
|
"label.jspsych-survey-multi-select-text input[type='checkbox'] {margin-right: 1em;}"
|
||||||
|
display_element.innerHTML = '<style id="jspsych-survey-multi-select-css">' + cssstr + '</style>';
|
||||||
|
|
||||||
|
// form element
|
||||||
|
var trial_form_id = _join(plugin_id_name, "form");
|
||||||
|
display_element.innerHTML += '<form id="'+trial_form_id+'"></form>';
|
||||||
|
var trial_form = display_element.querySelector("#" + trial_form_id);
|
||||||
|
// show preamble text
|
||||||
|
var preamble_id_name = _join(plugin_id_name, 'preamble');
|
||||||
|
if(trial.preamble !== null){
|
||||||
|
trial_form.innerHTML += '<div id="'+preamble_id_name+'" class="'+preamble_id_name+'">'+trial.preamble+'</div>';
|
||||||
|
}
|
||||||
|
// generate question order. this is randomized here as opposed to randomizing the order of trial.questions
|
||||||
|
// so that the data are always associated with the same question regardless of order
|
||||||
|
var question_order = [];
|
||||||
|
for(var i=0; i<trial.questions.length; i++){
|
||||||
|
question_order.push(i);
|
||||||
|
}
|
||||||
|
if(trial.randomize_question_order){
|
||||||
|
question_order = jsPsych.randomization.shuffle(question_order);
|
||||||
|
}
|
||||||
|
// add multiple-select questions
|
||||||
|
for (var i = 0; i < trial.questions.length; i++) {
|
||||||
|
var question = trial.questions[question_order[i]];
|
||||||
|
var question_id = question_order[i];
|
||||||
|
// create question container
|
||||||
|
var question_classes = [_join(plugin_id_name, 'question')];
|
||||||
|
if (question.horizontal) {
|
||||||
|
question_classes.push(_join(plugin_id_name, 'horizontal'));
|
||||||
|
}
|
||||||
|
|
||||||
|
trial_form.innerHTML += '<div id="'+_join(plugin_id_name, question_id)+'" data-name="'+question.name+'" class="'+question_classes.join(' ')+'"></div>';
|
||||||
|
|
||||||
|
var question_selector = _join(plugin_id_selector, question_id);
|
||||||
|
|
||||||
|
// add question text
|
||||||
|
display_element.querySelector(question_selector).innerHTML += '<p id="survey-question" class="' + plugin_id_name + '-text survey-multi-select">' + question.prompt + '</p>';
|
||||||
|
|
||||||
|
// create option check boxes
|
||||||
|
for (var j = 0; j < question.options.length; j++) {
|
||||||
|
var option_id_name = _join(plugin_id_name, "option", question_id, j);
|
||||||
|
|
||||||
|
// add check box container
|
||||||
|
display_element.querySelector(question_selector).innerHTML += '<div id="'+option_id_name+'" class="'+_join(plugin_id_name, 'option')+'"></div>';
|
||||||
|
|
||||||
|
// add label and question text
|
||||||
|
var form = document.getElementById(option_id_name)
|
||||||
|
var input_name = _join(plugin_id_name, 'response', question_id);
|
||||||
|
var input_id = _join(plugin_id_name, 'response', question_id, j);
|
||||||
|
var label = document.createElement('label');
|
||||||
|
label.setAttribute('class', plugin_id_name+'-text');
|
||||||
|
label.innerHTML = question.options[j];
|
||||||
|
label.setAttribute('for', input_id)
|
||||||
|
|
||||||
|
// create checkboxes
|
||||||
|
var input = document.createElement('input');
|
||||||
|
input.setAttribute('type', "checkbox");
|
||||||
|
input.setAttribute('name', input_name);
|
||||||
|
input.setAttribute('id', input_id);
|
||||||
|
input.setAttribute('value', question.options[j])
|
||||||
|
form.appendChild(label)
|
||||||
|
form.insertBefore(input, label)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// add submit button
|
||||||
|
trial_form.innerHTML += '<div class="fail-message"></div>'
|
||||||
|
trial_form.innerHTML += '<button id="'+plugin_id_name+'-next" class="'+plugin_id_name+' jspsych-btn">'+trial.button_label+'</button>';
|
||||||
|
|
||||||
|
// validation check on the data first for custom validation handling
|
||||||
|
// then submit the form
|
||||||
|
display_element.querySelector('#jspsych-survey-multi-select-next').addEventListener('click', function(){
|
||||||
|
for(var i=0; i<trial.questions.length; i++){
|
||||||
|
if(trial.questions[i].required){
|
||||||
|
if(display_element.querySelector('#jspsych-survey-multi-select-'+i+' input:checked') == null){
|
||||||
|
display_element.querySelector('#jspsych-survey-multi-select-'+i+' input').setCustomValidity(trial.required_message);
|
||||||
|
} else {
|
||||||
|
display_element.querySelector('#jspsych-survey-multi-select-'+i+' input').setCustomValidity('');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
trial_form.reportValidity();
|
||||||
|
})
|
||||||
|
|
||||||
|
trial_form.addEventListener('submit', function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
var response_time = endTime - startTime;
|
||||||
|
|
||||||
|
// create object to hold responses
|
||||||
|
var question_data = {};
|
||||||
|
var has_response = [];
|
||||||
|
for(var index=0; index<trial.questions.length; index++){
|
||||||
|
var match = display_element.querySelector('#jspsych-survey-multi-select-'+index);
|
||||||
|
var val = [];
|
||||||
|
var inputboxes = match.querySelectorAll("input[type=checkbox]:checked")
|
||||||
|
for(var j=0; j<inputboxes.length; j++){
|
||||||
|
currentChecked = inputboxes[j];
|
||||||
|
val.push(currentChecked.value)
|
||||||
|
}
|
||||||
|
var id = 'Q' + index
|
||||||
|
var obje = {};
|
||||||
|
var name = id;
|
||||||
|
if(match.attributes['data-name'].value !== ''){
|
||||||
|
name = match.attributes['data-name'].value;
|
||||||
|
}
|
||||||
|
obje[name] = val;
|
||||||
|
Object.assign(question_data, obje);
|
||||||
|
if(val.length == 0){ has_response.push(false); } else { has_response.push(true); }
|
||||||
|
}
|
||||||
|
|
||||||
|
// save data
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response_time,
|
||||||
|
"responses": JSON.stringify(question_data),
|
||||||
|
"question_order": JSON.stringify(question_order)
|
||||||
|
};
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
176
PCSurvey/PCstatic/js/plugins/jspsych-survey-text.js
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-survey-text
|
||||||
|
* a jspsych plugin for free response survey questions
|
||||||
|
*
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
jsPsych.plugins['survey-text'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'survey-text',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
questions: {
|
||||||
|
type: jsPsych.plugins.parameterType.COMPLEX,
|
||||||
|
array: true,
|
||||||
|
pretty_name: 'Questions',
|
||||||
|
default: undefined,
|
||||||
|
nested: {
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Prompt for the subject to response'
|
||||||
|
},
|
||||||
|
placeholder: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Value',
|
||||||
|
default: "",
|
||||||
|
description: 'Placeholder text in the textfield.'
|
||||||
|
},
|
||||||
|
rows: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Rows',
|
||||||
|
default: 1,
|
||||||
|
description: 'The number of rows for the response text box.'
|
||||||
|
},
|
||||||
|
columns: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Columns',
|
||||||
|
default: 40,
|
||||||
|
description: 'The number of columns for the response text box.'
|
||||||
|
},
|
||||||
|
required: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Required',
|
||||||
|
default: false,
|
||||||
|
description: 'Require a response'
|
||||||
|
},
|
||||||
|
name: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Question Name',
|
||||||
|
default: '',
|
||||||
|
description: 'Controls the name of data values associated with this question'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
preamble: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Preamble',
|
||||||
|
default: null,
|
||||||
|
description: 'HTML formatted string to display at the top of the page above all the questions.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
description: 'The text that appears on the button to finish the trial.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
for (var i = 0; i < trial.questions.length; i++) {
|
||||||
|
if (typeof trial.questions[i].rows == 'undefined') {
|
||||||
|
trial.questions[i].rows = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < trial.questions.length; i++) {
|
||||||
|
if (typeof trial.questions[i].columns == 'undefined') {
|
||||||
|
trial.questions[i].columns = 40;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (var i = 0; i < trial.questions.length; i++) {
|
||||||
|
if (typeof trial.questions[i].value == 'undefined') {
|
||||||
|
trial.questions[i].value = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var html = '';
|
||||||
|
// show preamble text
|
||||||
|
if(trial.preamble !== null){
|
||||||
|
html += '<div id="jspsych-survey-text-preamble" class="jspsych-survey-text-preamble">'+trial.preamble+'</div>';
|
||||||
|
}
|
||||||
|
// start form
|
||||||
|
html += '<form id="jspsych-survey-text-form">'
|
||||||
|
|
||||||
|
// generate question order
|
||||||
|
var question_order = [];
|
||||||
|
for(var i=0; i<trial.questions.length; i++){
|
||||||
|
question_order.push(i);
|
||||||
|
}
|
||||||
|
if(trial.randomize_question_order){
|
||||||
|
question_order = jsPsych.randomization.shuffle(question_order);
|
||||||
|
}
|
||||||
|
|
||||||
|
// add questions
|
||||||
|
for (var i = 0; i < trial.questions.length; i++) {
|
||||||
|
var question = trial.questions[question_order[i]];
|
||||||
|
var question_index = question_order[i];
|
||||||
|
html += '<div id="jspsych-survey-text-'+question_index+'" class="jspsych-survey-text-question" style="margin: 2em 0em;">';
|
||||||
|
html += '<p class="jspsych-survey-text">' + question.prompt + '</p>';
|
||||||
|
var autofocus = i == 0 ? "autofocus" : "";
|
||||||
|
var req = question.required ? "required" : "";
|
||||||
|
if(question.rows == 1){
|
||||||
|
html += '<input type="text" id="input-'+question_index+'" name="#jspsych-survey-text-response-' + question_index + '" data-name="'+question.name+'" size="'+question.columns+'" '+autofocus+' '+req+' placeholder="'+question.placeholder+'"></input>';
|
||||||
|
} else {
|
||||||
|
html += '<textarea id="input-'+question_index+'" name="#jspsych-survey-text-response-' + question_index + '" data-name="'+question.name+'" cols="' + question.columns + '" rows="' + question.rows + '" '+autofocus+' '+req+' placeholder="'+question.placeholder+'"></textarea>';
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
html += '<input type="submit" id="jspsych-survey-text-next" class="jspsych-btn jspsych-survey-text" value="'+trial.button_label+'"></input>';
|
||||||
|
|
||||||
|
html += '</form>'
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
// backup in case autofocus doesn't work
|
||||||
|
display_element.querySelector('#input-'+question_order[0]).focus();
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-survey-text-form').addEventListener('submit', function(e) {
|
||||||
|
e.preventDefault();
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
var response_time = endTime - startTime;
|
||||||
|
|
||||||
|
// create object to hold responses
|
||||||
|
var question_data = {};
|
||||||
|
|
||||||
|
for(var index=0; index < trial.questions.length; index++){
|
||||||
|
var id = "Q" + index;
|
||||||
|
var q_element = document.querySelector('#jspsych-survey-text-'+index).querySelector('textarea, input');
|
||||||
|
var val = q_element.value;
|
||||||
|
var name = q_element.attributes['data-name'].value;
|
||||||
|
if(name == ''){
|
||||||
|
name = id;
|
||||||
|
}
|
||||||
|
var obje = {};
|
||||||
|
obje[name] = val;
|
||||||
|
Object.assign(question_data, obje);
|
||||||
|
}
|
||||||
|
// save data
|
||||||
|
var trialdata = {
|
||||||
|
"rt": response_time,
|
||||||
|
"responses": JSON.stringify(question_data)
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// next trial
|
||||||
|
jsPsych.finishTrial(trialdata);
|
||||||
|
});
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
279
PCSurvey/PCstatic/js/plugins/jspsych-video-button-response.js
Normal file
@@ -0,0 +1,279 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-video-button-response
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for playing a video file and getting a button response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["video-button-response"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('video-button-response', 'stimulus', 'video');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'video-button-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
sources: {
|
||||||
|
type: jsPsych.plugins.parameterType.VIDEO,
|
||||||
|
pretty_name: 'Video',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The video file to play.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'The labels for the buttons.'
|
||||||
|
},
|
||||||
|
button_html: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button HTML',
|
||||||
|
default: '<button class="jspsych-btn">%choice%</button>',
|
||||||
|
array: true,
|
||||||
|
description: 'The html of the button. Can create own style.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the buttons.'
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Width',
|
||||||
|
default: '',
|
||||||
|
description: 'The width of the video in pixels.'
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Height',
|
||||||
|
default: '',
|
||||||
|
description: 'The height of the video display in pixels.'
|
||||||
|
},
|
||||||
|
autoplay: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Autoplay',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the video will begin playing as soon as it has loaded.'
|
||||||
|
},
|
||||||
|
controls: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Controls',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the subject will be able to pause the video or move the playback to any point in the video.'
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Start',
|
||||||
|
default: null,
|
||||||
|
description: 'Time to start the clip.'
|
||||||
|
},
|
||||||
|
stop: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Stop',
|
||||||
|
default: null,
|
||||||
|
description: 'Time to stop the clip.'
|
||||||
|
},
|
||||||
|
rate: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Rate',
|
||||||
|
default: 1,
|
||||||
|
description: 'The playback rate of the video. 1 is normal, <1 is slower, >1 is faster.'
|
||||||
|
},
|
||||||
|
trial_ends_after_video: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'End trial after video finishes',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the trial will end immediately after the video finishes playing.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show trial before it ends.'
|
||||||
|
},
|
||||||
|
margin_vertical: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Margin vertical',
|
||||||
|
default: '0px',
|
||||||
|
description: 'The vertical margin of the button.'
|
||||||
|
},
|
||||||
|
margin_horizontal: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Margin horizontal',
|
||||||
|
default: '8px',
|
||||||
|
description: 'The horizontal margin of the button.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the trial will end when subject makes a response.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// setup stimulus
|
||||||
|
var video_html = '<div>'
|
||||||
|
video_html += '<video id="jspsych-video-button-response-stimulus"';
|
||||||
|
|
||||||
|
if(trial.width) {
|
||||||
|
video_html += ' width="'+trial.width+'"';
|
||||||
|
}
|
||||||
|
if(trial.height) {
|
||||||
|
video_html += ' height="'+trial.height+'"';
|
||||||
|
}
|
||||||
|
if(trial.autoplay){
|
||||||
|
video_html += " autoplay ";
|
||||||
|
}
|
||||||
|
if(trial.controls){
|
||||||
|
video_html +=" controls ";
|
||||||
|
}
|
||||||
|
video_html +=">";
|
||||||
|
|
||||||
|
var video_preload_blob = jsPsych.pluginAPI.getVideoBuffer(trial.sources[0]);
|
||||||
|
if(!video_preload_blob) {
|
||||||
|
for(var i=0; i<trial.sources.length; i++){
|
||||||
|
var file_name = trial.sources[i];
|
||||||
|
if(file_name.indexOf('?') > -1){
|
||||||
|
file_name = file_name.substring(0, file_name.indexOf('?'));
|
||||||
|
}
|
||||||
|
var type = file_name.substr(file_name.lastIndexOf('.') + 1);
|
||||||
|
type = type.toLowerCase();
|
||||||
|
video_html+='<source src="' + file_name + '" type="video/'+type+'">';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
video_html += "</video>";
|
||||||
|
video_html += "</div>";
|
||||||
|
|
||||||
|
//display buttons
|
||||||
|
var buttons = [];
|
||||||
|
if (Array.isArray(trial.button_html)) {
|
||||||
|
if (trial.button_html.length == trial.choices.length) {
|
||||||
|
buttons = trial.button_html;
|
||||||
|
} else {
|
||||||
|
console.error('Error in video-button-response plugin. The length of the button_html array does not equal the length of the choices array');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
buttons.push(trial.button_html);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
video_html += '<div id="jspsych-video-button-response-btngroup">';
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
var str = buttons[i].replace(/%choice%/g, trial.choices[i]);
|
||||||
|
video_html += '<div class="jspsych-video-button-response-button" style="display: inline-block; margin:'+trial.margin_vertical+' '+trial.margin_horizontal+'" id="jspsych-video-button-response-button-' + i +'" data-choice="'+i+'">'+str+'</div>';
|
||||||
|
}
|
||||||
|
video_html += '</div>';
|
||||||
|
|
||||||
|
// add prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
video_html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = video_html;
|
||||||
|
|
||||||
|
var start_time = performance.now();
|
||||||
|
|
||||||
|
if(video_preload_blob){
|
||||||
|
display_element.querySelector('#jspsych-video-button-response-stimulus').src = video_preload_blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-video-button-response-stimulus').onended = function(){
|
||||||
|
if(trial.trial_ends_after_video){
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.start !== null){
|
||||||
|
display_element.querySelector('#jspsych-video-button-response-stimulus').currentTime = trial.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.stop !== null){
|
||||||
|
display_element.querySelector('#jspsych-video-button-response-stimulus').addEventListener('timeupdate', function(e){
|
||||||
|
var currenttime = display_element.querySelector('#jspsych-video-button-response-stimulus').currentTime;
|
||||||
|
if(currenttime >= trial.stop){
|
||||||
|
display_element.querySelector('#jspsych-video-button-response-stimulus').pause();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-video-button-response-stimulus').playbackRate = trial.rate;
|
||||||
|
|
||||||
|
// add event listeners to buttons
|
||||||
|
for (var i = 0; i < trial.choices.length; i++) {
|
||||||
|
display_element.querySelector('#jspsych-video-button-response-button-' + i).addEventListener('click', function(e){
|
||||||
|
var choice = e.currentTarget.getAttribute('data-choice'); // don't use dataset for jsdom compatibility
|
||||||
|
after_response(choice);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
button: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
function end_trial() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"button_pressed": response.button
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
function after_response(choice) {
|
||||||
|
|
||||||
|
// measure rt
|
||||||
|
var end_time = performance.now();
|
||||||
|
var rt = end_time - start_time;
|
||||||
|
response.button = choice;
|
||||||
|
response.rt = rt;
|
||||||
|
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-video-button-response-stimulus').className += ' responded';
|
||||||
|
|
||||||
|
// disable all the buttons after a response
|
||||||
|
var btns = document.querySelectorAll('.jspsych-video-button-response-button button');
|
||||||
|
for(var i=0; i<btns.length; i++){
|
||||||
|
//btns[i].removeEventListener('click');
|
||||||
|
btns[i].setAttribute('disabled', 'disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
236
PCSurvey/PCstatic/js/plugins/jspsych-video-keyboard-response.js
Normal file
@@ -0,0 +1,236 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-video-keyboard-response
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for playing a video file and getting a keyboard response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["video-keyboard-response"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('video-keyboard-response', 'stimulus', 'video');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'video-keyboard-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
sources: {
|
||||||
|
type: jsPsych.plugins.parameterType.VIDEO,
|
||||||
|
pretty_name: 'Video',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The video file to play.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
array: true,
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
description: 'The keys the subject is allowed to press to respond to the stimulus.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Width',
|
||||||
|
default: '',
|
||||||
|
description: 'The width of the video in pixels.'
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Height',
|
||||||
|
default: '',
|
||||||
|
description: 'The height of the video display in pixels.'
|
||||||
|
},
|
||||||
|
autoplay: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Autoplay',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the video will begin playing as soon as it has loaded.'
|
||||||
|
},
|
||||||
|
controls: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Controls',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the subject will be able to pause the video or move the playback to any point in the video.'
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Start',
|
||||||
|
default: null,
|
||||||
|
description: 'Time to start the clip.'
|
||||||
|
},
|
||||||
|
stop: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Stop',
|
||||||
|
default: null,
|
||||||
|
description: 'Time to stop the clip.'
|
||||||
|
},
|
||||||
|
rate: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Rate',
|
||||||
|
default: 1,
|
||||||
|
description: 'The playback rate of the video. 1 is normal, <1 is slower, >1 is faster.'
|
||||||
|
},
|
||||||
|
trial_ends_after_video: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'End trial after video finishes',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the trial will end immediately after the video finishes playing.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show trial before it ends.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the trial will end when subject makes a response.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// setup stimulus
|
||||||
|
var video_html = '<div>'
|
||||||
|
video_html += '<video id="jspsych-video-keyboard-response-stimulus"';
|
||||||
|
|
||||||
|
if(trial.width) {
|
||||||
|
video_html += ' width="'+trial.width+'"';
|
||||||
|
}
|
||||||
|
if(trial.height) {
|
||||||
|
video_html += ' height="'+trial.height+'"';
|
||||||
|
}
|
||||||
|
if(trial.autoplay){
|
||||||
|
video_html += " autoplay ";
|
||||||
|
}
|
||||||
|
if(trial.controls){
|
||||||
|
video_html +=" controls ";
|
||||||
|
}
|
||||||
|
video_html +=">";
|
||||||
|
|
||||||
|
var video_preload_blob = jsPsych.pluginAPI.getVideoBuffer(trial.sources[0]);
|
||||||
|
if(!video_preload_blob) {
|
||||||
|
for(var i=0; i<trial.sources.length; i++){
|
||||||
|
var file_name = trial.sources[i];
|
||||||
|
if(file_name.indexOf('?') > -1){
|
||||||
|
file_name = file_name.substring(0, file_name.indexOf('?'));
|
||||||
|
}
|
||||||
|
var type = file_name.substr(file_name.lastIndexOf('.') + 1);
|
||||||
|
type = type.toLowerCase();
|
||||||
|
video_html+='<source src="' + file_name + '" type="video/'+type+'">';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
video_html += "</video>";
|
||||||
|
video_html += "</div>";
|
||||||
|
|
||||||
|
// add prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
video_html += trial.prompt;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = video_html;
|
||||||
|
|
||||||
|
if(video_preload_blob){
|
||||||
|
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').src = video_preload_blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').onended = function(){
|
||||||
|
if(trial.trial_ends_after_video){
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.start !== null){
|
||||||
|
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').currentTime = trial.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.stop !== null){
|
||||||
|
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').addEventListener('timeupdate', function(e){
|
||||||
|
var currenttime = display_element.querySelector('#jspsych-video-keyboard-response-stimulus').currentTime;
|
||||||
|
if(currenttime >= trial.stop){
|
||||||
|
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').pause();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').playbackRate = trial.rate;
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
key: null
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
function end_trial() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// kill keyboard listeners
|
||||||
|
jsPsych.pluginAPI.cancelAllKeyboardResponses();
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"key_press": response.key
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// function to handle responses by the subject
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
// after a valid response, the stimulus will have the CSS class 'responded'
|
||||||
|
// which can be used to provide visual feedback that a response was recorded
|
||||||
|
display_element.querySelector('#jspsych-video-keyboard-response-stimulus').className += ' responded';
|
||||||
|
|
||||||
|
// only record the first response
|
||||||
|
if (response.key == null) {
|
||||||
|
response = info;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (trial.response_ends_trial) {
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// start the response listener
|
||||||
|
if (trial.choices != jsPsych.NO_KEYS) {
|
||||||
|
var keyboardListener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
291
PCSurvey/PCstatic/js/plugins/jspsych-video-slider-response.js
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
/**
|
||||||
|
* jspsych-video-slider-response
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* plugin for playing a video file and getting a slider response
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["video-slider-response"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('video-slider-response', 'stimulus', 'video');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'video-slider-response',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
sources: {
|
||||||
|
type: jsPsych.plugins.parameterType.VIDEO,
|
||||||
|
pretty_name: 'Video',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The video file to play.'
|
||||||
|
},
|
||||||
|
prompt: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Prompt',
|
||||||
|
default: null,
|
||||||
|
description: 'Any content here will be displayed below the stimulus.'
|
||||||
|
},
|
||||||
|
width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Width',
|
||||||
|
default: '',
|
||||||
|
description: 'The width of the video in pixels.'
|
||||||
|
},
|
||||||
|
height: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Height',
|
||||||
|
default: '',
|
||||||
|
description: 'The height of the video display in pixels.'
|
||||||
|
},
|
||||||
|
autoplay: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Autoplay',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the video will begin playing as soon as it has loaded.'
|
||||||
|
},
|
||||||
|
controls: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Controls',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the subject will be able to pause the video or move the playback to any point in the video.'
|
||||||
|
},
|
||||||
|
start: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Start',
|
||||||
|
default: null,
|
||||||
|
description: 'Time to start the clip.'
|
||||||
|
},
|
||||||
|
stop: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Stop',
|
||||||
|
default: null,
|
||||||
|
description: 'Time to stop the clip.'
|
||||||
|
},
|
||||||
|
rate: {
|
||||||
|
type: jsPsych.plugins.parameterType.FLOAT,
|
||||||
|
pretty_name: 'Rate',
|
||||||
|
default: 1,
|
||||||
|
description: 'The playback rate of the video. 1 is normal, <1 is slower, >1 is faster.'
|
||||||
|
},
|
||||||
|
min: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Min slider',
|
||||||
|
default: 0,
|
||||||
|
description: 'Sets the minimum value of the slider.'
|
||||||
|
},
|
||||||
|
max: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Max slider',
|
||||||
|
default: 100,
|
||||||
|
description: 'Sets the maximum value of the slider',
|
||||||
|
},
|
||||||
|
slider_start: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Slider starting value',
|
||||||
|
default: 50,
|
||||||
|
description: 'Sets the starting value of the slider',
|
||||||
|
},
|
||||||
|
step: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Step',
|
||||||
|
default: 1,
|
||||||
|
description: 'Sets the step of the slider'
|
||||||
|
},
|
||||||
|
labels: {
|
||||||
|
type: jsPsych.plugins.parameterType.HTML_STRING,
|
||||||
|
pretty_name:'Labels',
|
||||||
|
default: [],
|
||||||
|
array: true,
|
||||||
|
description: 'Labels of the slider.',
|
||||||
|
},
|
||||||
|
slider_width: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name:'Slider width',
|
||||||
|
default: null,
|
||||||
|
description: 'Width of the slider in pixels.'
|
||||||
|
},
|
||||||
|
button_label: {
|
||||||
|
type: jsPsych.plugins.parameterType.STRING,
|
||||||
|
pretty_name: 'Button label',
|
||||||
|
default: 'Continue',
|
||||||
|
array: false,
|
||||||
|
description: 'Label of the button to advance.'
|
||||||
|
},
|
||||||
|
require_movement: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Require movement',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the participant will have to move the slider before continuing.'
|
||||||
|
},
|
||||||
|
trial_ends_after_video: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'End trial after video finishes',
|
||||||
|
default: false,
|
||||||
|
description: 'If true, the trial will end immediately after the video finishes playing.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'How long to show trial before it ends.'
|
||||||
|
},
|
||||||
|
response_ends_trial: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Response ends trial',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, the trial will end when subject makes a response.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// setup stimulus
|
||||||
|
var video_html = '<video id="jspsych-video-slider-response-stimulus"';
|
||||||
|
|
||||||
|
if(trial.width) {
|
||||||
|
video_html += ' width="'+trial.width+'"';
|
||||||
|
}
|
||||||
|
if(trial.height) {
|
||||||
|
video_html += ' height="'+trial.height+'"';
|
||||||
|
}
|
||||||
|
if(trial.autoplay){
|
||||||
|
video_html += " autoplay ";
|
||||||
|
}
|
||||||
|
if(trial.controls){
|
||||||
|
video_html +=" controls ";
|
||||||
|
}
|
||||||
|
video_html +=">";
|
||||||
|
|
||||||
|
var video_preload_blob = jsPsych.pluginAPI.getVideoBuffer(trial.sources[0]);
|
||||||
|
if(!video_preload_blob) {
|
||||||
|
for(var i=0; i<trial.sources.length; i++){
|
||||||
|
var file_name = trial.sources[i];
|
||||||
|
if(file_name.indexOf('?') > -1){
|
||||||
|
file_name = file_name.substring(0, file_name.indexOf('?'));
|
||||||
|
}
|
||||||
|
var type = file_name.substr(file_name.lastIndexOf('.') + 1);
|
||||||
|
type = type.toLowerCase();
|
||||||
|
video_html+='<source src="' + file_name + '" type="video/'+type+'">';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
video_html += "</video>";
|
||||||
|
|
||||||
|
var html = '<div id="jspsych-video-slider-response-wrapper" style="margin: 100px 0px;">';
|
||||||
|
html += '<div id="jspsych-video-slider-response-stimulus">' + video_html + '</div>';
|
||||||
|
html += '<div class="jspsych-video-slider-response-container" style="position:relative; margin: 0 auto 3em auto; ';
|
||||||
|
if(trial.slider_width !== null){
|
||||||
|
html += 'width:'+trial.slider_width+'px;';
|
||||||
|
}
|
||||||
|
html += '">';
|
||||||
|
html += '<input type="range" value="'+trial.start+'" min="'+trial.min+'" max="'+trial.max+'" step="'+trial.step+'" style="width: 100%;" id="jspsych-video-slider-response-response"></input>';
|
||||||
|
html += '<div>'
|
||||||
|
for(var j=0; j < trial.labels.length; j++){
|
||||||
|
var width = 100/(trial.labels.length-1);
|
||||||
|
var left_offset = (j * (100 /(trial.labels.length - 1))) - (width/2);
|
||||||
|
html += '<div style="display: inline-block; position: absolute; left:'+left_offset+'%; text-align: center; width: '+width+'%;">';
|
||||||
|
html += '<span style="text-align: center; font-size: 80%;">'+trial.labels[j]+'</span>';
|
||||||
|
html += '</div>'
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
// add prompt if there is one
|
||||||
|
if (trial.prompt !== null) {
|
||||||
|
html += '<div>'+trial.prompt+'</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// add submit button
|
||||||
|
html += '<button id="jspsych-video-slider-response-next" class="jspsych-btn" '+ (trial.require_movement ? "disabled" : "") + '>'+trial.button_label+'</button>';
|
||||||
|
|
||||||
|
display_element.innerHTML = html;
|
||||||
|
|
||||||
|
if(video_preload_blob){
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-stimulus').src = video_preload_blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-stimulus').onended = function(){
|
||||||
|
if(trial.trial_ends_after_video){
|
||||||
|
end_trial();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.start !== null){
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-stimulus').currentTime = trial.start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(trial.stop !== null){
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-stimulus').addEventListener('timeupdate', function(e){
|
||||||
|
var currenttime = display_element.querySelector('#jspsych-video-slider-response-stimulus').currentTime;
|
||||||
|
if(currenttime >= trial.stop){
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-stimulus').pause();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-stimulus').playbackRate = trial.rate;
|
||||||
|
|
||||||
|
if(trial.require_movement){
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-response').addEventListener('change', function(){
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-next').disabled = false;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
var startTime = performance.now();
|
||||||
|
|
||||||
|
// store response
|
||||||
|
var response = {
|
||||||
|
rt: null,
|
||||||
|
response: null
|
||||||
|
};
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-next').addEventListener('click', function() {
|
||||||
|
// measure response time
|
||||||
|
var endTime = performance.now();
|
||||||
|
response.rt = endTime - startTime;
|
||||||
|
response.response = display_element.querySelector('#jspsych-video-slider-response-response').value;
|
||||||
|
|
||||||
|
if(trial.response_ends_trial){
|
||||||
|
end_trial();
|
||||||
|
} else {
|
||||||
|
display_element.querySelector('#jspsych-video-slider-response-next').disabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
// function to end trial when it is time
|
||||||
|
function end_trial() {
|
||||||
|
|
||||||
|
// kill any remaining setTimeout handlers
|
||||||
|
jsPsych.pluginAPI.clearAllTimeouts();
|
||||||
|
|
||||||
|
// gather the data to store for the trial
|
||||||
|
var trial_data = {
|
||||||
|
"rt": response.rt,
|
||||||
|
"stimulus": trial.stimulus,
|
||||||
|
"response": response.response
|
||||||
|
};
|
||||||
|
|
||||||
|
// clear the display
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
// move on to the next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
// end trial if time limit is set
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
end_trial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
259
PCSurvey/PCstatic/js/plugins/jspsych-visual-search-circle.js
Normal file
@@ -0,0 +1,259 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
* jspsych-visual-search-circle
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* display a set of objects, with or without a target, equidistant from fixation
|
||||||
|
* subject responds to whether or not the target is present
|
||||||
|
*
|
||||||
|
* based on code written for psychtoolbox by Ben Motz
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
**/
|
||||||
|
|
||||||
|
jsPsych.plugins["visual-search-circle"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('visual-search-circle', 'target', 'image');
|
||||||
|
jsPsych.pluginAPI.registerPreload('visual-search-circle', 'foil', 'image');
|
||||||
|
jsPsych.pluginAPI.registerPreload('visual-search-circle', 'fixation_image', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'visual-search-circle',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
target: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Target',
|
||||||
|
default: undefined,
|
||||||
|
description: 'The image to be displayed.'
|
||||||
|
},
|
||||||
|
foil: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Foil',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Path to image file that is the foil/distractor.'
|
||||||
|
},
|
||||||
|
fixation_image: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Fixation image',
|
||||||
|
default: undefined,
|
||||||
|
description: 'Path to image file that is a fixation target.'
|
||||||
|
},
|
||||||
|
set_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Set size',
|
||||||
|
default: undefined,
|
||||||
|
description: 'How many items should be displayed?'
|
||||||
|
},
|
||||||
|
target_present: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Target present',
|
||||||
|
default: true,
|
||||||
|
description: 'Is the target present?'
|
||||||
|
},
|
||||||
|
target_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Target size',
|
||||||
|
array: true,
|
||||||
|
default: [50, 50],
|
||||||
|
description: 'Two element array indicating the height and width of the search array element images.'
|
||||||
|
},
|
||||||
|
fixation_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Fixation size',
|
||||||
|
array: true,
|
||||||
|
default: [16, 16],
|
||||||
|
description: 'Two element array indicating the height and width of the fixation image.'
|
||||||
|
},
|
||||||
|
circle_diameter: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Circle diameter',
|
||||||
|
default: 250,
|
||||||
|
description: 'The diameter of the search array circle in pixels.'
|
||||||
|
},
|
||||||
|
target_present_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Target present key',
|
||||||
|
default: 'j',
|
||||||
|
description: 'The key to press if the target is present in the search array.'
|
||||||
|
},
|
||||||
|
target_absent_key: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Target absent key',
|
||||||
|
default: 'f',
|
||||||
|
description: 'The key to press if the target is not present in the search array.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: null,
|
||||||
|
description: 'The maximum duration to wait for a response.'
|
||||||
|
},
|
||||||
|
fixation_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Fixation duration',
|
||||||
|
default: 1000,
|
||||||
|
description: 'How long to show the fixation image for before the search array (in milliseconds).'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// circle params
|
||||||
|
var diam = trial.circle_diameter; // pixels
|
||||||
|
var radi = diam / 2;
|
||||||
|
var paper_size = diam + trial.target_size[0];
|
||||||
|
|
||||||
|
// stimuli width, height
|
||||||
|
var stimh = trial.target_size[0];
|
||||||
|
var stimw = trial.target_size[1];
|
||||||
|
var hstimh = stimh / 2;
|
||||||
|
var hstimw = stimw / 2;
|
||||||
|
|
||||||
|
// fixation location
|
||||||
|
var fix_loc = [Math.floor(paper_size / 2 - trial.fixation_size[0] / 2), Math.floor(paper_size / 2 - trial.fixation_size[1] / 2)];
|
||||||
|
|
||||||
|
// possible stimulus locations on the circle
|
||||||
|
var display_locs = [];
|
||||||
|
var possible_display_locs = trial.set_size;
|
||||||
|
var random_offset = Math.floor(Math.random() * 360);
|
||||||
|
for (var i = 0; i < possible_display_locs; i++) {
|
||||||
|
display_locs.push([
|
||||||
|
Math.floor(paper_size / 2 + (cosd(random_offset + (i * (360 / possible_display_locs))) * radi) - hstimw),
|
||||||
|
Math.floor(paper_size / 2 - (sind(random_offset + (i * (360 / possible_display_locs))) * radi) - hstimh)
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// get target to draw on
|
||||||
|
display_element.innerHTML += '<div id="jspsych-visual-search-circle-container" style="position: relative; width:' + paper_size + 'px; height:' + paper_size + 'px"></div>';
|
||||||
|
var paper = display_element.querySelector("#jspsych-visual-search-circle-container");
|
||||||
|
|
||||||
|
// check distractors - array?
|
||||||
|
if(!Array.isArray(trial.foil)){
|
||||||
|
fa = [];
|
||||||
|
for(var i=0; i<trial.set_size; i++){
|
||||||
|
fa.push(trial.foil);
|
||||||
|
}
|
||||||
|
trial.foil = fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
show_fixation();
|
||||||
|
|
||||||
|
function show_fixation() {
|
||||||
|
// show fixation
|
||||||
|
//var fixation = paper.image(trial.fixation_image, fix_loc[0], fix_loc[1], trial.fixation_size[0], trial.fixation_size[1]);
|
||||||
|
paper.innerHTML += "<img src='"+trial.fixation_image+"' style='position: absolute; top:"+fix_loc[0]+"px; left:"+fix_loc[1]+"px; width:"+trial.fixation_size[0]+"px; height:"+trial.fixation_size[1]+"px;'></img>";
|
||||||
|
|
||||||
|
// wait
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
// after wait is over
|
||||||
|
show_search_array();
|
||||||
|
}, trial.fixation_duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show_search_array() {
|
||||||
|
|
||||||
|
var search_array_images = [];
|
||||||
|
|
||||||
|
var to_present = [];
|
||||||
|
if(trial.target_present){
|
||||||
|
to_present.push(trial.target);
|
||||||
|
}
|
||||||
|
to_present = to_present.concat(trial.foil);
|
||||||
|
|
||||||
|
for (var i = 0; i < display_locs.length; i++) {
|
||||||
|
|
||||||
|
paper.innerHTML += "<img src='"+to_present[i]+"' style='position: absolute; top:"+display_locs[i][0]+"px; left:"+display_locs[i][1]+"px; width:"+trial.target_size[0]+"px; height:"+trial.target_size[1]+"px;'></img>";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var trial_over = false;
|
||||||
|
|
||||||
|
var after_response = function(info) {
|
||||||
|
|
||||||
|
trial_over = true;
|
||||||
|
|
||||||
|
var correct = false;
|
||||||
|
|
||||||
|
if (jsPsych.pluginAPI.compareKeys(info.key,trial.target_present_key) && trial.target_present ||
|
||||||
|
jsPsych.pluginAPI.compareKeys(info.key,trial.target_absent_key) && !trial.target_present) {
|
||||||
|
correct = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
clear_display();
|
||||||
|
|
||||||
|
end_trial(info.rt, correct, info.key);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
var valid_keys = [trial.target_present_key, trial.target_absent_key];
|
||||||
|
|
||||||
|
key_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: valid_keys,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: false,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (trial.trial_duration !== null) {
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
|
||||||
|
if (!trial_over) {
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(key_listener);
|
||||||
|
|
||||||
|
trial_over = true;
|
||||||
|
|
||||||
|
var rt = null;
|
||||||
|
var correct = 0;
|
||||||
|
var key_press = null;
|
||||||
|
|
||||||
|
clear_display();
|
||||||
|
|
||||||
|
end_trial(rt, correct, key_press);
|
||||||
|
}
|
||||||
|
}, trial.trial_duration);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function clear_display() {
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function end_trial(rt, correct, key_press) {
|
||||||
|
|
||||||
|
// data saving
|
||||||
|
var trial_data = {
|
||||||
|
correct: correct,
|
||||||
|
rt: rt,
|
||||||
|
key_press: key_press,
|
||||||
|
locations: JSON.stringify(display_locs),
|
||||||
|
target_present: trial.target_present,
|
||||||
|
set_size: trial.set_size
|
||||||
|
};
|
||||||
|
|
||||||
|
// go to next trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// helper function for determining stimulus locations
|
||||||
|
|
||||||
|
function cosd(num) {
|
||||||
|
return Math.cos(num / 180 * Math.PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
function sind(num) {
|
||||||
|
return Math.sin(num / 180 * Math.PI);
|
||||||
|
}
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
196
PCSurvey/PCstatic/js/plugins/jspsych-vsl-animate-occlusion.js
Normal file
@@ -0,0 +1,196 @@
|
|||||||
|
/**
|
||||||
|
* jsPsych plugin for showing animations that mimic the experiment described in
|
||||||
|
*
|
||||||
|
* Fiser, J., & Aslin, R. N. (2002). Statistical learning of higher-order
|
||||||
|
* temporal structure from visual shape sequences. Journal of Experimental
|
||||||
|
* Psychology: Learning, Memory, and Cognition, 28(3), 458.
|
||||||
|
*
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins['vsl-animate-occlusion'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('vsl-animate-occlusion', 'stimuli', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'vsl-animate-occlusion',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimuli: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimuli',
|
||||||
|
default: undefined,
|
||||||
|
array: true,
|
||||||
|
description: 'A stimulus is a path to an image file.'
|
||||||
|
},
|
||||||
|
choices: {
|
||||||
|
type: jsPsych.plugins.parameterType.KEYCODE,
|
||||||
|
pretty_name: 'Choices',
|
||||||
|
array: true,
|
||||||
|
default: jsPsych.ALL_KEYS,
|
||||||
|
description: 'This array contains the keys that the subject is allowed to press in order to respond to the stimulus. '
|
||||||
|
},
|
||||||
|
canvas_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Canvas size',
|
||||||
|
array: true,
|
||||||
|
default: [400,400],
|
||||||
|
description: 'Array specifying the width and height of the area that the animation will display in.'
|
||||||
|
},
|
||||||
|
image_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Image size',
|
||||||
|
array: true,
|
||||||
|
default: [100,100],
|
||||||
|
description: 'Array specifying the width and height of the images to show.'
|
||||||
|
},
|
||||||
|
initial_direction: {
|
||||||
|
type: jsPsych.plugins.parameterType.SELECT,
|
||||||
|
pretty_name: 'Initial direction',
|
||||||
|
choices: ['left','right'],
|
||||||
|
default: 'left',
|
||||||
|
description: 'Which direction the stimulus should move first.'
|
||||||
|
},
|
||||||
|
occlude_center: {
|
||||||
|
type: jsPsych.plugins.parameterType.BOOL,
|
||||||
|
pretty_name: 'Occlude center',
|
||||||
|
default: true,
|
||||||
|
description: 'If true, display a rectangle in the center of the screen that is just wide enough to occlude the image completely as it passes behind.'
|
||||||
|
},
|
||||||
|
cycle_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Cycle duration',
|
||||||
|
default: 1000,
|
||||||
|
description: 'How long it takes for a stimulus in the sequence to make a complete cycle.'
|
||||||
|
},
|
||||||
|
pre_movement_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Pre movement duration',
|
||||||
|
default: 500,
|
||||||
|
description: 'How long to wait before the stimuli starts moving from behind the center rectangle.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// variable to keep track of timing info and responses
|
||||||
|
var start_time = 0;
|
||||||
|
var responses = [];
|
||||||
|
|
||||||
|
var directions = [
|
||||||
|
[{
|
||||||
|
params: {
|
||||||
|
x: trial.canvas_size[0] - trial.image_size[0]
|
||||||
|
},
|
||||||
|
ms: trial.cycle_duration / 2
|
||||||
|
}, {
|
||||||
|
params: {
|
||||||
|
x: trial.canvas_size[0] / 2 - trial.image_size[0] / 2
|
||||||
|
},
|
||||||
|
ms: trial.cycle_duration / 2
|
||||||
|
}],
|
||||||
|
[{
|
||||||
|
params: {
|
||||||
|
x: 0
|
||||||
|
},
|
||||||
|
ms: trial.cycle_duration / 2
|
||||||
|
}, {
|
||||||
|
params: {
|
||||||
|
x: trial.canvas_size[0] / 2 - trial.image_size[0] / 2
|
||||||
|
},
|
||||||
|
ms: trial.cycle_duration / 2
|
||||||
|
}]
|
||||||
|
];
|
||||||
|
|
||||||
|
var which_image = 0;
|
||||||
|
var next_direction = (trial.initial_direction == "right") ? 0 : 1;
|
||||||
|
|
||||||
|
function next_step() {
|
||||||
|
if (trial.stimuli.length == which_image) {
|
||||||
|
endTrial();
|
||||||
|
} else {
|
||||||
|
|
||||||
|
var d = directions[next_direction];
|
||||||
|
next_direction === 0 ? next_direction = 1 : next_direction = 0;
|
||||||
|
var i = trial.stimuli[which_image];
|
||||||
|
which_image++;
|
||||||
|
|
||||||
|
c.animate(d[0].params, d[0].ms, mina.linear, function() {
|
||||||
|
c.animate(d[1].params, d[1].ms, mina.linear, function() {
|
||||||
|
next_step();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
c.attr({
|
||||||
|
href: i
|
||||||
|
});
|
||||||
|
|
||||||
|
// start timer for this trial
|
||||||
|
start_time = performance.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
display_element.innerHTML = "<svg id='jspsych-vsl-animate-occlusion-canvas' width=" + trial.canvas_size[0] + " height=" + trial.canvas_size[1] + "></svg>";
|
||||||
|
|
||||||
|
var paper = Snap("#jspsych-vsl-animate-occlusion-canvas");
|
||||||
|
|
||||||
|
var c = paper.image(trial.stimuli[which_image], trial.canvas_size[0] / 2 - trial.image_size[0] / 2, trial.canvas_size[1] / 2 - trial.image_size[1] / 2, trial.image_size[0], trial.image_size[1]).attr({
|
||||||
|
"id": 'jspsych-vsl-animate-occlusion-moving-image'
|
||||||
|
});
|
||||||
|
|
||||||
|
display_element.querySelector('#jspsych-vsl-animate-occlusion-moving-image').removeAttribute('preserveAspectRatio');
|
||||||
|
|
||||||
|
if (trial.occlude_center) {
|
||||||
|
paper.rect((trial.canvas_size[0] / 2) - (trial.image_size[0] / 2), 0, trial.image_size[0], trial.canvas_size[1]).attr({
|
||||||
|
fill: "#000"
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// add key listener
|
||||||
|
var after_response = function(info) {
|
||||||
|
responses.push({
|
||||||
|
key: info.key,
|
||||||
|
stimulus: which_image - 1,
|
||||||
|
rt: info.rt
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
key_listener = jsPsych.pluginAPI.getKeyboardResponse({
|
||||||
|
callback_function: after_response,
|
||||||
|
valid_responses: trial.choices,
|
||||||
|
rt_method: 'performance',
|
||||||
|
persist: true,
|
||||||
|
allow_held_key: false
|
||||||
|
});
|
||||||
|
|
||||||
|
if (trial.pre_movement_duration > 0) {
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
next_step();
|
||||||
|
}, trial.pre_movement_duration);
|
||||||
|
} else {
|
||||||
|
next_step();
|
||||||
|
}
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.cancelKeyboardResponse(key_listener);
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
"stimuli": JSON.stringify(trial.stimuli),
|
||||||
|
"responses": JSON.stringify(responses)
|
||||||
|
};
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
103
PCSurvey/PCstatic/js/plugins/jspsych-vsl-grid-scene.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
/**
|
||||||
|
* jsPsych plugin for showing scenes that mimic the experiments described in
|
||||||
|
*
|
||||||
|
* Fiser, J., & Aslin, R. N. (2001). Unsupervised statistical learning of
|
||||||
|
* higher-order spatial structures from visual scenes. Psychological science,
|
||||||
|
* 12(6), 499-504.
|
||||||
|
*
|
||||||
|
* Josh de Leeuw
|
||||||
|
*
|
||||||
|
* documentation: docs.jspsych.org
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins['vsl-grid-scene'] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.registerPreload('vsl-grid-scene', 'stimuli', 'image');
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: 'vsl-grid-scene',
|
||||||
|
description: '',
|
||||||
|
parameters: {
|
||||||
|
stimuli: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
pretty_name: 'Stimuli',
|
||||||
|
array: true,
|
||||||
|
default: undefined,
|
||||||
|
description: 'An array that defines a grid.'
|
||||||
|
},
|
||||||
|
image_size: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Image size',
|
||||||
|
array: true,
|
||||||
|
default: [100,100],
|
||||||
|
description: 'Array specifying the width and height of the images to show.'
|
||||||
|
},
|
||||||
|
trial_duration: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT,
|
||||||
|
pretty_name: 'Trial duration',
|
||||||
|
default: 2000,
|
||||||
|
description: 'How long to show the stimulus for in milliseconds.'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
display_element.innerHTML = plugin.generate_stimulus(trial.stimuli, trial.image_size);
|
||||||
|
|
||||||
|
jsPsych.pluginAPI.setTimeout(function() {
|
||||||
|
endTrial();
|
||||||
|
}, trial.trial_duration);
|
||||||
|
|
||||||
|
function endTrial() {
|
||||||
|
|
||||||
|
display_element.innerHTML = '';
|
||||||
|
|
||||||
|
var trial_data = {
|
||||||
|
"stimulus": JSON.stringify(trial.stimuli)
|
||||||
|
};
|
||||||
|
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
plugin.generate_stimulus = function(pattern, image_size) {
|
||||||
|
var nrows = pattern.length;
|
||||||
|
var ncols = pattern[0].length;
|
||||||
|
|
||||||
|
// create blank element to hold code that we generate
|
||||||
|
var html = '<div id="jspsych-vsl-grid-scene-dummy" css="display: none;">';
|
||||||
|
|
||||||
|
// create table
|
||||||
|
html += '<table id="jspsych-vsl-grid-scene table" '+
|
||||||
|
'style="border-collapse: collapse; margin-left: auto; margin-right: auto;">';
|
||||||
|
|
||||||
|
for (var row = 0; row < nrows; row++) {
|
||||||
|
html += '<tr id="jspsych-vsl-grid-scene-table-row-'+row+'" css="height: '+image_size[1]+'px;">';
|
||||||
|
|
||||||
|
for (var col = 0; col < ncols; col++) {
|
||||||
|
html += '<td id="jspsych-vsl-grid-scene-table-' + row + '-' + col +'" '+
|
||||||
|
'style="padding: '+ (image_size[1] / 10) + 'px ' + (image_size[0] / 10) + 'px; border: 1px solid #555;">'+
|
||||||
|
'<div id="jspsych-vsl-grid-scene-table-cell-' + row + '-' + col + '" style="width: '+image_size[0]+'px; height: '+image_size[1]+'px;">';
|
||||||
|
if (pattern[row][col] !== 0) {
|
||||||
|
html += '<img '+
|
||||||
|
'src="'+pattern[row][col]+'" style="width: '+image_size[0]+'px; height: '+image_size[1]+'"></img>';
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
html += '</td>';
|
||||||
|
}
|
||||||
|
html += '</tr>';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</table>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
return html;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Example plugin template
|
||||||
|
*/
|
||||||
|
|
||||||
|
jsPsych.plugins["PLUGIN-NAME"] = (function() {
|
||||||
|
|
||||||
|
var plugin = {};
|
||||||
|
|
||||||
|
plugin.info = {
|
||||||
|
name: "PLUGIN-NAME",
|
||||||
|
parameters: {
|
||||||
|
parameter_name: {
|
||||||
|
type: jsPsych.plugins.parameterType.INT, // BOOL, STRING, INT, FLOAT, FUNCTION, KEYCODE, SELECT, HTML_STRING, IMAGE, AUDIO, VIDEO, OBJECT, COMPLEX
|
||||||
|
default: undefined
|
||||||
|
},
|
||||||
|
parameter_name: {
|
||||||
|
type: jsPsych.plugins.parameterType.IMAGE,
|
||||||
|
default: undefined
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugin.trial = function(display_element, trial) {
|
||||||
|
|
||||||
|
// data saving
|
||||||
|
var trial_data = {
|
||||||
|
parameter_name: 'parameter value'
|
||||||
|
};
|
||||||
|
|
||||||
|
// end trial
|
||||||
|
jsPsych.finishTrial(trial_data);
|
||||||
|
};
|
||||||
|
|
||||||
|
return plugin;
|
||||||
|
})();
|
||||||
97
PCSurvey/PCstatic/js/random_number.js
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
// function randn_bm() {
|
||||||
|
// var u = 0, v = 0;
|
||||||
|
// while(u === 0) u = Math.random(); //Converting [0,1) to (0,1)
|
||||||
|
// while(v === 0) v = Math.random();
|
||||||
|
// return (Math.sqrt( -2.0 * Math.log( u ) ) * Math.cos( 2.0 * Math.PI * v )); // still multiply with 10%
|
||||||
|
// }
|
||||||
|
|
||||||
|
var spareRandom = null;
|
||||||
|
|
||||||
|
function normalRandom()
|
||||||
|
{
|
||||||
|
var val, u, v, s, mul;
|
||||||
|
|
||||||
|
if(spareRandom !== null)
|
||||||
|
{
|
||||||
|
val = spareRandom;
|
||||||
|
spareRandom = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
u = Math.random()*2-1;
|
||||||
|
v = Math.random()*2-1;
|
||||||
|
|
||||||
|
s = u*u+v*v;
|
||||||
|
} while(s === 0 || s >= 1);
|
||||||
|
|
||||||
|
mul = Math.sqrt(-2 * Math.log(s) / s);
|
||||||
|
|
||||||
|
val = u * mul;
|
||||||
|
spareRandom = v * mul;
|
||||||
|
}
|
||||||
|
|
||||||
|
return val / 14; // 7 standard deviations on either side
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalRandomInRange(min, max)
|
||||||
|
{
|
||||||
|
var val;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
val = normalRandom();
|
||||||
|
} while(val < min || val > max);
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
function promiseGenerator({id, timeout}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (jsPsych.data.getURLVariable('debug') === 'true') {
|
||||||
|
$('.debug').html(id + ' visible after ' + timeout + 'ms.');
|
||||||
|
};
|
||||||
|
if (id === '.test') {
|
||||||
|
$(id).css({'display': 'block'});
|
||||||
|
} else {
|
||||||
|
$(id).css({'visibility': 'visible'});
|
||||||
|
};
|
||||||
|
resolve();
|
||||||
|
}, timeout);
|
||||||
|
// console.log(id + " at " + timeout);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function promiseGenerator_display({id, timeout}) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (jsPsych.data.getURLVariable('debug') === 'true') {
|
||||||
|
$('.debug').html(id + ' visible after ' + timeout + 'ms.');
|
||||||
|
};
|
||||||
|
$(id).css({'display': 'block'});
|
||||||
|
resolve();
|
||||||
|
}, timeout);
|
||||||
|
// console.log(id + " at " + timeout);
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function estBetaParams(mu, sigma) {
|
||||||
|
// console.log("b_mu = "+mu+", b_sigma = "+sigma);
|
||||||
|
variance = Math.pow(sigma, 2);
|
||||||
|
alpha = ((1 - mu) / variance - 1 / mu) * Math.pow(mu,2);
|
||||||
|
beta = alpha * (1 / mu - 1);
|
||||||
|
return {
|
||||||
|
a: alpha,
|
||||||
|
b: beta
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function betaRandomInRange(min, max) {
|
||||||
|
var betaparams = estBetaParams(0.9, 0.1);
|
||||||
|
var random_num = jStat.beta.sample(betaparams.a, betaparams.b);
|
||||||
|
// console.log("random_number -> "+random_num);
|
||||||
|
var out = min + random_num*(max-min);
|
||||||
|
// console.log("out -> "+Math.round(out)+" (min: "+min+", max: "+max+")");
|
||||||
|
return Math.round(out);
|
||||||
|
}
|
||||||
|
|
||||||
9
PCSurvey/PCstatic/js/sha256.min.js
vendored
Normal file
9
PCSurvey/PCstatic/write_data.php
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
<?php
|
||||||
|
$post_data = json_decode(file_get_contents('php://input'), true);
|
||||||
|
// the directory "data" must be writable by the server
|
||||||
|
$name = "/Data/".$post_data['filename'].".json";
|
||||||
|
//$name = "logsOutput/".$post_data['filename'].".json";
|
||||||
|
$data = $post_data['filedata'];
|
||||||
|
// write the file to disk
|
||||||
|
file_put_contents($name, $data);
|
||||||
|
?>
|
||||||
44
PCSurvey/build/potree/LICENSE
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
|
||||||
|
============
|
||||||
|
== POTREE ==
|
||||||
|
============
|
||||||
|
|
||||||
|
http://potree.org
|
||||||
|
|
||||||
|
Copyright (c) 2011-2017, Markus Schütz
|
||||||
|
All rights reserved.
|
||||||
|
|
||||||
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
modification, are permitted provided that the following conditions are met:
|
||||||
|
|
||||||
|
1. Redistributions of source code must retain the above copyright notice, this
|
||||||
|
list of conditions and the following disclaimer.
|
||||||
|
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||||
|
this list of conditions and the following disclaimer in the documentation
|
||||||
|
and/or other materials provided with the distribution.
|
||||||
|
|
||||||
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||||
|
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
|
The views and conclusions contained in the software and documentation are those
|
||||||
|
of the authors and should not be interpreted as representing official policies,
|
||||||
|
either expressed or implied, of the FreeBSD Project.
|
||||||
|
|
||||||
|
|
||||||
|
=====================
|
||||||
|
== PLASIO / LASLAZ ==
|
||||||
|
=====================
|
||||||
|
|
||||||
|
http://plas.io/
|
||||||
|
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Uday Verma, uday.karan@gmail.com
|
||||||
693
PCSurvey/build/potree/potree.css
Normal file
@@ -0,0 +1,693 @@
|
|||||||
|
|
||||||
|
/* CSS - Cascading Style Sheet */
|
||||||
|
/* Palette color codes */
|
||||||
|
/* Palette URL: http://paletton.com/#uid=13p0u0kex8W2uqu8af7lEqaulDE */
|
||||||
|
|
||||||
|
/* Feel free to copy&paste color codes to your application */
|
||||||
|
|
||||||
|
/* As hex codes */
|
||||||
|
.color-primary-0 { color: #19282C } /* Main Primary color */
|
||||||
|
.color-primary-1 { color: #7A8184 }
|
||||||
|
.color-primary-2 { color: #39474B }
|
||||||
|
.color-primary-3 { color: #2D6D82 }
|
||||||
|
.color-primary-4 { color: #108FB9 }
|
||||||
|
|
||||||
|
/* As RGBa codes */
|
||||||
|
.rgba-primary-0 { color: rgba( 25, 40, 44,1) } /* Main Primary color */
|
||||||
|
.rgba-primary-1 { color: rgba(122,129,132,1) }
|
||||||
|
.rgba-primary-2 { color: rgba( 57, 71, 75,1) }
|
||||||
|
.rgba-primary-3 { color: rgba( 45,109,130,1) }
|
||||||
|
.rgba-primary-4 { color: rgba( 16,143,185,1) }
|
||||||
|
|
||||||
|
/* Generated by Paletton.com © 2002-2014 */
|
||||||
|
/* http://paletton.com */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
:root{
|
||||||
|
|
||||||
|
--color-0: rgba( 25, 40, 44, 1);
|
||||||
|
--color-1: rgba(122,129,132, 1);
|
||||||
|
--color-2: rgba( 57, 71, 75, 1);
|
||||||
|
--color-3: rgba( 45,109,130, 1);
|
||||||
|
--color-4: rgba( 16,143,185, 1);
|
||||||
|
|
||||||
|
--bg-color: var(--color-0);
|
||||||
|
--bg-color-2: rgb(60, 80, 85);
|
||||||
|
--bg-light-color: rgba( 48, 61, 65, 1);
|
||||||
|
--bg-dark-color: rgba( 24, 31, 33, 1);
|
||||||
|
--bg-hover-color: var(--color-2);
|
||||||
|
|
||||||
|
--font-color: #9AA1A4;
|
||||||
|
--font-color-2: #ddd;
|
||||||
|
--font-color: #cccccc;
|
||||||
|
--border-color: black;
|
||||||
|
|
||||||
|
--measurement-detail-node-bg-light: var(--color-1);
|
||||||
|
--measurement-detail-node-bg-dark: var(--color-2);
|
||||||
|
--measurement-detail-area-bg-color: #eee;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#sidebar_root{
|
||||||
|
color: var(--font-color);
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
font-family: Arial,Helvetica,sans-serif;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree_failpage{
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: white;
|
||||||
|
position: absolute;
|
||||||
|
margin: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree_failpage a{
|
||||||
|
color: initial !important;
|
||||||
|
text-decoration: underline !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree_info_text{
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 1px 1px 1px black,
|
||||||
|
1px -1px 1px black,
|
||||||
|
-1px 1px 1px black,
|
||||||
|
-1px -1px 1px black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree_message{
|
||||||
|
width: 500px;
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
padding: 5px;
|
||||||
|
margin: 5px;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--font-color);
|
||||||
|
font-family: Arial;
|
||||||
|
opacity: 0.8;
|
||||||
|
border: 1px solid black;
|
||||||
|
display: flex;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree_message_error{
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
#potree_description{
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
left: 50%;
|
||||||
|
transform: translateX(-50%);
|
||||||
|
text-align: center;
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
#potree_sidebar_container{
|
||||||
|
position: absolute;
|
||||||
|
z-index: 0;
|
||||||
|
width: 350px;
|
||||||
|
height: 100%;
|
||||||
|
overflow-y: auto;
|
||||||
|
font-size: 85%;
|
||||||
|
overflow: hidden;
|
||||||
|
border-right: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree_sidebar_brand{
|
||||||
|
margin: 1px 20px;
|
||||||
|
line-height: 2em;
|
||||||
|
font-size: 100%;
|
||||||
|
font-weight: bold;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#potree_sidebar_container a{
|
||||||
|
color: #8Aa1c4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree_menu_toggle{
|
||||||
|
position: absolute;
|
||||||
|
float: left;
|
||||||
|
margin: 8px 8px;
|
||||||
|
background: none;
|
||||||
|
width: 2.5em;
|
||||||
|
height: 2.5em;
|
||||||
|
z-index: 100;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#potree_map_toggle{
|
||||||
|
position: absolute;
|
||||||
|
float: left;
|
||||||
|
margin: 8px 8px;
|
||||||
|
background: none;
|
||||||
|
width: 2.5em;
|
||||||
|
height: 2.5em;
|
||||||
|
z-index: 100;
|
||||||
|
top: calc(2.5em + 8px);
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
#potree_render_area{
|
||||||
|
position: absolute;
|
||||||
|
/*background: linear-gradient(-90deg, red, yellow);*/
|
||||||
|
top: 0px;
|
||||||
|
bottom: 0px;
|
||||||
|
left: 0px;
|
||||||
|
right: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
z-index: 1;
|
||||||
|
-webkit-transition: left .35s;
|
||||||
|
transition: left .35s;
|
||||||
|
text-align: start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree-panel {
|
||||||
|
border: 1px solid black;
|
||||||
|
border-radius: 0.4em;
|
||||||
|
padding: 0px;
|
||||||
|
background-color: var(--bg-light-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.potree-panel-heading{
|
||||||
|
background-color: var(--bg-dark-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover, a:visited, a:link, a:active{
|
||||||
|
color: #ccccff;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation{
|
||||||
|
position: absolute;
|
||||||
|
padding: 10px;
|
||||||
|
opacity: 0.5;
|
||||||
|
transform: translate(-50%, -30px);
|
||||||
|
will-change: left, top;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-titlebar{
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
border-radius: 1.5em;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.7);
|
||||||
|
font-size: 1em;
|
||||||
|
opacity: 1;
|
||||||
|
margin: auto;
|
||||||
|
display: table;
|
||||||
|
padding: 1px 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-expand{
|
||||||
|
color: white;
|
||||||
|
font-size: 0.6em;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-action-icon{
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
display: inline-block;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: 1.5em;
|
||||||
|
text-align: center;
|
||||||
|
font-family: Arial;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-action-icon:hover{
|
||||||
|
filter: drop-shadow(0px 0px 1px white);
|
||||||
|
width: 24px;
|
||||||
|
height: 24px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-item {
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
opacity: 0.5;
|
||||||
|
border-radius: 1.5em;
|
||||||
|
font-size: 1em;
|
||||||
|
line-height: 1.5em;
|
||||||
|
padding: 1px 8px 0px 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
display: flex;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-item:hover {
|
||||||
|
opacity: 1.0;
|
||||||
|
box-shadow: 0 0 5px #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-main{
|
||||||
|
display: flex;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-label{
|
||||||
|
display: inline-block;
|
||||||
|
height: 100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
z-index: 100;
|
||||||
|
vertical-align: middle;
|
||||||
|
line-height: 1.5em;
|
||||||
|
font-family: Arial;
|
||||||
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-description{
|
||||||
|
position: relative;
|
||||||
|
color: white;
|
||||||
|
background-color: black;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 5px 0px 0px 0px;
|
||||||
|
border-radius: 4px;
|
||||||
|
display: none;
|
||||||
|
max-width: 500px;
|
||||||
|
width: 500px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-description-close{
|
||||||
|
filter: invert(100%);
|
||||||
|
float: right;
|
||||||
|
opacity: 0.5;
|
||||||
|
margin: 0px 0px 8px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.annotation-description-content{
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
.annotation-icon{
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
filter: invert(100%);
|
||||||
|
margin: 2px 2px;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
canvas {
|
||||||
|
width: 100%;
|
||||||
|
height: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
body{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
position: absolute;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.axis {
|
||||||
|
font: 10px sans-serif;
|
||||||
|
color: var(--font-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.axis path{
|
||||||
|
fill: rgba(255, 255, 255, 0.5);
|
||||||
|
stroke: var(--font-color);
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
.axis line {
|
||||||
|
fill: rgba(255, 255, 255, 0.5);
|
||||||
|
stroke: var(--font-color);
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
opacity: 0.1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tick text{
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene_header{
|
||||||
|
display:flex;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scene_content{
|
||||||
|
padding: 5px 0px 5px 0px;
|
||||||
|
/*background-color: rgba(0, 0, 0, 0.4);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.measurement_content{
|
||||||
|
padding: 5px 15px 5px 10px;
|
||||||
|
/*background-color: rgba(0, 0, 0, 0.4);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.propertypanel_content{
|
||||||
|
padding: 5px 15px 5px 10px;
|
||||||
|
/*background-color: rgba(0, 0, 0, 0.4);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.measurement_value_table{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.coordinates_table_container table td {
|
||||||
|
width: 33%;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
#scene_object_properties{
|
||||||
|
margin: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.pv-panel-heading{
|
||||||
|
padding: 4px !important;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row
|
||||||
|
}
|
||||||
|
|
||||||
|
.pv-menu-list{
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 15px 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pv-menu-list > *{
|
||||||
|
margin: 4px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-slider {
|
||||||
|
margin-top: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
background-color: var(--color-1) !important;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-selectmenu-button.ui-button{
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pv-menu-list > li > .ui-slider{
|
||||||
|
background-color: var(--color-1) !important;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pv-menu-list .ui-slider{
|
||||||
|
background-color: var(--color-1) !important;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-slider-handle{
|
||||||
|
border: 1px solid black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-widget{
|
||||||
|
box-sizing:border-box
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-body > li > .ui-slider{
|
||||||
|
background-color: var(--color-1) !important;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.panel-body > div > li > .ui-slider{
|
||||||
|
background-color: var(--color-1) !important;
|
||||||
|
background: none;
|
||||||
|
border: 1px solid black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.pv-select-label{
|
||||||
|
margin: 1px;
|
||||||
|
font-size: 90%;
|
||||||
|
font-weight: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-icon:hover{
|
||||||
|
/*background-color: #09181C;*/
|
||||||
|
filter: drop-shadow(0px 0px 4px white);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-widget-content{
|
||||||
|
/*color: var(--font-color) !important;*/
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion > h3{
|
||||||
|
background-color: var(--bg-color-2) !important;
|
||||||
|
background: #f6f6f6 50% 50% repeat-x;
|
||||||
|
border: 1px solid black;
|
||||||
|
color: var(--font-color-2);
|
||||||
|
cursor: pointer;
|
||||||
|
margin: 2px 0 0 0;
|
||||||
|
padding: 4px 10px 4px 30px;
|
||||||
|
box-shadow: 0px 3px 3px #111;
|
||||||
|
text-shadow: 1px 1px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
|
||||||
|
font-size: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion > h3:hover{
|
||||||
|
filter: brightness(125%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.accordion-content{
|
||||||
|
padding: 0px 0px !important;
|
||||||
|
border: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.icon-bar{
|
||||||
|
height: 4px !important;
|
||||||
|
border: 1px solid black;
|
||||||
|
background-color: white;
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.canvas{
|
||||||
|
-webkit-transition: top .35s, left .35s, bottom .35s, right .35s, width .35s;
|
||||||
|
transition: top .35s, left .35s, bottom .35s, right .35s, width .35s;
|
||||||
|
text-align: start
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_window{
|
||||||
|
background-color: var(--bg-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_titlebar{
|
||||||
|
background-color: var(--bg-color-2);
|
||||||
|
color: var(--font-color-2);
|
||||||
|
text-shadow: 1px 1px 0 #000, -1px -1px 0 #000, 1px -1px 0 #000, -1px 1px 0 #000, 1px 1px 0 #000;
|
||||||
|
font-size: 1em;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#profile_window_title{
|
||||||
|
position: absolute;
|
||||||
|
margin: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-container-button{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.profile-button:hover{
|
||||||
|
background-color: #0000CC;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unselectable{
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.selectable{
|
||||||
|
-webkit-touch-callout: text;
|
||||||
|
-webkit-user-select: text;
|
||||||
|
-khtml-user-select: text;
|
||||||
|
-moz-user-select: text;
|
||||||
|
-ms-user-select: text;
|
||||||
|
user-select: text;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.divider {
|
||||||
|
display: block;
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-weight: bold;
|
||||||
|
font-size: 90%;
|
||||||
|
letter-spacing: 1px;
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-right: 0px;
|
||||||
|
margin-top: 1px;
|
||||||
|
margin-bottom: 1px;
|
||||||
|
padding: 1px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider > span {
|
||||||
|
position: relative;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider > span:before,
|
||||||
|
.divider > span:after {
|
||||||
|
content: "";
|
||||||
|
position: absolute;
|
||||||
|
top: 50%;
|
||||||
|
width: 9999px;
|
||||||
|
height: 1px;
|
||||||
|
background: #b2b2b2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider > span:before {
|
||||||
|
right: 100%;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.divider > span:after {
|
||||||
|
left: 100%;
|
||||||
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
.ol-dragbox {
|
||||||
|
background-color: rgba(255,255,255,0.4);
|
||||||
|
border-color: rgba(100,150,0,1);
|
||||||
|
border: 1px solid red;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-icon{
|
||||||
|
opacity: 0.5;
|
||||||
|
height: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.text-icon:hover{
|
||||||
|
opacity: 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-grid-cell{
|
||||||
|
flex-grow: 1; margin: 0px 3px 0px 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-grid-label{
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0px 3px 0px 3px;
|
||||||
|
text-align:center;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-grid-cell > input{
|
||||||
|
width: 100%
|
||||||
|
}
|
||||||
|
|
||||||
|
.invalid_value{
|
||||||
|
color: #e05e5e;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* OVERRIDES
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
.ui-spinner-input{
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jstree-themeicon-custom{
|
||||||
|
background-size: 16px !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jstree-default .jstree-clicked{
|
||||||
|
/*background-color: #ffffff !important;*/
|
||||||
|
background-color: #34494f !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jstree-default .jstree-hovered{
|
||||||
|
background-color: #34494f !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.jstree-anchor{
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-state-default{
|
||||||
|
background: #a6a9aa !important;
|
||||||
|
border: 1px solid black;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.ui-state-active{
|
||||||
|
background: #c6c9ca !important;
|
||||||
|
color: black !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cesium-viewer .cesium-viewer-cesiumWidgetContainer{
|
||||||
|
position: absolute;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
24773
PCSurvey/build/potree/potree.js
Normal file
95
PCSurvey/build/potree/profile.html
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
<div id="profile_window" style="
|
||||||
|
position: absolute;
|
||||||
|
width: 84%;
|
||||||
|
left: 15%; top: 55%; height: 44%;
|
||||||
|
margin: 5px;
|
||||||
|
border: 1px solid black;
|
||||||
|
display: none; box-sizing: border-box; z-index:10000">
|
||||||
|
|
||||||
|
<div id="profile_titlebar" class="pv-titlebar" style="display: flex; position: absolute; height: 30px; width: 100%; box-sizing: border-box;">
|
||||||
|
<span style="padding-right: 10px">
|
||||||
|
<span id="profile_window_title" data-i18n="profile.title"></span>
|
||||||
|
</span>
|
||||||
|
<span id="profileInfo" style="flex-grow: 1; flex-direction: row"> </span>
|
||||||
|
<!-- <span id="profile_toggle_size_button" class="ui-icon ui-icon-newwin profile-button"> </span> -->
|
||||||
|
<!--<span id="closeProfileContainer" class="ui-icon ui-icon-close profile-button"> </span>-->
|
||||||
|
<img id="closeProfileContainer" class="button-icon" style="width: 24px; height: 24px; margin: 4px"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div style="position: absolute; top: 30px; width: 100%; height: calc(100% - 30px); box-sizing: border-box;" class="pw_content">
|
||||||
|
|
||||||
|
<span class="pv-main-color" style="height: 100%; width: 100%; padding: 5px; display:flex; flex-direction: column; box-sizing: border-box;">
|
||||||
|
<div style=" width: 100%; color: #9d9d9d; margin: 5px; display: flex; flex-direction: row; box-sizing: border-box;">
|
||||||
|
<span data-i18n="profile.nb_points"></span>:
|
||||||
|
<span id="profile_num_points">-</span>
|
||||||
|
<!--<span id="profile_threshold" style="width: 300px">
|
||||||
|
Threshold: <span id="potree_profile_threshold_label">123</span> <div id="potree_profile_threshold_slider"></div>
|
||||||
|
</span>-->
|
||||||
|
<span style="flex-grow: 1;"></span>
|
||||||
|
<span>
|
||||||
|
|
||||||
|
<a id="potree_download_profile_ortho_link" href="#" download="profile.csv">
|
||||||
|
<img id="potree_download_csv_icon" class="text-icon"/>
|
||||||
|
<!-- <input id="potree_download_profile_ortho_button" type="button" data-i18n="[value]profile.save_ortho"> -->
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<a id="potree_download_profile_link" href="#" download="profile.las">
|
||||||
|
<img id="potree_download_las_icon" class="text-icon"/>
|
||||||
|
<!-- <input id="potree_download_profile_button" type="button" data-i18n="[value]profile.save_las"> -->
|
||||||
|
</a>
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="profile_draw_container" style="
|
||||||
|
width: 100%;
|
||||||
|
flex-grow: 1;
|
||||||
|
position: relative; height: 100%;
|
||||||
|
box-sizing: border-box; user-select: none">
|
||||||
|
<div style="
|
||||||
|
position: absolute;
|
||||||
|
left: 41px;
|
||||||
|
top: 0;
|
||||||
|
bottom: 20;
|
||||||
|
width: calc(100% - 41px);
|
||||||
|
height: calc(100% - 20px);
|
||||||
|
background-color: #000000;
|
||||||
|
"></div>
|
||||||
|
<svg id="profileSVG" style="
|
||||||
|
fill: #9d9d9d;
|
||||||
|
position: absolute;
|
||||||
|
left: 0; right: 0;
|
||||||
|
top: 0; bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
"></svg>
|
||||||
|
<div id="profileCanvasContainer" style="
|
||||||
|
position: absolute;
|
||||||
|
left: 41px;
|
||||||
|
top: 0;
|
||||||
|
bottom: 20;
|
||||||
|
width: calc(100% - 41px);
|
||||||
|
height: calc(100% - 20px);
|
||||||
|
/*background-color: #000000;*/
|
||||||
|
"></div>
|
||||||
|
|
||||||
|
<div id="profileSelectionProperties" style="
|
||||||
|
position: absolute;
|
||||||
|
left: 50px;
|
||||||
|
top: 10px;
|
||||||
|
background-color: black;
|
||||||
|
color: white;
|
||||||
|
opacity: 0.7;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid white;
|
||||||
|
user-select: auto;
|
||||||
|
">
|
||||||
|
position: asdsadf asdf<br>
|
||||||
|
rgb: 123 423 123
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
15
PCSurvey/build/potree/resources/LICENSE
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
icons/map_icon.png
|
||||||
|
from sitn PotreeViewer
|
||||||
|
http://ne.ch/sitn
|
||||||
|
https://github.com/PotreeViewer/PotreeViewer
|
||||||
|
|
||||||
|
icons/navigation_cube.svg
|
||||||
|
icons/orthographic_camera.svg
|
||||||
|
icons/perspective_camera.svg
|
||||||
|
free for commerical use without attribution
|
||||||
|
http://www.freepik.com/free-icon/package-cube-box-for-delivery_720159.htm
|
||||||
|
|
||||||
|
|
||||||
BIN
PCSurvey/build/potree/resources/icons/angle.png
Normal file
|
After Width: | Height: | Size: 602 B |
157
PCSurvey/build/potree/resources/icons/annotation.svg
Normal file
@@ -0,0 +1,157 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||||
|
sodipodi:docname="annotation.svg"
|
||||||
|
inkscape:export-filename="D:\dev\workspaces\potree\develop\resources\icons\profile.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs3799">
|
||||||
|
<inkscape:path-effect
|
||||||
|
effect="spiro"
|
||||||
|
id="path-effect4170"
|
||||||
|
is_visible="true" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3890">
|
||||||
|
<stop
|
||||||
|
id="stop3898"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#ff0000;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffff00;stop-opacity:1;"
|
||||||
|
offset="0.25"
|
||||||
|
id="stop3904" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#00ff00;stop-opacity:1;"
|
||||||
|
offset="0.5"
|
||||||
|
id="stop3902" />
|
||||||
|
<stop
|
||||||
|
id="stop3906"
|
||||||
|
offset="0.75"
|
||||||
|
style="stop-color:#00ffff;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#0000ff;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3894" />
|
||||||
|
</linearGradient>
|
||||||
|
<linearGradient
|
||||||
|
inkscape:collect="always"
|
||||||
|
xlink:href="#linearGradient3890-1"
|
||||||
|
id="linearGradient3896-3"
|
||||||
|
x1="17"
|
||||||
|
y1="5"
|
||||||
|
x2="17"
|
||||||
|
y2="26"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
spreadMethod="pad"
|
||||||
|
gradientTransform="matrix(0.91304348,0,0,0.91304348,2.5217391,2.173913)" />
|
||||||
|
<linearGradient
|
||||||
|
id="linearGradient3890-1">
|
||||||
|
<stop
|
||||||
|
id="stop3898-6"
|
||||||
|
offset="0"
|
||||||
|
style="stop-color:#ff0000;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#ffff00;stop-opacity:1;"
|
||||||
|
offset="0.25"
|
||||||
|
id="stop3904-8" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#00ff00;stop-opacity:1;"
|
||||||
|
offset="0.5"
|
||||||
|
id="stop3902-8" />
|
||||||
|
<stop
|
||||||
|
id="stop3906-2"
|
||||||
|
offset="0.75"
|
||||||
|
style="stop-color:#00ffff;stop-opacity:1;" />
|
||||||
|
<stop
|
||||||
|
style="stop-color:#0000ff;stop-opacity:1;"
|
||||||
|
offset="1"
|
||||||
|
id="stop3894-7" />
|
||||||
|
</linearGradient>
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.313708"
|
||||||
|
inkscape:cx="12.960878"
|
||||||
|
inkscape:cy="6.4904832"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1377"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:pagecheckerboard="true">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<circle
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55555558"
|
||||||
|
id="path3000"
|
||||||
|
cx="59.629543"
|
||||||
|
cy="16"
|
||||||
|
r="5" />
|
||||||
|
<circle
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3770"
|
||||||
|
cx="59.629543"
|
||||||
|
cy="16"
|
||||||
|
r="14" />
|
||||||
|
<circle
|
||||||
|
id="path3772"
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
cx="59.629543"
|
||||||
|
cy="16"
|
||||||
|
r="9" />
|
||||||
|
<path
|
||||||
|
id="path4535"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 21.96875,22.09375 C 28,12 26,1 16,1 6,1 4,12 10.03125,22.09375 15.112504,30.59761 16,30 16,30 c 0,0 0.887496,0.59761 5.96875,-7.90625 z"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="scscs" />
|
||||||
|
<circle
|
||||||
|
cy="8.498291"
|
||||||
|
cx="16"
|
||||||
|
id="circle4538"
|
||||||
|
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.55430424"
|
||||||
|
r="4.9887381" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.7 KiB |
99
PCSurvey/build/potree/resources/icons/area.svg
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||||
|
sodipodi:docname="area.svg"
|
||||||
|
inkscape:export-filename="D:\dev\workspaces\potree\develop\resources\icons\area.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs3799" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="15.836083"
|
||||||
|
inkscape:cx="-2.4229598"
|
||||||
|
inkscape:cy="11.830286"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1377"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
style="fill:#e73100;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 7.0000003,25.75 H 25 l -5,-10 6,-9.9999996 H 7.0000003 Z"
|
||||||
|
id="path3790"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cccccc" />
|
||||||
|
<circle
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-1"
|
||||||
|
cx="7"
|
||||||
|
cy="26"
|
||||||
|
r="2.7499998" />
|
||||||
|
<circle
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7"
|
||||||
|
cx="25"
|
||||||
|
cy="26"
|
||||||
|
r="2.7499998" />
|
||||||
|
<circle
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-0"
|
||||||
|
cx="7"
|
||||||
|
cy="6.000001"
|
||||||
|
r="2.7499998" />
|
||||||
|
<circle
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9"
|
||||||
|
cx="26"
|
||||||
|
cy="6.000001"
|
||||||
|
r="2.7499998" />
|
||||||
|
<circle
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-4"
|
||||||
|
cx="20"
|
||||||
|
cy="16"
|
||||||
|
r="2.7499998" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
119
PCSurvey/build/potree/resources/icons/area_backup.svg
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.5 r10040"
|
||||||
|
sodipodi:docname="area.svg"
|
||||||
|
inkscape:export-filename="D:\dev\workspaces\potree\develop\resources\icons\area.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs3799" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="2.7994505"
|
||||||
|
inkscape:cx="-38.367796"
|
||||||
|
inkscape:cy="-28.878944"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1018"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
style="fill:#ff0000;fill-opacity:1;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
d="M 7,25 25,25 20,15 26,5 7,5 z"
|
||||||
|
id="path3790"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cccccc" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:2.18181828999999980;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3807-0-1"
|
||||||
|
sodipodi:cx="11"
|
||||||
|
sodipodi:cy="22"
|
||||||
|
sodipodi:rx="6"
|
||||||
|
sodipodi:ry="6"
|
||||||
|
d="M 17,22 A 6,6 0 1 1 5,22 6,6 0 1 1 17,22 z"
|
||||||
|
transform="matrix(0.45833331,0,0,0.45833331,1.9583336,15.166667)" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:2.18181828999999980;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3807-0-7"
|
||||||
|
sodipodi:cx="11"
|
||||||
|
sodipodi:cy="22"
|
||||||
|
sodipodi:rx="6"
|
||||||
|
sodipodi:ry="6"
|
||||||
|
d="M 17,22 A 6,6 0 1 1 5,22 6,6 0 1 1 17,22 z"
|
||||||
|
transform="matrix(0.45833331,0,0,0.45833331,19.958334,15.166667)" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:2.18181828999999980;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3807-0-7-0"
|
||||||
|
sodipodi:cx="11"
|
||||||
|
sodipodi:cy="22"
|
||||||
|
sodipodi:rx="6"
|
||||||
|
sodipodi:ry="6"
|
||||||
|
d="M 17,22 A 6,6 0 1 1 5,22 6,6 0 1 1 17,22 z"
|
||||||
|
transform="matrix(0.45833331,0,0,0.45833331,1.9583336,-4.8333327)" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:2.18181828999999980;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3807-0-7-9"
|
||||||
|
sodipodi:cx="11"
|
||||||
|
sodipodi:cy="22"
|
||||||
|
sodipodi:rx="6"
|
||||||
|
sodipodi:ry="6"
|
||||||
|
d="M 17,22 A 6,6 0 1 1 5,22 6,6 0 1 1 17,22 z"
|
||||||
|
transform="matrix(0.45833331,0,0,0.45833331,20.958334,-4.8333327)" />
|
||||||
|
<path
|
||||||
|
sodipodi:type="arc"
|
||||||
|
style="fill:#00ff00;fill-opacity:1;stroke:#000000;stroke-width:2.18181828999999980;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
id="path3807-0-7-4"
|
||||||
|
sodipodi:cx="11"
|
||||||
|
sodipodi:cy="22"
|
||||||
|
sodipodi:rx="6"
|
||||||
|
sodipodi:ry="6"
|
||||||
|
d="M 17,22 A 6,6 0 1 1 5,22 6,6 0 1 1 17,22 z"
|
||||||
|
transform="matrix(0.45833331,0,0,0.45833331,14.958334,5.1666673)" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.2 KiB |
103
PCSurvey/build/potree/resources/icons/back.svg
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||||
|
sodipodi:docname="back.svg"
|
||||||
|
inkscape:export-filename="D:\dev\workspaces\potree\develop\resources\icons\area.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs3799" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="11.313709"
|
||||||
|
inkscape:cx="2.2740742"
|
||||||
|
inkscape:cy="12.023111"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1377"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
d="m 12,5 v 15 l -6,7 6,-7 h 15"
|
||||||
|
id="path891"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#44a24a;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 11.970172,4.9850856 V 20.014914 H 27 V 4.9850856 Z"
|
||||||
|
id="path843"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.31372549;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 12,5 6,12 H 21 L 27,5 Z"
|
||||||
|
id="path879"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.31372549;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 27,5 -6,7 v 15 l 6,-7 z"
|
||||||
|
id="path881"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path840"
|
||||||
|
d="M 5.9850856,11.970171 V 27 H 21.014914 V 11.970171 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:0.31372549;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
d="M 6,27 V 12 l 6,-7 h 15 v 15 l -6,7 z"
|
||||||
|
id="path885"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
d="M 6,12 H 21 L 27,5"
|
||||||
|
id="path887"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
|
d="M 21,12 V 27"
|
||||||
|
id="path889"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.9 KiB |
121
PCSurvey/build/potree/resources/icons/bottom.svg
Normal file
@@ -0,0 +1,121 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||||
|
sodipodi:docname="bottom.svg"
|
||||||
|
inkscape:export-filename="D:\dev\workspaces\potree\develop\resources\icons\area.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs3799">
|
||||||
|
<pattern
|
||||||
|
y="0"
|
||||||
|
x="0"
|
||||||
|
height="6"
|
||||||
|
width="6"
|
||||||
|
patternUnits="userSpaceOnUse"
|
||||||
|
id="EMFhbasepattern" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="4"
|
||||||
|
inkscape:cx="6.2210905"
|
||||||
|
inkscape:cy="1.1094284"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="2560"
|
||||||
|
inkscape:window-height="1377"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 12,5 v 15 l -6,7 6,-7 h 15"
|
||||||
|
id="path891"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#44a24a;fill-opacity:0;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 11.970172,4.985086 V 20.014914 H 27 V 4.985086 Z"
|
||||||
|
id="path843"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#e73100;fill-opacity:0;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 12,5 -6,7 v 15 l 6,-7 z"
|
||||||
|
id="path835"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.3137255;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="M 12,5 6,12 H 21 L 27,5 Z"
|
||||||
|
id="path879"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.31372549;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 27,5 -6,7 v 15 l 6,-7 z"
|
||||||
|
id="path881"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#2669e7;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1"
|
||||||
|
d="m 12,20 -6,7 h 15 l 6,-7 z"
|
||||||
|
id="path900"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
id="path840"
|
||||||
|
d="M 5.985086,11.970171 V 27 H 21.014914 V 11.970171 Z"
|
||||||
|
style="fill:#ffffff;fill-opacity:0.31372549;stroke:#000000;stroke-width:1;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 6,27 V 12 l 6,-7 h 15 v 15 l -6,7 z"
|
||||||
|
id="path885"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 6,12 H 21 L 27,5"
|
||||||
|
id="path887"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 21,12 V 27"
|
||||||
|
id="path889"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.5 KiB |
62
PCSurvey/build/potree/resources/icons/clip-plane-x.svg
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
version="1.1"
|
||||||
|
id="svg13"
|
||||||
|
sodipodi:docname="clip-plane-x.svg"
|
||||||
|
inkscape:version="0.92.1 r15371">
|
||||||
|
<metadata
|
||||||
|
id="metadata19">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs17" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
id="namedview15"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="23.805928"
|
||||||
|
inkscape:cx="8.4566285"
|
||||||
|
inkscape:cy="9.6500557"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg13" />
|
||||||
|
<style
|
||||||
|
type="text/css"
|
||||||
|
id="style3694">
|
||||||
|
.st0{fill:#DDDDDD;stroke:#DDDDDD;}
|
||||||
|
</style>
|
||||||
|
<path
|
||||||
|
class="st0"
|
||||||
|
d="M 11.95212,2.5364655 3.0470973,7.3937514 v 9.8206226 l 8.9050227,4.751235 8.905025,-4.751235 V 7.4463721 Z M 18.355643,7.9167192 11.956168,11.331392 5.5834101,7.8551936 11.948074,4.3830437 Z M 4.6661927,9.1990428 11.142574,12.731099 v 6.967776 L 4.6661927,16.243726 Z M 12.761668,19.698875 V 12.736766 L 19.23805,9.2808065 V 16.242917 Z M 6.2852879,11.92641 9.5234785,13.692842 v 3.307002 L 6.2852879,15.27227 Z"
|
||||||
|
id="path11"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="fill:#dddddd;stroke:#dddddd;stroke-width:0.8095476" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
61
PCSurvey/build/potree/resources/icons/clip-plane-y.svg
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
version="1.1"
|
||||||
|
id="svg35"
|
||||||
|
sodipodi:docname="clip-plane-y.svg"
|
||||||
|
inkscape:version="0.92.1 r15371">
|
||||||
|
<metadata
|
||||||
|
id="metadata41">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs39" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
id="namedview37"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="27.812867"
|
||||||
|
inkscape:cx="15.739941"
|
||||||
|
inkscape:cy="13.312402"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg35" />
|
||||||
|
<style
|
||||||
|
type="text/css"
|
||||||
|
id="style3694">
|
||||||
|
.st0{fill:#DDDDDD;stroke:#DDDDDD;}
|
||||||
|
</style>
|
||||||
|
<path
|
||||||
|
class="st0"
|
||||||
|
d="M 11.983343,3.156765 3.4754522,7.797433 v 9.382656 l 8.5078908,4.539347 8.507891,-4.539347 V 7.847707 Z M 18.10129,8.297078 11.98721,11.559467 5.8986542,8.238296 11.979476,4.9209921 Z M 5.0223414,9.522214 11.209898,12.896753 v 6.657038 L 5.0223414,16.252729 Z m 7.7344466,10.031577 v -6.651624 l 6.187557,-3.301835 v 6.651624 z m 4.640667,-7.374021 v 3.144826 l -3.093778,1.65053 v -3.144825 z"
|
||||||
|
id="path33"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="fill:#dddddd;stroke:#dddddd;stroke-width:0.77344459" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.0 KiB |
62
PCSurvey/build/potree/resources/icons/clip-plane-z.svg
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
version="1.1"
|
||||||
|
id="svg24"
|
||||||
|
sodipodi:docname="clip-plane-z.svg"
|
||||||
|
inkscape:version="0.92.1 r15371">
|
||||||
|
<metadata
|
||||||
|
id="metadata30">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<defs
|
||||||
|
id="defs28" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1"
|
||||||
|
objecttolerance="10"
|
||||||
|
gridtolerance="10"
|
||||||
|
guidetolerance="10"
|
||||||
|
inkscape:pageopacity="0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1001"
|
||||||
|
id="namedview26"
|
||||||
|
showgrid="false"
|
||||||
|
inkscape:zoom="19.666667"
|
||||||
|
inkscape:cx="18.300037"
|
||||||
|
inkscape:cy="12.90824"
|
||||||
|
inkscape:window-x="-9"
|
||||||
|
inkscape:window-y="-9"
|
||||||
|
inkscape:window-maximized="1"
|
||||||
|
inkscape:current-layer="svg24" />
|
||||||
|
<style
|
||||||
|
type="text/css"
|
||||||
|
id="style3694">
|
||||||
|
.st0{fill:#DDDDDD;stroke:#DDDDDD;}
|
||||||
|
</style>
|
||||||
|
<path
|
||||||
|
class="st0"
|
||||||
|
d="M 12.112502,2.9534908 3.4367263,7.685732 v 9.567802 l 8.6757757,4.628922 8.675775,-4.628922 V 7.7369979 Z M 18.351173,8.1952365 12.116446,11.522002 5.9077448,8.1352951 12.108559,4.7525312 Z M 5.0141399,9.4445478 11.323795,12.885676 v 6.7884 L 5.0141399,16.307875 Z M 12.901209,19.674076 V 12.891197 L 19.210863,9.5242072 V 16.307086 Z M 12.104615,6.5515715 15.043336,8.1723638 12.125121,9.7292713 9.2021733,8.1352951 Z"
|
||||||
|
id="path22"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
style="fill:#dddddd;stroke:#dddddd;stroke-width:0.78870684" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |
99
PCSurvey/build/potree/resources/icons/clip-polygon.svg
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||||
|
sodipodi:docname="clip-polygon.svg"
|
||||||
|
inkscape:export-filename="D:\dev\workspaces\potree\develop\resources\icons\area.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs3799" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="31.672167"
|
||||||
|
inkscape:cx="10.156073"
|
||||||
|
inkscape:cy="15.68414"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="3840"
|
||||||
|
inkscape:window-height="2066"
|
||||||
|
inkscape:window-x="-11"
|
||||||
|
inkscape:window-y="-11"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.39215687;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 7,25 H 25 L 20,15 26,5.0000002 H 7 Z"
|
||||||
|
id="path3790"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="cccccc" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="25.25"
|
||||||
|
cx="7"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-1" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="25.25"
|
||||||
|
cx="25"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="5.25"
|
||||||
|
cx="7"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-0" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="5.25"
|
||||||
|
cx="26"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="15.25"
|
||||||
|
cx="20"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-4" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.2 KiB |
93
PCSurvey/build/potree/resources/icons/clip-screen.svg
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||||
|
sodipodi:docname="clip-screen.svg"
|
||||||
|
inkscape:export-filename="D:\dev\workspaces\potree\develop\resources\icons\area.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs3799" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="31.672167"
|
||||||
|
inkscape:cx="2.8713385"
|
||||||
|
inkscape:cy="21.081934"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="3840"
|
||||||
|
inkscape:window-height="2066"
|
||||||
|
inkscape:window-x="-11"
|
||||||
|
inkscape:window-y="-11"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title></dc:title>
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.39215686;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 7,25.75 H 25 V 5.7500006 H 7 Z"
|
||||||
|
id="path3790"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="26"
|
||||||
|
cx="7"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-1" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="26"
|
||||||
|
cx="25"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="6"
|
||||||
|
cx="7"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-0" />
|
||||||
|
<circle
|
||||||
|
r="2.7499998"
|
||||||
|
cy="6"
|
||||||
|
cx="25"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 3.0 KiB |
130
PCSurvey/build/potree/resources/icons/clip_volume.svg
Normal file
@@ -0,0 +1,130 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.92.2 (5c3e80d, 2017-08-06)"
|
||||||
|
sodipodi:docname="clip_volume.svg"
|
||||||
|
inkscape:export-filename="D:\dev\workspaces\potree\develop\resources\icons\clip_volume.png"
|
||||||
|
inkscape:export-xdpi="90"
|
||||||
|
inkscape:export-ydpi="90">
|
||||||
|
<defs
|
||||||
|
id="defs3799">
|
||||||
|
<inkscape:perspective
|
||||||
|
sodipodi:type="inkscape:persp3d"
|
||||||
|
inkscape:vp_x="0 : 19.884691 : 1"
|
||||||
|
inkscape:vp_y="0 : 1000 : 0"
|
||||||
|
inkscape:vp_z="32 : 20.018646 : 1"
|
||||||
|
inkscape:persp3d-origin="16 : 10.666667 : 1"
|
||||||
|
id="perspective5140" />
|
||||||
|
</defs>
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="43.627907"
|
||||||
|
inkscape:cx="14.731397"
|
||||||
|
inkscape:cy="14.005208"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="3840"
|
||||||
|
inkscape:window-height="2066"
|
||||||
|
inkscape:window-x="-11"
|
||||||
|
inkscape:window-y="-11"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.39215687;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 27.999591,5.9999091 -6,5.9999999 v 16 l 6,-7 z"
|
||||||
|
id="path3776"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.39215687;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="m 5.4995909,12.499909 v 15 H 21.499591 v -15 z"
|
||||||
|
id="path4436"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:#ffffff;fill-opacity:0.39215687;stroke:#000000;stroke-width:2;stroke-linecap:butt;stroke-linejoin:bevel;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
d="M 5.9995909,11.999909 11.999591,4.9999091 h 16 l -7,6.9999999 z"
|
||||||
|
id="path3774"
|
||||||
|
inkscape:connector-curvature="0"
|
||||||
|
sodipodi:nodetypes="ccccc" />
|
||||||
|
<circle
|
||||||
|
r="2.9375"
|
||||||
|
cy="5.0624089"
|
||||||
|
cx="10.999591"
|
||||||
|
style="fill:#fffff7;fill-opacity:1;stroke:#000000;stroke-width:1.06818187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9-1" />
|
||||||
|
<circle
|
||||||
|
r="2.9375"
|
||||||
|
cy="5.0624089"
|
||||||
|
cx="26.99959"
|
||||||
|
style="fill:#fffff7;fill-opacity:1;stroke:#000000;stroke-width:1.06818187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9-1-9" />
|
||||||
|
<circle
|
||||||
|
r="2.9375"
|
||||||
|
cy="20.999907"
|
||||||
|
cx="27.06209"
|
||||||
|
style="fill:#fffff7;fill-opacity:1;stroke:#000000;stroke-width:1.06818187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9-1-8" />
|
||||||
|
<circle
|
||||||
|
r="2.9375"
|
||||||
|
cy="11.937409"
|
||||||
|
cx="5.9995909"
|
||||||
|
style="fill:#ffffff;fill-opacity:1;stroke:#000000;stroke-width:1.06818187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9-1-6" />
|
||||||
|
<circle
|
||||||
|
r="2.9375"
|
||||||
|
cy="12.062409"
|
||||||
|
cx="21.99959"
|
||||||
|
style="fill:#fffff7;fill-opacity:1;stroke:#000000;stroke-width:1.06818187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9-1-5" />
|
||||||
|
<circle
|
||||||
|
r="2.9375"
|
||||||
|
cy="27.062408"
|
||||||
|
cx="5.9995909"
|
||||||
|
style="fill:#fffff7;fill-opacity:1;stroke:#000000;stroke-width:1.06818187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9-1-0" />
|
||||||
|
<circle
|
||||||
|
r="2.9375"
|
||||||
|
cy="27.062408"
|
||||||
|
cx="21.99959"
|
||||||
|
style="fill:#fffff7;fill-opacity:1;stroke:#000000;stroke-width:1.06818187;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||||
|
id="path3807-0-7-9-1-2" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 4.8 KiB |
70
PCSurvey/build/potree/resources/icons/close.svg
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||||
|
|
||||||
|
<svg
|
||||||
|
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||||
|
xmlns:cc="http://creativecommons.org/ns#"
|
||||||
|
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||||
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||||
|
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||||
|
width="32px"
|
||||||
|
height="32px"
|
||||||
|
id="svg3797"
|
||||||
|
version="1.1"
|
||||||
|
inkscape:version="0.48.5 r10040"
|
||||||
|
sodipodi:docname="close.svg">
|
||||||
|
<defs
|
||||||
|
id="defs3799" />
|
||||||
|
<sodipodi:namedview
|
||||||
|
id="base"
|
||||||
|
pagecolor="#ffffff"
|
||||||
|
bordercolor="#666666"
|
||||||
|
borderopacity="1.0"
|
||||||
|
inkscape:pageopacity="0.0"
|
||||||
|
inkscape:pageshadow="2"
|
||||||
|
inkscape:zoom="22.395604"
|
||||||
|
inkscape:cx="9.4629706"
|
||||||
|
inkscape:cy="16.706715"
|
||||||
|
inkscape:current-layer="layer1"
|
||||||
|
showgrid="true"
|
||||||
|
inkscape:grid-bbox="true"
|
||||||
|
inkscape:document-units="px"
|
||||||
|
inkscape:window-width="1920"
|
||||||
|
inkscape:window-height="1018"
|
||||||
|
inkscape:window-x="-8"
|
||||||
|
inkscape:window-y="-8"
|
||||||
|
inkscape:window-maximized="1">
|
||||||
|
<inkscape:grid
|
||||||
|
type="xygrid"
|
||||||
|
id="grid3805" />
|
||||||
|
</sodipodi:namedview>
|
||||||
|
<metadata
|
||||||
|
id="metadata3802">
|
||||||
|
<rdf:RDF>
|
||||||
|
<cc:Work
|
||||||
|
rdf:about="">
|
||||||
|
<dc:format>image/svg+xml</dc:format>
|
||||||
|
<dc:type
|
||||||
|
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||||
|
<dc:title />
|
||||||
|
</cc:Work>
|
||||||
|
</rdf:RDF>
|
||||||
|
</metadata>
|
||||||
|
<g
|
||||||
|
id="layer1"
|
||||||
|
inkscape:label="Layer 1"
|
||||||
|
inkscape:groupmode="layer">
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
d="M 7,25 25,7"
|
||||||
|
id="path2986"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
<path
|
||||||
|
style="fill:none;stroke:#000000;stroke-width:8;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
|
||||||
|
d="M 7,7 25,25"
|
||||||
|
id="path2988"
|
||||||
|
inkscape:connector-curvature="0" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 2.1 KiB |