Sum of numbers separated with comma

Posted on

Problem

I am very new to HTML and I’ve decided to attempt to put what I know into an HTML page that allows you to enter any amount of numbers, separated by commas, and would display the sum of all the numbers below.

<!DOCTYPE html>

<html>

<head>
  <title>Sum of two numbers</title>
</head>

<body>
  <h1>Enter any amount of numbers separated by a comma:</h1>
  <input id="nums" type="text" required="required" />
  <button onclick="sum()">Get sum</button>
  <h3 id="sum"></h3>

  <script lang="javascript">
    function sum() {
      sumofnums = 0;
      nums = document.getElementById("nums").value.split(",");
      for (i = 0; i < nums.length; i++) {
        sumofnums += parseInt(nums[i]);
      }
      document.getElementById("sum").innerHTML = sumofnums;
    }
  </script>
</body>

</html>

Are there any bad practices in my code?

Solution

HTML or XHTML? Which version? Be clear.

Your file is ambiguous. The usage of the empty element tag syntax <input ... */>* suggests (not mandates) that it’s XHTML, whereas the absence of a namespace declaration suggests its not.

I recommend that documents are always clear about whether they’re HTML or XHTML. And I recommend XHTML because parsing XHTML is simpler than parsing HTML, and HTML5 is defined in a way that XHTML5 documents are (more or less) a subset of HTML5 documents. The keyword is polyglot syntax.

Maybe in your context it’s clear, but there is not sufficient information for us, the reviewers, whether your server would serve it as text/html or application/xhtml+xml.

Note that <!DOCTYPE html> does not sufficiently declare HTML5. The HTML5 specification says that an HTML5 document should have a doctype declaration of the form <!DOCTYPE html>. But it does not declare that everything that has such a doctype declaration is HTML5. It also does not (and cannot) prevent any other specification from also using the <!DOCTYPE html> declaration for some other variant of HTML than HTML5. Furthermore, it permits XHTML5 to also use the very same <!DOCTYPE html> declaration. See this.

I recommend to use the XHTML5 with the polyglot syntax, which is the “common subset” of HTML5 and XHTML5. It is basically HTML5 parsable with an XML parser. I recommend this for multiple reasons.

  • The parsing rules of XML are simpler, therefore automated processing of documents with tools such as XSLT is simpler / possible with the XML syntax.
  • You can create DTDs or XML Schemas that further validate your syntax. XML Schema with XML namespaces allows you to validate the mix of different XML-based languages such as for example XHTML and SVG within a single document.

(It’s a pitty that the guys of WhatWG are so ignorant towards XML and its capabilities. It’s a pitty that the guys of WhatWG had to reinvent the wheel and declare HTML5 as a markup language of its own right besides SGML and XML. That was completely unnecessary and it only confuses people, as we can see with this discussion about the <!DOCTYPE>.)

Declare encoding

It’s recommended to always declare the encoding. And the encoding should be declared within the first 1024 bytes.

There are 4 ways how the server can declare the encoding of a (X)HTML document to the client:

  • HTTP Content-Type header: The server would send something like Content-Type: text/html; charset=UTF-8 or Content-Type: application/xhtml+xml; charset=UTF-8 to the client.
  • XML declaration (only for XHTML, not HTML), as the first line of the document: <?xml version="1.0" encoding="UTF-8"?>.
  • Meta element declaring the Content-Type, like this: <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> resp. <meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
  • Meta element declaring the Charset, like this: <meta charset="UTF-8" />

See this for more information.

Document Outline

The outline of your document looks like this:

  • Enter any amount of numbers separated by a comma:
    • (level skipped)
      • (empty headline)

I doubt that this outline makes sense.

Keep in mind that <h1/>, <h2/> etc. are for headlines. If you just want a paragraph with big text but without the semantics of a headline, use a normal paragraph instead and style it with CSS.

Also, skipping levels is not recommended. For a <h*N*/> element, the next heading should have a level not greater than N+1.

How to declare the scripting language

The correct way to declare the scripting language on a <script/> element is like this:

<script type="text/javascript">
    // ...
</script>

If you know that the User Agent supports HTML5 or behaves as expected, you can actually omit the declaration of the scripting language:

The default, which is used if the attribute is absent, is “text/javascript”.

The lang attribute is actually meant for describing the content language, like this:

<h1 lang="en">Hi, <span lang="es">Hola</span>, <span lang="de">Hallo und <span lang="de-BY">Servus</span></span>!</h1>

