0

I wrote some JavaScript to intercept form data on a submit event, and to build an array of objects from the several <select> fields, processing one field per iteration of a loop that grabs the field value and pushes it into an array. Each iteration should construct and push() one object into the array unitl all form fields have been processed.

Instead, on this test page on my website, I get the complete array of all the objects from all the form fields on the first iteration prior to the first push. The array stays exactly like that on each subsequent iteration despite the recurring pushes.

The js is:

function buildClasses(formData) {
  var timeslots = ['0830', '0900', '1030', '1245', '1415', '1545'];
  var classrooms = ['chapel', 'A', 'B', 'C', 'D', 'E', 'F', 'I'];
  var classes = [];
  var ts = '';
  var rm = '';
  var startIndex = 3; 

  if(formData[startIndex].value == 'attend') { 
    formData[startIndex].value = 'chapel'; 
  }
    else {formData[startIndex].value = 'unsure';} 
  for(var i = startIndex; i < formData.length; i++) {
    if(formData[i].value == 'unsure') {}
      else {
             ts = timeslots[i - startIndex];
             rm = formDataArr[i].value; 
             classes.push(
                            {
                               timeslot: ts,
                               room: rm
                            }
                         );  
           }  //  end else/if
    }  //  end for
  return classSelections;
}  //  end def fn buildClasses

formData is:

3: Object {name: "select-yui_3_nnn ... nnn-field", value: "unsure"}
4: Object {name: "select-yui_3_nnn ... nnn-field", value: "A"}
5: Object {name: "select-yui_3_nnn ... nnn-field", value: "B"}
6: Object {name: "select-yui_3_nnn ... nnn-field", value: "A"}
7: Object {name: "select-yui_3_nnn ... nnn-field", value: "unsure"}
8: Object {name: "select-yui_3_nnn ... nnn-field", value: "C"}
length: 9

The scheme in buildClasses() is to cycle through the form fields beginning at index 3, to ignore the "unsure" values, and to build classes using the non-unsure values, one each per iteration of the loop.

Investigating with console.log()on the test page, I determined that, in the first iteration, prior to the first push(), classes is:

