Syntax Error in JS

(function iife() {

  "use strict";



  function getPriceEl(form) {

    return form.querySelector(".license_price");

  }



  function getCheckboxes(form) {

    return form.querySelectorAll("input[type='checkbox']");

  }



  function getCheckboxPrice(checkbox) {

    return checkbox.parentNode.querySelector(".license_price").innerHTML;

  }



  function getTotalEl(form) {

    return form.querySelector(".totalprice");

  }



  function updatePrice(select, prices) {

    var price = getPriceEl(select.form);

    price.innerHTML = "€" + prices[select.selectedIndex];

  }



  function isChecked(checkbox) {

    return checkbox.checked;

  }



  function priceToValue(price) {

    return Number(price.split("€")[1]);

  }



  function sum(val1, val2) {

    return val1 + val2;

  }



  function checkboxTotals(checkboxes) {

    return Array.from(checkboxes)

      .filter(isChecked)

      .map(getCheckboxPrice)

      .map(priceToValue)

      .reduce(sum, 0);

  }



  function updateTotal(form) {

    var total = getTotalEl(form);

    var dropdownPrice = priceToValue(getPriceEl(form).innerHTML);

    var checkboxTotal = checkboxTotals(getCheckboxes(form));

    var totalPrice = dropdownPrice + checkboxTotal;

    total.innerHTML = "€" + totalPrice;

    console.log(totalPrice);
  }



  function updatePriceHandler(evt) {

    var select = evt.target;

    var form = select.form;

    updatePrice(select, prices);

    updateTotal(form);

  }



  function updateTotalHandler(evt) {

    var form = evt.target.form;

    updateTotal(form);

  }



  var prices = [99, 236, 1475];

  var form = document.querySelector("#order");

  var select = form.elements.license_type;

  var checkboxes = getCheckboxes(form);

  select.addEventListener("change", updatePriceHandler);

  checkboxes.forEach(function addCheckboxHandler(checkbox) {

    checkbox.addEventListener("click", updateTotalHandler);

  });
});

This website says that there is no syntax error →
https://esprima.org/demo/validate.html

However the browser has a different story to tell:

What can be fix?

The code starts with an IIFE, an immediately invoked function expression. Check the end of that code to see if it ends properly for an IIFE.

1 Like

I think is the pedagogy for IIFE →

(function () {
    //Our JS CODE GOES HERE
})();

I have corrected it in the end. I is still generating the error in the end:

image

Uncaught SyntaxError: Unexpected end of input

I was finally able to fix it. In the start of the custom.js the JQuery was also opened here →

jQuery(document).ready(function($) {

that also needed to be closed.

Error free Now →

image

2 Likes

Nice one. It might be a little thing but using }()); is preferable to })();
I’m glad that you used the former, for the latter looks like dogs balls hanging off.

Cue seasonal rant - this is not directed at you, but just inspired by your situation.

There’s also a very good reason to have the invoking parenthesis inside too.

With a function declaration you have:

function funcDecl() {
    console.log("Function declaration");
}
funcDecl(); // Function declaration

That function declaration cannot be directly invoked by adding parenthesis on the end of it, because function declarations are hoisted and defined before the code is run.

We can turn that function declaration into a function expression by assigning it to a variable, which makes it a function expression instead.

const funcExpr = function funcExpr() {
    console.log("Function expression");
}
funcExpr(); // Function expression

Now notice that in both cases, it is the function itself that is invoked.

That function expression can be directly invoked too, where the return value of the function ends up being assigned to the variable.

const result = function funcExpr() {
    console.log("Function expression");
    return "Success";
}();
console.log(result); // Success

In all of these situations, the invoking parenthesis comes directly after the function, whether that be the function name or the function directly.

With an IIFE, the invoking parenthesis can come after the function, or after the enclosing parenthesis. Both achieve the same thing, but they imply different things to us.

When the invoking parenthesis come after the function, that says that we are invoking the function, which is a fully consistent behavior with how functions are normally used.

(function iife() {
  // ...
}()); // Good

When the invoking parenthesis though come after the enclosing parenthesis, that instead says that we are invoking the new environment created by the enclosing parenthesis, which just-so happens to contain a function. That is a change of mind-set that is quite divorced from how we normally think about functions.

(function iife() {
  // ...
})(); // Bad

Because of that, deriding the dogs balls out of the invoked enclosing parenthesis helps us to remain true to a way of coding that is more consistent with how functions are normally used.

And once again, I’m glad that you kept the invoking parenthesis inside of the enclosing parenthesis. For that is how things should be.

(function iife() {
  // ...
}()); // Good

I’m glad to be supported on this by others too.

End rant

2 Likes

This is slightly advanced. I have taken this link in my Gmails Draft where I often save education articles that I do not completely grasp in 1st instance.

Thank you so much for sharing the knowledge and enlightening me.

1 Like