What you did, actually declares the contents of the <script/> element to be in a non-existent natural language named JavaScript.

Naming Conventions

Because JavaScript and Java were somehow born together, they follow identical naming conventions. Which means, we also use camelCase for variables and functions in JavaScript.

Your variable sumofnums should be named sumOfNums.

Local vs Global Variables

In JavaScript, whenever you assign a variable without declaration, it is implicitly global. Local variables need to be declared explicitly, using the var keyword.

You should declare your variables, like this:

var sumOfNums = 0;
var nums = document.getElementById("nums").value.split(",");

The same is true for i.
It can be declared at the for-loop, like in Java:

for (var i = 0; i < nums.length; i++) {
  sumOfNums += parseInt(nums[i]);
}

However, be aware that scopes in JavaScript are only global or function-local. Blocks do not define new scopes for variables.

User Input Validation

If the user inputs crap, you might want to tell the user instead of silently failing. JavaScript supports regular expressions, in case you want to go for that. But anyhow, you want to deal with parseInt() failing.

JavaScript supports exception handling quite similar to Java with a try-catch-finally, you might want to go for that and tell the user about bogus input.

The required attribute of <input/>

The required attribute of <input/> is for form submission. Because you use the <input/> element outside a form, there is no form submission, therefore the required attribute doesn’t make sense.

Indentation

Consistent indentation is paramount, and you follow it.
There is no official standard or convention for indentation in JavaScript.

While the community has taken a lot of rules from Java, including the 4 spaces indentation, some Software Craftsmen like Robert C. Martin suggest that indentation nowadays should actually be 2 spaces rather than 4.

Strict mode

JavaScript is in its core ECMA-262, aka ECMAScript. Strictly speaking, JavaScript was Netscape’s name for its implementation of ECMAScript.

ECMA-262 defines a strict mode (10.1.1) which can be enabled with the use strict directive. The most notable differences are:

  • In strict mode, usage of the future reserved words implements, interface, let, package, private, protected, public, static and yield is an error. (7.6.1.2)
  • Octal literals are not supported. (7.8.3)
  • Octal escape sequences are not supported. (7.8.4)
  • functions and variables declared eval() code must be declared within a new variable environment that is accessible to the eval code only. (10.4.2.1)
  • The delete operator is limited. (11.4.1)
  • Assignment are stricter. (11.13.1)
  • eval and arguments are not allowed as variable names (12.2.1), including exception variables (12.14.1).
  • with is not allowed. (12.10)
    A full list can be seen in Annex C.

You might want to make it a habit to program in strict mode always. It ensures greater compatibility of your source code with future language directions.

Your JS has a few problems. In the first place, you should always define your variables with the var keyword, or you can have major problems debugging your program (using var to declare variables):

sumofnums = 0;

should become:

var sumofnums = 0;

You do your braces correctly, but sumofnums would be easier to read as sumOfNums. Also, JSLint thinks we should merge the first two var declarations. Additionally, you should use a four spaces per level of indentation, not two:

function sum() {
    var sumOfNums = 0, nums = document.getElementById("nums").value.split(",");

    for (var i = 0; i < nums.length; i++) {
        sumOfNums += parseInt(nums[i]);
    }

    document.getElementById("sum").innerHTML = sumOfNums;
}

You have a problem in your HTML, according to the official validator at W3C:

This is not valid:

<script lang="javascript">

It should be this:

<script type="text/javascript">

Because lang attributes are supposed to specify the language of the webpage, they are not allowed to be longer than 8 characters, according to the W3C validator: Bad value javascript for attribute lang on element script: Subtags must not exceed 8 characters in length.

The correct use for this attribute would be to use it as this for a Spanish webpage:

lang="es"

In American English:

lang="en-us"

Comments w.r.t the algo and not the javascript practises:

  • Don’t trust the user. Suppose I enter, or 0,, shouldn’t you provide me 0 rather than NaN?
  • Provide valid error message for error conditions like empty input or invalid cases as above.
  • Does parseInt take care of characters? Does it throw exceptions? Should you catch it in the outer loop? Should you provide any error message or continue by ignoring it?

parseInt only allows integers and truncates all decimal entries, so entering .5,.5 throws a NaN, and 0.5,0.5 returns 0 instead of 1. Either modify your instructions to tell the user you only accept integers or (even better) change to parseFloat to allow non-integer numbers.

Leave a Reply

Your email address will not be published. Required fields are marked *