1: Object {timeslot: "0900", room: "A"}
2: Object {timesolt: "1030", room: "B"}
3: Object {timeslot: "1245", room: "A"}
5: Object {timeslot: "1545:, room: "C"}
length: 4

It's incredible, I know. But before composing this question, I tested it on the test page dozens of times, always with that result.

The whole thing is live at the page Test Conference Registration 2019. I littered the code with console logs, so that one can see what is produced on each iteration. Test it as you will. (It connects to and updates a live AWS table, so you will also get in the console the AWS return information.)

The function looks simple and straightforward. Yet it produces vexing results on my website. The site is built on the Squarespace platform using one of its 'form blocks' to construct the form.

I built the snippet below using the same code. It functions correctly, just as expected.

So, there must be something about the way the Squarespace form block works that is causing the entire array to appear even prior to the first push. I'm hoping that someone here may have experience with Squarespace and may be able to shed some light.

Thanks for reading this and for any effort toward answers.

Update:

Since first posting this question, I've come to understand the problem better and differently. I've completely revised it, changed the issue, and published it under a new title. I hope I've clarified things and posted a better question than originally.

Thanks to everyone who responded to the first version of this question.

/*  new schema w/o comments  */

$(document).ready(function() {
  init();
}); // end doc.ready

function init() {
  document.addEventListener("submit", processFormData);
} // end def fn init

function processFormData(event) {
  event.preventDefault();
  var formData = $('form').serializeArray();
  classes = buildClasses(formData);
} //  end def fn processFormData

function buildClasses(fd) {
  var timeslots = ['0830', '0900', '1030', '1245', '1415', '1545'];
  var classrooms = ['chapel', 'A', 'B', 'C', 'D', 'E', 'F', 'I'];
  var ts = '';
  var rm = '';
  var startIndex = 3;
  var classes = [];

  console.log('classes post-initialization : ', classes);

  if (fd[startIndex].value == 'attend') {
    fd[startIndex].value = 'chapel';
  } else {
    fd[startIndex].value = 'unsure';
  }
  for (var i = startIndex; i < fd.length; i++) {
    if (fd[i].value == 'unsure') {} else {
      ts = timeslots[i - startIndex];
      rm = fd[i].value;

      console.log('fd[i].value : ', i, fd[i].value);
      console.log('classes pre-push', classes);

      classes.push({
        timeslot: ts,
        room: rm
      });

      console.log('classes post-push : ', classes);

    } //  end else/if
  } //  end for
  return classes;
} //  end def fn buildClassSelections
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<form action="" method="post">
  <div>
    <label>First Name
    <input type="text" name="fname" size="25">
  </label>
  </div>
  <div>
    <label>Last Name
    <input type="text" name="lname" size="25">
  </label>
  </div>
  <div>
    <label>email address
    <input type="email" name="email" size="25">
  </label>
  </div>
  <div>
    <label>08:30 Keynote Speaker
    <select name="select">
      <option value="" name="defaultOptionUnsure">unsure</option>
      <option value="attend" name="">attend</option>
      <option value="not attend">not attend</option>
    </select>
  </label>
    <label>09:00 Classes
    <select name="select">
      <option value="">unsure</option>
      <option value="class room A">room A</option>
      <option value="class room B">room B</option>
    </select>
    </label>
    <label>10:30 Classes
    <select name="select">
      <option value="">unsure</option>
      <option value="class room A">room A</option>
      <option value="class room B">room B</option>
    </select>
  </label>
  </div>
  <div>
    <input type="submit" value="submit form">
  </div>
</form>
alxfyv
  • 389
  • 1
  • 6
  • 18
  • Please update your question with a sample section of the `formDataArr` – Charlie Jun 21 '19 at 02:33
  • Actually your code are too dirty and hard to read. Someone should spend too much time to understand what were you trying to do, and then help you. I would suggest you reindent with 2 spaces your code, remove unnecessary comments and console.logs. And try replicate your problem only with part of code connected to your problem – AidOnline01 Jun 21 '19 at 02:34
  • please show us html form. PS: you problem may be there, you use a global, but your code i so dirty, i'm not shure – Mister Jojo Jun 21 '19 at 02:55
  • @CharlieH I updated the question with the requested data plus the content of the classSelections variable (the array of objects) after the first iteration. I'm never sure how much to put in or leave out. Guess I opted the wrong way. Thanks for your kind consideration and time. – alxfyv Jun 21 '19 at 05:14
  • @AidOnline01 I believe you refer to the pen. I stripped the js of all the comments and the console log commands. I don't know that the pen will be of much assistance, though, as it's still throwing the 502, Bad Gateway error. I've asked Codepen support for some help. I also updated the question to provide the info Charlie H. asked for. Thanks for your interest. How else might I help? – alxfyv Jun 21 '19 at 05:35
  • @MisterJojo I believe you refer to the pen's code. I stripped it of the comments and console log commands. You should find it 'clean' now. As to the HTML, the code is simple. I don't believe the error is there. I don't believe I use a global variable. I believe I defined all the variables with a var instruction. Thanks for considering my problem. – alxfyv Jun 21 '19 at 05:41
  • FormData is not like jQuery serializeArray, they are more, and I don't see the utility if you just want to build a js object to store in a arrow. – Mister Jojo Jun 21 '19 at 14:46

2 Answers2

1

It is hard to tell, but I would bet that this line:

if(formDataArr[i] == 'unsure') {} // skip ‘unsure’

should read:

if(formDataArr[i].value == 'unsure') {} // skip ‘unsure’

Having said that, you should probably test a function like this in isolation, easily done in a node.js REPL. But nothing would beat a full blown mocha/chai test environment.

DDupont
  • 441
  • 2
  • 11
  • Of course, it should (read as you say). I knew I'd be embarrassed. Color me flushed. That takes care of the problem with the' unsure' responses, but, I'm still getting the complete classSelecttions array on the first iteration. (Sans the 'unsure' values. Thank you.) I'm a novice HTML, CSS, JavaScript, and jQuery autodidact. As of yet, node.js is beyond me. I don't know what REPL is. And, mocha/chai is something I order from the barista. I've a long way to go, but you chart my future course for me. Thanks again for spotting that error. If you can help with the rest, please do. – alxfyv Jun 21 '19 at 05:58
  • I am not clear on "the first iteration". I only see a single loop in your buildClassSelections function and it definitely only adds one object per loop iteration. FYI: There is no need to initialize your array with an empty object, only to remove it later. Just initialize it as an empty array: ```var classSelections = [];``` – DDupont Jun 23 '19 at 04:06
  • I meant the first time through the loop. I updated the question to better explain the issue. If you will, please read it. Thanks for the tip on initializing the array without the {} empty object. I've incorporated that. – alxfyv Jun 23 '19 at 19:50
1

for a start

const myForm    = document.querySelector("#My-Form")
,     FormNames = Array.from(myForm.elements).reduce((a,n)=>{ if (n.name ) a.push(n.name);  return a }, [])
;
var ResultArray = []

myForm.onsubmit = e =>{
  e.preventDefault()

  let info = {}
  for (let elm of FormNames) {
    info[elm] = myForm[elm].value
  }

  ResultArray.push(info)

  myForm.reset()
  console.clear()
  console.log('ResultArray = ', ResultArray )
}
body { font-family: Arial, Helvetica, sans-serif; }
form { margin: 1em }
label,
button {
  display: block;
  float: left;
  clear: both;
  margin: .3em;
}
label { width:24em; line-height: 2em; }
input,
select { float: right; width: 15em;}
<form action="" method="post" id="My-Form">
  <label>First Name     <input type="text"  name="fName"></label>
  <label>Last Name      <input type="text"  name="lName"></label>
  <label>email address  <input thpe="email" name="email"></label>
  <label>08:30 Keynote Speaker
    <select name="Keynote_Speaker">
      <option value=""          >unsure     </option>
      <option value="attend"    >attend     </option>
      <option value="not attend">not attend </option>
    </select>
  </label>
  <label>09:00 Classes
    <select name="Classes_09_00">
      <option value=""            >unsure </option>
      <option value="class room A">room A </option>
      <option value="class room B">room B </option>
      <option value="class room C">room C </option>
    </select>
  </label>
  <label>10:30 Classes
    <select name="Classes_10_30">
      <option value=""            >unsure </option>
      <option value="class room A">room A </option>
      <option value="claww room B">room B </option>
      <option value="class room C">room C </option>
    </select>
  </label>
  <button type="submit">submit form</button>
</form>
Mister Jojo
  • 20,093
  • 6
  • 21
  • 40
  • Thank you so much for taking the time and having the interest to help. Your js gives me a lot to investigate for which I am grateful. Unfortunately, I cannot use the HTML you provide. The site is developed using Squarespace' platform. The form is one of their 'form blocks.'I have no control over the HTML, but I can reference the
    element. Though I could not have written it myself, I understand the js code you wrote. If I can incorporate it, or learn more about it and adapt it, I will. Thanks again for being interested and for your time and effort. They are quite appreciated.
    – alxfyv Jun 21 '19 at 18:12
  • I'm just saying thank you once again for the help you gave. I've studied the problem more, learned more, and can better appreciate your solution. It's so helpful. Thanks for a great answer and your time. – alxfyv Jun 25 '19 at 22:32