define(['angular'], function (angular) { var inspectionUpload = angular.module('inspectionupload', []); inspectionUpload.directive('ngInspectionUpload', ['$q', function ($q) { return { require: "?ngModel", restrict: "E", scope: true, controller: ['$scope', '$http', '$timeout', '$interval', function (scope, http, timeout, $interval) { var stop = undefined; var baseInterval = 5; scope.barcodeRequired = true; scope.pseudoProgress = 0; //Uploads selected files scope.onFileSelected = function (files) { scope.uploading = true; scope.statusMessage = "Preparing..."; var prepareRequest = { section: scope.section || "default", policyNumber: scope.policyNumber, vehicleSequenceNumber: scope.vehicleSequenceNumber }; //Make request to server for upload http.post(scope.uploadUrl.replace('Upload', 'PrepareUpload'), prepareRequest) .then(function (response) { scope.uploadId = response && response.data && response.data.Id; if (scope.uploadId) { scope.status = response.data; scope.startUploadQuery(); scope.startUpload(scope.uploadId); } else { scope.onUploadFailed("Server returned unexpected response"); } }, scope.onUploadFailed); } //Keep watch of the current status. Updating the model and template as progress in being made during the upload scope.$watch("status", function (status) { //Avoid model not being cleared if (status === null) { scope.updateModel(status); } switch (status && status.Status) { case "ready": scope.statusMessage = "Preparing..."; progress = 0; scope.pseudoProgress = 0; scope.startPseudoUpload(); scope.updateModel(null); break; case "uploading": scope.statusMessage = "Uploading..."; progress = status.Progress; scope.updateModel(null); break; case "done": scope.statusMessage = "Done!"; status.Progress = 1; scope.pseudoProgress = 100; scope.stopPseudoUpload(); scope.uploaded = true; scope.uploading = false; scope.updateModel(status); break; case "canceled": scope.clearUpload(); break; case "exception": scope.onUploadFailed(scope.status.ErrorMessage); status.Progress = 1; scope.updateModel(null); break; } }, true); scope.startPseudoUpload = function () { if (angular.isDefined(stop)) return; stop = $interval(function () { if (scope.pseudoProgress < 98) { var interval = baseInterval - (baseInterval * (scope.pseudoProgress / 100)); scope.pseudoProgress += interval; } }, 100); }; scope.stopPseudoUpload = function () { if (angular.isDefined(stop)) { $interval.cancel(stop); stop = undefined; } }; scope.cancelUploadClicked = function () { //Make request to server for upload http.post(scope.uploadUrl.replace('Upload', 'CancelUpload'), { id: scope.uploadId }) .then(function (response) { scope.uploadId = response && response.data && response.data.Id; if (scope.uploadId) { scope.status = response.data; } else { scope.onUploadFailed("Server returned unexpected response"); } }, scope.onUploadFailed); } scope.clearUpload = function () { scope.abortUpload(); scope.uploading = false; scope.uploaded = false; scope.status = null; scope.statusMessage = null; scope.errorMessage = null; scope.pseudoProgress = 0; } scope.onUploadFailed = function (error) { scope.uploading = false; scope.uploaded = false; scope.status = null; var message = "There was an error uploading. Please try again"; if (angular.isString(error)) message = error; scope.errorMessage = message; scope.abortUpload(); } scope.startUploadQuery = function () { if (scope.uploading) { http.post(scope.uploadUrl.replace('Upload', 'QueryUpload'), { id: scope.uploadId }) .then(function (response) { scope.status = response.data; if (/ready|uploading/.test(scope.status.Status)) { timeout(scope.startUploadQuery, 700); } }, function (error) { scope.onUploadFailed("Unkown error occured, check network connectivity and try again"); }); } } }], link: function (scope, element, attrs, ngModel) { //Create a hidden iframe on the page to use for image uploading //Create an id for the form. //Collisions can occur, but are unlikely. You are more likely to be hit by a bus on top of a meteor with a one legged blind man called Earl at the wheel. (5.3x10^^36) var uuidEst = 'xxxxxxxx_xxxx_4xxx_yxxx_xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); scope.formname = "frm_" + uuidEst; scope.iframename = "i" + scope.formname; var myel = element[0]; scope.formElement = myel.querySelector("form"); scope.idElement = myel.querySelector("input[type='hidden']"); scope.fileElement = myel.querySelector("input[type='file']"); var iframeElement = document.createElement("iframe"); iframeElement.name = scope.iframename; iframeElement.id = scope.iframename; iframeElement.width = 0; iframeElement.height = 0; iframeElement.style.display = "none"; iframeElement.style.zIndex = -10000; myel.appendChild(iframeElement); //If the attribute barcode-required is specified if ("barcodeRequired" in attrs) { scope.barcodeRequired = true; } else { scope.barcodeRequired = false; } //Utilize attribute and get them into the directives scope attrs.$observe("url", function (url) { scope.uploadUrl = url; }); //track some urls attrs.$observe("section", function (section) { scope.section = section; }); //used in uploads identitfy and scan information from for instance licencedisks images attrs.$observe("policyNumber", function (policyNumber) { scope.policyNumber = policyNumber; }); attrs.$observe("vehicleSequenceNumber", function (vehicleSequenceNumber) { scope.vehicleSequenceNumber = vehicleSequenceNumber; }); attrs.$observe("uploadTemplateUrl", function (uploadTemplateUrl) { scope.uploadTemplateUrl = uploadTemplateUrl; }); //Used as a placeholder to give the user template of what photo is desired attrs.$observe("ngModel", function (ngModelStr) { scope.$watch(ngModelStr, function (newVal, oldVal) { if (newVal) { scope.status = newVal } else { scope.clearUpload(); } }); }); //If the attribute barcode-required is specified if ("barcodeRequired" in attrs) { scope.barcodeRequired = true; } else { scope.barcodeRequired = false; } //watch if a file is selected angular.element(scope.fileElement).on('change', function () { scope.onFileSelected(scope.fileElement.files); scope.$apply(); }); //provide a start upload method scope.startUpload = function (id) { scope.idElement.value = id; scope.formElement.target = scope.iframename; scope.formElement.submit(); } //provide an abort upload method scope.abortUpload = function () { scope.formElement.reset(); } scope.triggerUpload = function () { scope.uploaded = false; scope.status = null; scope.statusMessage = null; scope.errorMessage = null; scope.fileElement.click(); } //provide method to update the model scope.updateModel = function (newModel) { ngModel.$setViewValue(newModel); } //Initialize the model if it was already set if (scope.$eval(attrs.ngModel)) { scope.status = scope.$eval(attrs.ngModel); scope.uploaded = true; scope.uploading = false; } }, template: '
' + '
' + '' + '
' + '
' + '
We are unable to read the barcode.
' + '
' + '
    ' + '
  • ' + '
    We are scanning the barcode so please ensure its visible
    ' + '
  • ' + '
  • ' + '
    Take photo where there is enough light,
    ' + '
  • ' + '
  • ' + '
    Make sure when taking the photo the phone is level with the disc
    ' + '
  • ' + '
' + '
' + 'Upload template' + '
{{errorMessage}}
' + '
' + '' + '
' + '
' + '
' + '' + '
' + '' + '
' + '
' + '
' + '' + '
Unable to read barcode. Please try again with a better quality picture
' + '
' + '' + '
' + '
' }; }]); return inspectionUpload; });