As I was building a custom form for a SharePoint 2013 client side solution, I ran across the following error when I tried to use JSOM to upload a file attachment:

Object doesn't support property or method 'moveTo'

I had been using a pretty good solution to attach files based on this post. However after digging further I realised the issues with this approach:

  1. The moveTo function is not present in the SharePoint 2013 Client Side Object Model for JavaScript.
  2. The file size limit is 1.5MB
  3. Attachments are stored in the List as "Attachments/[ItemId]" and I could not find another way to create it using JSOM

Ultimately, this wasn't going to cut it. While there are a couple of ways to do this, with the REST API or the Lists.asmx Web Service, I opted for the Lists.asmx and used the excellent SP Services library which made it simple as :).

//TypeScript
//File Attachment - Upload a single file as an attachment to a list item.
        addFileAttachment(fileInput: any, listTitle, itemId): JQueryPromise<any> {
            var deferred = $.Deferred();
            var reader = new FileReader();
            reader.onerror = (e) => {
                var error = (<any>e.target).error.code;
                deferred.reject("File transfer failed: " + error);
            };
            reader.onabort = () => {
                deferred.reject("File transfer aborted");
            };
            reader.onload = (file: any) => {
                var fileData = new Uint8Array(file.target.result);
                var fileContent = new SP.Base64EncodedByteArray();
                for (var i = 0; i < fileData.length; i++) {
                    fileContent.append(fileData[i]);
                }
                
                $().SPServices({
                    operation: "AddAttachment",
                    listName: listTitle,
                    listItemID: itemId,
                    fileName: fileInput.name,
                    attachment: fileContent.toBase64String(),
                    async: true,
                    completefunc: function () {
                        deferred.resolve();
                    }
                });
            };
            reader.readAsArrayBuffer(fileInput);
            return deferred.promise();
        }

The fileInput is your HTML Input element which you can get via jquery or other means.
Note that the output of this function is returning a jQuery Promise.
Example:

 var control = document.getElementById("MyInputFileControl");
 var listTitle = "My List Title";
 var itemId = 1;
 addFileAttachment(control, listTitle, itemId)
  .done(() =>{ console.log('success');})
  .fail((error) => { console.error(error);});

So that's pretty much it. I've simplified this example slightly for readability. In my scenario I've added progress callbacks to update a Modal Dialog and a Progress bar.