Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 115 additions & 51 deletions www/experiments.php
Original file line number Diff line number Diff line change
Expand Up @@ -554,99 +554,163 @@ function refreshExperimentFormState(){
echo "$id";
} ?>';
if(priorState && currentTestID && priorState.indexOf("resubmit="+ currentTestID) > -1 ){
var form = $("form.experiments_grades");
form[0].reset();
var form = document.querySelector("form.experiments_grades");
form.reset();
var pairs = priorState.split("&");

pairs.forEach(pair => {
var keyval = pair.split("=");
let keyval = pair.split("=").map(decodeURIComponent);
if( keyval[0] !== 'runs' ){
var input = form.find("[name='" + keyval[0] + "']");

if( input.length ){
if( input.filter("[type=checkbox],[type=radio]").length ){
input = input.filter( "[value='"+ keyval[1] +"']" ).attr("checked", true);
} else if(input.filter("[type=text]").length ) {
input.val(keyval[1]);
var checks = form.querySelectorAll("[type=checkbox][name='" + keyval[0] + "']");
if( checks.length ){
checks.forEach(input => {
if( input.value === keyval[1] ){
input.checked = true;
}
});
}
var input = form.querySelector("textarea[name='" + keyval[0] + "']:not([data-hydrated='true']),input[type='text'][name='" + keyval[0] + "']:not([data-hydrated='true'])");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if these queries will be more readable as templates

form.querySelector(`textarea[name='${keyval[0]}']:not([data-...`);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hmm yeah maybe? I left them for now... we could revisit


if( !input ){
let priors = form.querySelectorAll("textarea[name='" + keyval[0] + "'],input[type='text'][name='" + keyval[0] + "']");
if( priors.length ){
var lastPrior = priors[priors.length - 1];
if( lastPrior && lastPrior.parentElement.classList.contains('experiment_pair_value-add') ){
var newInput = lastPrior.parentElement.cloneNode(true);
lastPrior.parentElement.after(newInput);
input = newInput.querySelector('input[type=text],textarea');
}
}
}
if( input && !(keyval[1] === 'on' && form.querySelectorAll("[type=checkbox][name='" + keyval[0] + "']")) ){
input.value = keyval[1];
input.setAttribute('data-hydrated', 'true');
}

}
});

}
}

// try and set the form state to localstorage
let form = document.querySelector("form.experiments_grades");

function saveExperimentFormState(){
localStorage.setItem("experimentForm", decodeURIComponent($("form.experiments_grades").serialize()) );
let formData = new FormData(form);
// encode values before they get poorly encoded for us by the browser (spaces turn to + etc)
let formString = "";
for (const pair of formData.entries()) {
formString += `${encodeURIComponent(pair[0])}=${encodeURIComponent(pair[1])}&`;
}


localStorage.setItem("experimentForm", formString);
}

$("form.experiments_grades").on("change submit", saveExperimentFormState );
form.addEventListener("change", saveExperimentFormState );
form.addEventListener("submit", saveExperimentFormState );



var expsActive;
function updateCount(){
expsActive = $(".experiment_description_go label:not(.experiment_pair_value-visible) input:checked");
expsActive = document.querySelectorAll(".experiment_description_go label:not(.experiment_pair_value-visible) input:checked");
if(expsActive.length > 0){
expsActive.parents("details").each(function(){
this.open = true;

// open parent details of active experiments
expsActive.forEach(elem => {
while( elem.closest('details:not([open])') ){
elem.closest('details:not([open])').open = true;
}
});
$(".experiments_foot").addClass("experiments_foot-stick");
$(".exps-cta").text("Ready to go?");
let expsActiveInfo = $('<details><summary><strong>' + expsActive.length + '</strong> experiment'+ (expsActive.length>1?'s':'') +' selected.</summary></details>');

let expsActiveLinks = $('<ol></ol>');
expsActive.each(function(){
let exp = $(this);
let newLi = $('<li><button type="button"></button></li>' );
newLi.find('button')
.html(exp.closest(".experiment_description").find('h5').text())
.on("click",function(){
exp.closest(".experiment_description")[0].scrollIntoView({behavior: 'smooth'});
});


document.querySelector(".experiments_foot").classList.add("experiments_foot-stick");
let cta = document.querySelector(".exps-cta");
if( cta ){
cta.innerText = "Ready to go?";
}
let expsActiveInfo = document.createElement('details');
expsActiveInfo.innerHTML = '<summary><strong>' + expsActive.length + '</strong> experiment'+ (expsActive.length>1?'s':'') +' selected.</summary>';

let expsActiveLinksContain = document.createElement('div');
expsActiveLinksContain.innerHTML = '<p class="experiments_jump">Scroll to:</p>';
let expsActiveLinks = document.createElement('ol');

expsActive.forEach(exp => {
let newLi = document.createElement('li');
let expDesc = exp.closest(".experiment_description");
newLi.innerHTML = '<button type="button">'+ expDesc.querySelector('h5').innerText +'</button>';
expsActiveLinks.append(newLi);
newLi.addEventListener("click", () => {
expDesc.scrollIntoView({behavior: 'smooth'});
});

});

expsActiveLinks.appendTo(expsActiveInfo).wrap("<div></div>").before('<p class="experiments_jump">Scroll to:</p>');
expsActiveLinksContain.append(expsActiveLinks);
expsActiveInfo.append(expsActiveLinksContain);

$(".exps-active").empty().append(expsActiveInfo);
$("[type=submit]").removeAttr("aria-disabled");
} else{
$(".experiments_foot").removeClass("experiments_foot-stick");
$(".exps-active").html('');
$(".exps-cta").text("Select one or more experiments...");

$("[type=submit]").attr("aria-disabled", true);
document.querySelector(".exps-active").innerHTML = '';
document.querySelector(".exps-active").append(expsActiveInfo);
form.querySelector("[type=submit]").removeAttribute("aria-disabled");
} else{
form.querySelector(".experiments_foot").classList.remove("experiments_foot-stick");
let expsActive = document.querySelector(".exps-cta");
if( expsActive ){
expsActive.innerText = "";
}
let cta = document.querySelector(".exps-cta");
if( cta ){
cta.innerText = "Select one or more experiments...";
}

document.querySelector("[type=submit]").setAttribute("aria-disabled", true);

}
}

function updateTestRunTotal(){
let fvonly = $('[name=fvonly]').val();
let fvonly = document.querySelector('[name=fvonly]').value;
let multiplier = fvonly === "1" ? 2 : 4;
let totalRuns = $('[name=runs]').val() * multiplier;
$('.exps-runcount-total').text("(" + totalRuns + " total runs)" );
let totalRuns = parseFloat(document.querySelector('[name=runs]').value) * multiplier;
document.querySelector('.exps-runcount-total').innerText = "(" + totalRuns + " total runs)";
}

$('[name=runs]').on("input", updateTestRunTotal);

document.querySelector('[name=runs]').addEventListener("input", updateTestRunTotal);
updateTestRunTotal();




// try and restore state at load
refreshExperimentFormState();
updateCount();
$("form.experiments_grades").on("change input submit", updateCount );
form.addEventListener("input", updateCount );
form.addEventListener("submit", updateCount );

// add add buttons
$(".experiment_pair_value-add").after("<button type='button' class='experiment_pair_value_addbtn'>Add more</button>").next().on("click", function(){ $(this).before($(this).prev().clone());});
document.querySelectorAll(".experiment_pair_value-add:last-child").forEach(pair => {
let btn = document.createElement('button');
btn.type = "button";
btn.className = "experiment_pair_value_addbtn";
btn.innerText = "Add more";
pair.after(btn);
btn.addEventListener("click", () => {
let newpair = pair.cloneNode(true);
pair.after(newpair);
});
});

$('<button type="button">Expand All</button>')
.on('click', function(){
$(this).closest(".util_overflow_more").addClass("util_overflow_more-expanded");
})
.appendTo(".util_overflow_more");
let overflowSections = document.querySelectorAll(".util_overflow_more");
overflowSections.forEach(section => {
let btn = document.createElement('button');
btn.type = "button";
btn.innerText = "Expand All";
section.append(btn);
btn.addEventListener("click", () => {
this.closest(".util_overflow_more").className.add("util_overflow_more-expanded");
});
});

// select all
document.querySelectorAll('.experiment_assets').forEach(details => {
Expand Down