Completed
Push — master ( 401bbc...02c732 )
by Grant
05:46 queued 02:35
created

ProfilePicAPI.refreshMultipleProfilePics   B

Complexity

Conditions 6
Paths 6

Size

Total Lines 1

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
nc 6
nop 1
dl 0
loc 1
rs 8.6666
c 0
b 0
f 0
1
var ProfilePicAPI = {};
2
3
ProfilePicAPI.version = "v1";
4
ProfilePicAPI.baseURL = "/tc/api/"+ProfilePicAPI.version;
5
6
ProfilePicAPI.loadingTextClass = 'fileUploadLoadingText';
7
ProfilePicAPI.loadingBarClass = 'fileUploadLoadingBar';
8
ProfilePicAPI.defaultProfilePic = '/images/user.png';
9
10
ProfilePicAPI.Uploader = function(
11
        fileInputButtons,
12
        dropZone,
13
        croppieContainer,
14
        clearButton,
15
        saveButton,
16
        userId,
17
        onUploadComplete
18
        ) {
19
20
    this.fileInputButtons = fileInputButtons;
21
    this.dropZone = dropZone;
22
    this.croppieContainer = croppieContainer;
23
    this.clearButton = clearButton;
24
    this.saveButton = saveButton;
25
    this.userId = userId;
26
    this.onUploadComplete = onUploadComplete;
27
28
    this.photo = null;
29
    this.croppie = null;
30
    this.max_filesize = 5242880;
31
    this.defaultPhotoSrc = ProfilePicAPI.defaultProfilePic;
32
    this.uploadUrl = ProfilePicAPI.baseURL + "/profilePic/" + this.userId;
33
34
    var self = this;
35
36
    self.init = function() {
37
        for (var i=0; i<fileInputButtons.length; i++) {
38
            fileInputButtons[i].onchange = self.addFiles;
39
        }
40
        if (self.saveButton) {
41
            self.saveButton.onclick = self.uploadPhoto;
42
        }
43
        if (self.clearButton) {
44
            self.clearButton.onclick = self.clearUpload;
45
        }
46
        if (self.dropZone) {
47
            self.initializeDropzone();
48
        }
49
    };
50
51
     self.initializeDropzone = function(){
52
        //clone dropZone to remove existing event listeners
53
        var clone = self.dropZone.cloneNode();
54
        while (self.dropZone.firstChild) {
55
          clone.appendChild(self.dropZone.lastChild);
56
        }
57
        self.dropZone.parentNode.replaceChild(clone, self.dropZone);
58
        self.dropZone = clone;
59
60
        self.dropZone.addEventListener("dragenter",  self.stopProp, false);
61
        self.dropZone.addEventListener("dragleave",  self.dragExit, false);
62
        self.dropZone.addEventListener("dragover",  self.dragOver, false);
63
        self.dropZone.addEventListener("drop",  self.processDroppedFiles, false);
64
    };
65
66
    /**
67
     * Use this function to set files programmatically
68
     *
69
     * @param {type} files
70
     * @return {undefined}
71
     */
72
    self.setFiles = function(files) {
73
        self.processNewFiles(files);
74
    };
75
76
    self.addFiles = function () {
77
        self.processNewFiles(this.files);
78
    };
79
80
    self.dragOver = function (ev) {
81
        self.stopProp(ev);
82
        self.dropZone.classList.remove("fileDropzoneNormal");
83
        self.dropZone.classList.add("fileDropzoneHighlight");
84
        //this.style["backgroundColor"] = "#F0FCF0";
85
        //this.style["borderColor"] = "#3DD13F";
86
        //this.style["color"] = "#3DD13F";
87
    };
88
89
    self.dragExit = function (ev) {
90
        self.stopProp(ev);
91
        self.dropZone.classList.remove("fileDropzoneHighlight");
92
        self.dropZone.classList.add("fileDropzoneNormal");
93
        //dropZone.style["backgroundColor"] = "#FEFEFE";
94
        //dropZone.style["borderColor"] = "#CCC";
95
        //dropZone.style["color"] = "#CCC";
96
    };
97
98
    self.stopProp = function (ev) {
99
        ev.stopPropagation();
100
        ev.preventDefault();
101
    };
102
103
    self.processDroppedFiles = function (ev) {
104
        self.stopProp(ev);
105
        var files = ev.dataTransfer.files;
106
        self.processNewFiles(files);
107
    };
108
109
    var actionWrapperDefault = document.querySelector(".update-profile__action-wrapper--default-state");
110
    var actionWrapperUpload = document.querySelector(".update-profile__action-wrapper--upload-state");
111
    var draggableArea = document.querySelector(".update-profile-photo__draggable-area-wrapper");
112
113
    self.clearUpload = function () {
114
        //Clear upload
115
        self.photo = null;
116
117
        //Clear preview
118
        self.croppieContainer.innerHTML = "";
119
        self.croppieContainer.classList.remove("croppie-container");
120
121
        //Clear input button value
122
        for (var i=0; i<self.fileInputButtons.length; i++) {
123
            self.fileInputButtons[i].value = null;
124
        }
125
126
        // UI Changes
127
        actionWrapperDefault.classList.remove("hidden");
128
        actionWrapperUpload.classList.remove("active");
129
        draggableArea.classList.remove("active");
130
        draggableArea.classList.remove("error");
131
        draggableArea.classList.remove("error--size");
132
        draggableArea.classList.remove("error--type");
133
134
    };
135
136
    self.processNewFiles = function (files) {
137
        if (files === null || files.length === 0) {
138
            //Do nothing if new files is empty
139
            return;
140
        }
141
        var file = files[0];
142
        if (file.type.match('image.*')) {
143
            self.clearUpload();
144
            var fr = new FileReader();
0 ignored issues
show
Bug introduced by
The variable FileReader seems to be never declared. If this is a global, consider adding a /** global: FileReader */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
145
            fr.file = file;
146
            fr.onloadend = function(ev) {
147
                if (ev.target.file.size < self.max_filesize) {
148
                    self.photo = ev.target.file;
149
                    self.croppie = self.makeProfilePicCroppie(self.croppieContainer, ev.target.result);
150
                    // UI Changes
151
                    actionWrapperDefault.classList.add("hidden");
152
                    actionWrapperUpload.classList.add("active");
153
                    draggableArea.classList.add("active");
154
                    draggableArea.classList.remove("error");
155
                } else {
156
                    // Indicates file is too large.
157
                    draggableArea.classList.remove("active");
158
                    draggableArea.classList.add("error--size");
159
                }
160
            };
161
            fr.readAsDataURL(fr.file);
162
        } else {
163
            // Indicates file is wrong type.
164
            draggableArea.classList.remove("active");
165
            draggableArea.classList.add("error--type");
166
        }
167
    };
168
169
    self.makeProfilePicCroppie = function(imageElement, imageSrc) {
170
171
        var croppie = new Croppie(imageElement, {
0 ignored issues
show
Bug introduced by
The variable Croppie seems to be never declared. If this is a global, consider adding a /** global: Croppie */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
172
            viewport: { width: 200, height: 200, type: 'circle'},
173
            boundary: { width: 200, height: 200 },
174
            showZoomer: true,
175
            enableZoom: true,
176
            enforceBoundary: true,
177
            mouseWheelZoombool: true
178
        });
179
        croppie.bind({
180
            url: imageSrc
181
        }).then(function() {
182
            var crImage = croppie.elements.img;
183
            crImage.setAttribute("alt", "Preview Profile Photo");
184
            croppie.setZoom(0.15);
185
        });
186
        return croppie;
187
    };
188
189
    self.uploadPhoto = function() {
190
        if (self.photo && self.croppie) {
191
            self.croppie.result({
192
                    type: 'blob',
193
                    size: 'viewport',
194
                    format: 'png',
195
                    quality: 1,
196
                    circle: false
197
                }).then(function(blob) {
198
                    var payload = blob;                    
199
                    var headers = {"Content-type": self.photo.type,
200
                        "X-File-Name": self.photo.name,
201
                        "Accept":"application/json"};
202
                    DataAPI.sendRequest(self.uploadUrl, 'PUT', headers, payload, function(request){
0 ignored issues
show
Bug introduced by
The variable DataAPI seems to be never declared. If this is a global, consider adding a /** global: DataAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
203
                        if (self.onUploadComplete) {
204
                            self.onUploadComplete(request);
205
                        }
206
                    });
207
                });
208
        }
209
    }
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
210
211
    self.init();
212
};
213
214
ProfilePicAPI.refreshUserProfilePic = function(imageElement) {
215
    if (UserAPI.hasSessionUser()) {
0 ignored issues
show
Bug introduced by
The variable UserAPI seems to be never declared. If this is a global, consider adding a /** global: UserAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
216
        var userId = UserAPI.getSessionUserAsJSON().user_id;
217
        ProfilePicAPI.refreshProfilePic(userId, imageElement);
218
    }
219
};
220
221
ProfilePicAPI.refreshProfilePic = function(userId, imageElement) {
222
    ProfilePicAPI.refreshMultipleProfilePics(userId, [imageElement]);
223
};
224
225
ProfilePicAPI.refreshProfilePicBackground = function(userId, imageElement) {
226
    ProfilePicAPI.refreshMultipleProfilePicsBackground(userId, [imageElement]);
227
};
228
229
ProfilePicAPI.refreshMultipleProfilePics = function(userId, imageElements) {
230
    var pic_url = ProfilePicAPI.baseURL+'/profilePic/'+userId;
231
    DataAPI.sendRequest(pic_url, 'GET', {"Accept":"image/*"}, null, function(request){
0 ignored issues
show
Bug introduced by
The variable DataAPI seems to be never declared. If this is a global, consider adding a /** global: DataAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
232
        if(request.readyState === 4){
233
            if (request.status === 200) {
234
                for (var i=0; i<imageElements.length;i++) {
235
                    var rand = Math.floor((Math.random() * 10000) + 1);
236
                    var randomQuery = "?v="+rand;
237
                    if (request.responseURL)
238
                        imageElements[i].src = request.responseURL + randomQuery;
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
239
                    else
240
                        imageElements[i].src = pic_url + randomQuery;
241
                }
242
            } else {
243
                for (var i=0; i<imageElements.length;i++) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable i already seems to be declared on line 234. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
Bug introduced by
It seems like i was already defined.
Loading history...
244
                    imageElements[i].src = ProfilePicAPI.defaultProfilePic;
245
                }
246
            }
247
        }
248
    });
249
};
250
251
ProfilePicAPI.refreshMultipleProfilePicsBackground = function(userId, imageElements) {
252
    var pic_url = ProfilePicAPI.baseURL+'/profilePic/'+userId;
253
    DataAPI.sendRequest(pic_url, 'GET', {"Accept":"image/*"}, null, function(request){
0 ignored issues
show
Bug introduced by
The variable DataAPI seems to be never declared. If this is a global, consider adding a /** global: DataAPI */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
254
        if (request.status == 200) {
255
            for (var i=0; i<imageElements.length;i++) {
256
                var rand = Math.floor((Math.random() * 10000) + 1);
257
                var randomQuery = "?v="+rand;
258
                if (request.responseURL)
259
                    imageElements[i].style.backgroundImage = "url("+request.responseURL+randomQuery+")";
0 ignored issues
show
Coding Style Best Practice introduced by
Curly braces around statements make for more readable code and help prevent bugs when you add further statements.

Consider adding curly braces around all statements when they are executed conditionally. This is optional if there is only one statement, but leaving them out can lead to unexpected behaviour if another statement is added later.

Consider:

if (a > 0)
    b = 42;

If you or someone else later decides to put another statement in, only the first statement will be executed.

if (a > 0)
    console.log("a > 0");
    b = 42;

In this case the statement b = 42 will always be executed, while the logging statement will be executed conditionally.

if (a > 0) {
    console.log("a > 0");
    b = 42;
}

ensures that the proper code will be executed conditionally no matter how many statements are added or removed.

Loading history...
260
                else 
261
                    imageElements[i].style.backgroundImage = "url("+ pic_url+randomQuery+")";
262
            }
263
        } else {
264
            for (var i=0; i<imageElements.length;i++) {
0 ignored issues
show
Comprehensibility Naming Best Practice introduced by
The variable i already seems to be declared on line 255. Consider using another variable name or omitting the var keyword.

This check looks for variables that are declared in multiple lines. There may be several reasons for this.

In the simplest case the variable name was reused by mistake. This may lead to very hard to locate bugs.

If you want to reuse a variable for another purpose, consider declaring it at or near the top of your function and just assigning to it subsequently so it is always declared.

Loading history...
Bug introduced by
It seems like i was already defined.
Loading history...
265
                imageElements[i].style.backgroundImage = "url("+ProfilePicAPI.defaultProfilePic+")";
266
            }
267
        }
268
    });
269
};
270