PageSourceSearch

https://ta-tum.com/js/modules/teacher/classroom/project/post/TeacherClassroomProjectPost.js

js ta-tum.com collected 2026-09-24 11:29:21 UTC 59,653 bytes, 1,182 lines download raw bytes

1/**
2 * Module Teacher Classroom Project Post
3 * @description Modelo/Vista/Controlador para gestión de actividad exclusiva de un post (task/test)
4 * @author Alejandro Micheloud
5 */
6
7var TeacherClassroomProjectPost = function (sco) {
8    var scope = sco;
9    var scope_body = null;
10    var builded = false;
11    var post_ob = null;
12    var render_by = "name";
13    var students_ar = [];
14    var current_response = null;
15    var current_student_guid = null;
16    var mReturn = null;
17    var _this = this;
18    /**
19     * Se invoca cuando el módulo recibe foco
20     * @returns {undefined}
21     */
22    function show() {
23        if (!builded) {
24            build(function () {
25                doStart();
26            });
27        } else {
28            doStart();
29        }
30    }
31    function doStart() {
32        scope_body.show();
33        mDiscover.showLoading();
34        console.log("getPost()");
35        mCom.ajax("classroom-project-post/" + mTeacherHome.getClassroomProjectGuid() + "/" + mTeacherHome.getCurrentPostGuid(), "GET", "", function (data, status) {
36            console.log("getPost() result");
37            console.log(data);
38            post_ob = data;
39            mDiscover.hideLoading();
40            if (status === "success") {
41                renderPost();
42            }
43        }, function (err, status, msg) {
44            mToast.toast(lang.classroom_project_get_post_error, 3000);
45            mDiscover.hideLoading();
46        });
47        if (mTeacherHome.getCurrentClassroom() !== null) {
48            renderClassroom();
49        } else {
50            $("body").off("on_current_classroom_update", renderClassroom);
51            $("body").on("on_current_classroom_update", renderClassroom);
52        }
53
54        current_student_guid = mTeacherHome.getCurrentStudentGuid();
55        closeResponse();
56    }
57    function renderClassroom() {
58        var classroom = mTeacherHome.getCurrentClassroom();
59        console.log(classroom);
60        var avatar = (classroom.avatar !== "") ? 'background-image:url(' + classroom.avatar + ');' : '';
61        scope_body.find(".d-bar-left-classroom .d-name").html(classroom.name);
62        scope_body.find(".d-bar-left-classroom .d-avatar").attr("style", avatar);
63    }
64
65    function getExercise() {
66        if (post_ob.post.exercises.length > 0) {
67            var exercise = JSON.parse(post_ob.post.exercises[0]);
68            CORE.get(function (response) {
69                console.log(response.data);
70                for (var i = 0;
71                    i < response.data.length;
72                    i++) {
73
74                    var row = response.data[i];
75
76                    row.resume = true;
77                    row.readOnly = true;
78                    row.showAnswer = true;
79                    row.returnScopes = true;
80                    row.lang = userLang;
81
82                    console.log("27-09, row.lang: " + row.lang)
83
84                    scope_body.find(".d-post-container .d-exercise").append(exeView);
85                    new runExercise(scope_body.find(".d-post-container .d-exercise").find('.holderExercise'), row);
86                    scope_body.find(".d-post-container .d-exercise .d-loader").hide();
87                }
88            }, function (err) {
89                console.log(JSON.parse(err).data);
90            }, {
91                exercises: [exercise.itemId],
92                scopes: [post_ob.post.exercises_scopes[0]],
93                resume: true,
94                readOnly: true,
95                showAnswer: true,
96                returnScopes: true
97            });
98            // userEmail: "asd6",
99        } else {
100            console.log("ERROR: exercise not defined");
101        }
102    }
103    function getExerciseResponse() {
104
105        if (post_ob.post.type === "quizz") {
106
107            if (current_response.status === "delivered" || current_response.status === "corrected") {
108
109                scope_body.find(".d-post-container.student .d-reset-test")
110                    .show()
111                    .off("click")
112                    .on("click", function () {
113                        mDiscover.openConfirm(lang.classroom_project_post_reset_test, lang.classroom_project_post_reset_test_msg, function (re) {
114                            if (re) {
115                                mDiscover.showLoading();
116                                mCom.ajax("classroom-project-post/reset/quizz", "PUT", { task_response_guid: current_response.guid }, function (data, status) {
117
118                                    mDiscover.hideLoading();
119                                    doStart();
120                                }, function (err, status, msg) {
121                                    mToast.toast("Problemas al reiniciar test", 3000);
122                                    mDiscover.hideLoading();
123                                });
124                            }
125                        });
126                    });
127            }
128            if (current_response.exercise_scope === null || current_response.data === null) {
129                scope_body.find(".d-post-container.student .d-content").html(lang.classroom_project_post_student_without_response);
130                return;
131            }
132            if (post_ob.post.exercises.length > 0) {
133                var exercise = JSON.parse(post_ob.post.exercises[0]);
134                CORE.get(function (response) {
135                    var total = 0, index = 0;
136                    for (var key in response.data) {
137                        if (key !== "status") {
138                            var row = response.data[key];
139                            if (!index) {
140                                scope_body.find(".d-post-container.student .d-content").append(exeView);
141                                new runExercise(scope_body.find(".d-post-container.student .d-content").find('.holderExercise'), {
142                                    resume: true,
143                                    exercise: exercise.itemId,
144                                    email: current_response.username,
145                                    scope: row.scope,
146                                    scopeId: row.scopeId,
147                                    readOnly: true,
148                                    token: row.token,
149                                    lang: userLang
150                                });
151                                scope_body.find(".d-post-container.student .d-content .d-loader").hide();
152                            }
153                            index++;
154                            total += row.earnedPoints;
155                        }
156                    }
157                    scope.find(".d-post-container.student .d-points span").html(total);
158                }, function (err) {
159                    console.log(JSON.parse(err).data);
160                }, {
161                    exercises: [exercise.itemId],
162                    scopes: ["post-" + current_response.exercise_scope],
163                    userEmail: current_response.username
164                });
165                // userEmail: "asd6",
166            } else {
167                console.log("ERROR: exercise not defined");
168            }
169        } else {
170            if (current_response.status === "delivered" || current_response.status === "corrected") {
171                if (current_response.status === "delivered" || current_response.status === "corrected") {
172                    scope_body.find(".d-post-container.student .d-reset-test")
173                        .show()
174                        .off("click")
175                        .on("click", function () {
176                            mDiscover.openConfirm(lang.classroom_project_post_reset_task, lang.classroom_project_post_reset_task_msg, function (re) {
177                                if (re) {
178                                    mDiscover.showLoading();
179                                    mCom.ajax("classroom-project-post/reset/task", "PUT", { task_response_guid: current_response.guid }, function (data, status) {
180
181                                        mDiscover.hideLoading();
182                                        doStart();
183                                    }, function (err, status, msg) {
184                                        mToast.toast("Problemas al reiniciar tarea", 3000);
185                                        mDiscover.hideLoading();
186                                    });
187                                }
188                            });
189                        });
190                }
191                if (current_response.hasOwnProperty("data") && current_response.data !== null) {
192                    if (typeof current_response.data === "string") {
193                        try {
194                            current_response.data = JSON.parse(current_response.data);
195                        } catch (e) {
196                            console.log("#161 Error parseando 'current_response.data' se intentará recuperar el texto que sea posible.")
197                            console.log(e);
198                            var recover_text = String(current_response.data).split('{"message":"').join("");
199                            current_response.data = {};
200                            current_response.data.message = recover_text;
201                        }
202                    }
203                    if (current_response.data.hasOwnProperty("message")) {
204                        scope_body.find(".d-post-container.student .d-content").html('<div class="d-student-message">' + current_response.data.message + '</div>');
205                    }
206                } else {
207                    scope_body.find(".d-post-container.student .d-content").html(lang.classroom_project_post_student_without_response);
208                }
209            } else {
210                scope_body.find(".d-post-container.student .d-content").html(lang.classroom_project_post_student_without_response);
211            }
212        }
213    }
214    function renderPost() {
215        if (post_ob.post.exercises_scopes.length > 0) {
216            post_ob.post.exercises_scopes[0] = "post-" + post_ob.post.exercises_scopes[0];
217        }
218
219        scope_body.find(".d-post-container.teacher").html(getHtmlPost(post_ob.post));
220        if (post_ob.post.type === "quizz") {
221            if (mDiscover.isCoreExerciseReady()) {
222                getExercise();
223            } else {
224                $(document).on("on_core_exercise_ready", function () {
225                    $(document).off("on_core_exercise_ready");
226                    console.log("EVENT 'on_core_exercise_ready' handled");
227                    getExercise();
228                });
229            }
230        }
231
232        // files
233        if (post_ob.post.hasOwnProperty("files")) {
234            for (var i = 0; i < post_ob.post.files.length; i++) {
235                scope_body.find(".d-post-container.teacher .d-files .d-file")
236                    .eq(i)
237                    .data(post_ob.post.files[i])
238                    .find(".d-info-title")
239                    .click(function () {
240                        window.open($(this).closest(".d-file").data().url, "_blank");
241                    });
242            }
243        }
244
245        renderResults();
246        // current student selected?
247        current_student_guid = mTeacherHome.getCurrentStudentGuid();
248        if (current_student_guid !== null) {
249            setTimeout(function () {
250                console.log("getCurrentStudentGuid: " + current_student_guid);
251                scope.find(".d-bar-left .d-order-by-btn[by='name']").click();
252                setTimeout(function () {
253                    $(".d-student[guid='" + current_student_guid + "']").click();
254                    if ($(".d-student[guid='" + current_student_guid + "']").length > 0) {
255                        var body = $("html, body");
256                        body.stop().animate({ scrollTop: $(".d-student[guid='" + current_student_guid + "']").position().top }, 500, 'swing', function () {
257
258                        });
259                    }
260                }, 400);
261            }, 200);
262        }
263    }
264    function openResponse($card) {
265        current_response = $card.data();
266        scope_body.find(".d-post-container.student").html(getHtmlPostStudent(current_response));
267        if (scope_body.find(".d-post-container.student .last-response-at").length > 0) {
268            mTooltip.setTooltip(scope_body.find(".d-post-container.student .last-response-at img"), scope_body.find(".d-post-container.student .last-response-at img").attr("data"));
269        } else {
270            mTooltip.setTooltip(scope_body.find(".d-post-container.student .last-response-at img"), "");
271        }
272
273        scope_body.find(".d-post-container.student").show();
274        scope_body.find(".d-post-container.teacher").hide();
275        scope_body.find(".d-post-container.student").css("margin-top", ($card.position().top - 40) + "px");
276        scope_body.find(".d-post-container.student .d-content").html(getHtmlLoader());
277        getExerciseResponse();
278        mTooltip.setTooltip(scope_body.find(".d-post-container.student .d-attemp-time"), "Tiempo empleado por el alumno para realizar la evaluación");
279        mTooltip.setTooltip(scope_body.find(".d-post-container.student .d-points"), "Puntos obtenidos por el alumno");
280        // comments
281        renderResponseComments();
282        // files
283        renderResponseFiles();
284        // close
285        scope_body.find(".d-post-container .d-header-task .d-close").click(closeResponse);
286    }
287    function renderResponseFiles() {
288        if (!current_response.hasOwnProperty("files"))
289            return;
290        var html = "";
291        var amount = current_response.files.length;
292        for (var i = 0; i < amount; i++) {
293            html += getHtmlFile(current_response.files[i]);
294        }
295        scope_body.find(".d-post-container.student .d-files").html(html);
296        // remove comment
297        for (var i = 0; i < amount; i++) {
298            scope_body.find(".d-post-container.student .d-files .d-file").eq(i)
299                .data(current_response.files[i])
300                .find(".d-info-title")
301                .click(function () {
302                    window.open($(this).closest(".d-file").data().url, "_blank");
303                });
304        }
305    }
306    function renderResponseComments() {
307        var html = "";
308        var amount = current_response.comments.length;
309        for (var i = 0;
310            i < amount;
311            i++) {
312            html += getHtmlComment(current_response.comments[i]);
313        }
314        scope_body.find(".d-post-container.student .d-comments .d-comment-list").html(html);
315        // remove comment
316        for (var i = 0;
317            i < amount;
318            i++) {
319            scope_body.find(".d-post-container.student .d-comments .d-comment-list .d-user-comment[guid='" + current_response.comments[i].guid + "']")
320                .data(current_response.comments[i])
321                .find(".d-remove")
322                .click(function () {
323                    var comment = $(this).closest(".d-user-comment").data();
324                    console.log(comment);
325                    mDiscover.showLoading();
326                    mCom.ajax("classroom-project-post/private-comment", "DELETE", comment, function (data, status) {
327                        console.log("delete private-comment () result");
328                        console.log(data);
329                        mDiscover.hideLoading();
330                        if (status === "success") {
331                            for (var i = 0;
332                                i < current_response.comments.length;
333                                i++) {
334                                if (current_response.comments[i].guid === comment.guid) {
335                                    current_response.comments.splice(i, 1);
336                                }
337                            }
338                            mToast.toast("Comentario privado borrado", 3000);
339                            renderResponseComments();
340                            scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text("");
341                        }
342                    }, function (err, status, msg) {
343                        mToast.toast("Problemas al borrar comentario", 3000);
344                        mDiscover.hideLoading();
345                    });
346                });
347        }
348
349        // add comment
350        /*
351         scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").off("keyup").on('keyup', function (e) {
352         if (e.keyCode === 13) {
353         var comment = scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text();
354         var data_ob = {task_response_guid: current_response.guid, comment: comment};
355         mDiscover.showLoading();
356         scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text("Enviando...");
357         mCom.ajax("classroom-project-post/private-comment", "POST", data_ob, function (data, status) {
358         console.log("insert private-comment result");
359         console.log(data);
360         mDiscover.hideLoading();
361         if (status === "success") {
362         current_response.comments.push(data);
363         mToast.toast("Comentario privado agregado", 3000);
364         renderResponseComments();
365         scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text("");
366         }
367         }, function (err, status, msg) {
368         mToast.toast("Problemas al agregar comentario", 3000);
369         scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text(data_ob.comment);
370         mDiscover.hideLoading();
371         });
372         }
373         });
374         */
375        scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").off("focus").on("focus", function (e) {
376            $(this).closest(".d-comment-add").find(".btn").show();
377            scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").trigger("keyup");
378        });
379        scope_body.find(".d-post-container.student .d-comments .d-comment-add .bt-comment").off("click").on("click", function (e) {
380            if ($(this).hasClass("disabled")) {
381                return;
382            } else {
383                sendComment();
384            }
385        });
386        scope_body.find(".d-post-container.student .d-comments .d-comment-add .bt-cancel").off("click").on("click", cancelComment);
387        scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").off("keyup").on('keyup', function (e) {
388            var val = $.trim($(this).text());
389            if (val !== "") {
390                $(this).closest(".d-comment-add").find(".btn.bt-comment").removeClass("disabled");
391            } else {
392                $(this).closest(".d-comment-add").find(".btn.bt-comment").addClass("disabled");
393            }
394            if (e.ctrlKey && e.keyCode === 13) {
395                sendComment();
396            }
397        });
398    }
399    function cancelComment() {
400        scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text("");
401        scope_body.find(".d-post-container.student .d-comments .d-comment-add .btn").hide();
402    }
403
404    function sendComment() {
405
406        var comment = scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").html();
407
408        comment = comment.split("<div>").join("{ENTER}").split("</div>").join("<div>");
409        comment = stripTags(comment);
410        comment = comment.split("{ENTER}").join("<br>");
411        var data_ob = { task_response_guid: current_response.guid, comment: comment };
412        mDiscover.showLoading();
413        scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text("Enviando...");
414        mCom.ajax("classroom-project-post/private-comment", "POST", data_ob, function (data, status) {
415            console.log("insert private-comment result");
416            console.log(data);
417            mDiscover.hideLoading();
418            if (status === "success") {
419                current_response.comments.push(data);
420                mToast.toast("Comentario privado agregado", 3000);
421                renderResponseComments();
422                scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text("");
423            }
424        }, function (err, status, msg) {
425            mToast.toast("Problemas al agregar comentario", 3000);
426            scope_body.find(".d-post-container.student .d-comments .d-comment-add .d-comment").text(data_ob.comment);
427            mDiscover.hideLoading();
428        });
429
430
431    }
432    function closeResponse() {
433        scope.find(".d-bar-left-list .d-student").removeClass("active standard-shadow-3");
434        scope_body.find(".d-post-container.student").hide();
435        scope_body.find(".d-post-container.teacher").show();
436    }
437    function renderResults() {
438        render_by = scope_body.find(".d-bar-left-order-by .d-order-by-btn.active").attr("by");
439        switch (render_by) {
440            case "name":
441                renderResultsByName();
442                break;
443            case "state":
444                // entregado / no entregado
445                renderResultsByState();
446                break;
447            case "score":
448                // calificados / sin calificar
449                renderResultsByScore();
450                break;
451        }
452        buildAccordion();
453        // load data
454        var amount = students_ar.length;
455        if (amount <= 0) {
456            scope.find(".d-bar-left-list").html(getHtmlStudents());
457            scope.find(".d-bar-left-list .d-student.empty a").click(function () {
458                routie("teacher/classroom/" + mTeacherHome.getClassroomGuid() + "/students");
459            });
460        } else {
461            for (var i = 0; i < amount; i++) {
462                scope.find(".d-bar-left-list .d-student").eq(i).data(students_ar[i]);
463            }
464        }
465
466        // cromo toggle
467        scope.find(".d-bar-left-list .d-student .d-cromo .d-cromo-icon").click(function (e) {
468            var post = $(this).closest(".d-student").data();
469            if ($(this).hasClass("active")) {
470                $(this).removeClass("active");
471                post.cromo = 0;
472            } else {
473                $(this).addClass("active");
474                post.cromo = 1;
475            }
476            $(this).closest(".d-student").data(post);
477            var data_ob = {
478                classroom_project_guid: mTeacherHome.getClassroomProjectGuid(),
479                post_guid: post_ob.post.guid,
480                student_guid: post.classroom_student_guid,
481                student_person_guid: post.student_guid,
482                cromo: post.cromo,
483                cromo_guid: post_ob.post.cromo_guid
484            };
485            mDiscover.showLoading();
486            mCom.ajax("classroom-project-post/cromo", "POST", data_ob, function (data, status) {
487                console.log("getPost() result");
488                console.log(data);
489                mDiscover.hideLoading();
490                if (status === "success") {
491                    mToast.toast("Asignación de cromo guardada", 3000);
492                }
493                // upd local object
494                console.log("updLocalStudentProp: " + updLocalStudentProp(data_ob.student_guid, "score", data_ob.score));
495            }, function (err, status, msg) {
496                mToast.toast("Problemas al guardar asignación", 3000);
497                mDiscover.hideLoading();
498            });
499        });
500        // select student
501        scope.find(".d-bar-left-list .d-student:not(.empty)").click(function (event) {
502            //var nodename = String(event.target.nodeName).toLowerCase();
503            if ($(event.target).closest(".d-cromo").length > 0 || $(event.target).closest(".d-points").length > 0 || $(event.target).closest(".d-checkbox").length > 0)
504                return;
505            var active = !$(this).hasClass("active");
506            if (active) {
507                scope.find(".d-bar-left-list .d-student").removeClass("active standard-shadow-3");
508                $(this).addClass("active standard-shadow-3");
509                openResponse($(this));
510            } else {
511                $(this).removeClass("active standard-shadow-3");
512                closeResponse();
513            }
514        });
515        scope_body.find(".d-bar-left input[type='checkbox']").on("change", function () {
516            if (scope_body.find(".d-bar-left-list input[type='checkbox']:checked").length > 0) {
517                scope_body.find(".d-bar-left-content-header .d-btn-return").removeClass("disabled");
518            } else {
519                scope_body.find(".d-bar-left-content-header .d-btn-return").addClass("disabled");
520            }
521        });
522        scope_body.find(".d-bar-left-content-header .d-btn-return").addClass("disabled");
523        // on change score
524        scope.find(".d-bar-left-list .d-student .d-score-input input")
525            .each(function () {
526                var score = $(this).val();
527                if (!isNaN(score) && score !== "") {
528                    var $card = $(this).closest(".d-student");
529                    var nota = getNotaByScore(score, post_ob.post.points);
530                    if (nota) {
531                        $card.find(".d-calification")
532                            .addClass("active")
533                            .find(".d-nota")
534                            .css("color", nota.color)
535                            .css("border-color", nota.color)
536                            .text(nota.Nota);
537                    }
538                }
539            })
540            .on("keyup change", function () {
541                var value = parseInt($(this).val());
542                if (value >= 0) {
543                    var $card = $(this).closest(".d-student");
544                    if (!$card.find("input[type='checkbox']").is(":checked")) {
545                        $card.find("input[type='checkbox']").click();
546                    }
547                }
548            }).off("save_changes").on("save_changes", function () {
549                var value = parseInt($(this).val());
550                var $card = $(this).closest(".d-student");
551                var student = $card.data();
552                //console.log("student.score: " + student.score + " value: " + value);
553                if (student.score !== value && !isNaN(value)) {
554                    var data_ob = { post_guid: post_ob.post.guid, student_guid: student.classroom_student_guid, score: value };
555                    //console.log(data_ob);
556                    mDiscover.showLoading();
557                    mCom.ajax("classroom-project-post/score", "POST", data_ob, function (data, status) {
558
559                        mDiscover.hideLoading();
560                        if (status === "success") {
561                            student.score = value;
562                            $card.data(student);
563                            mToast.toast(lang.classroom_project_post_score_save, 3000);
564                            var nota = getNotaByScore(data_ob.score, post_ob.post.points);
565                            if (nota) {
566                                $card.find(".d-calification")
567                                    .addClass("active")
568                                    .find(".d-nota")
569                                    .css("color", nota.color)
570                                    .css("border-color", nota.color)
571                                    .text(nota.Nota);
572                            }
573                        }
574                        // upd local object
575                        console.log("updLocalStudentProp: " + updLocalStudentProp(data_ob.student_guid, "score", data_ob.score));
576                    }, function (err, status, msg) {
577                        mToast.toast(lang.classroom_project_post_score_save_fail, 3000);
578                        mDiscover.hideLoading();
579                    });
580                } else {
581                    console.log("Score without changes");
582                }
583            }).off("blur").on("blur", function () {
584                $(this).trigger("save_changes");
585            }).off("keypress").on("keypress", function (e) {
586                if (e.which === 13) {
587                    $(this).trigger("save_changes");
588                }
589                return e.which !== 13;
590            });
591    }
592    function updLocalStudentProp(guid, prop, value) {
593        var amount = post_ob.responses.length;
594        for (var i = 0; i < amount; i++) {
595            if (post_ob.responses[i].classroom_student_guid === guid) {
596                post_ob.responses[i][prop] = value;
597                return true;
598            }
599        }
600        return false;
601    }
602
603    function renderResultsByName() {
604        var amount = post_ob.responses.length;
605        var html = '               <h3>' +
606            '                   <span class="d-arrow btn"></span>  ' +
607            '                   <span class="d-label btn">' + lang.classroom_project_post_filterby_name_label + ' <span>(' + amount + ')</span> </span>' +
608            '                   <div class="d-checkbox simple-checkbox asterisk"><input id="post-check-without-score" type="checkbox" /><label for="post-check-without-score"></label></div>' +
609            '               </h3>' +
610            '               <div class="d-container-students">';
611        students_ar = [];
612        for (var i = 0;
613            i < amount;
614            i++) {
615            html += getHtmlStudent(post_ob.responses[i]);
616            students_ar.push(post_ob.responses[i]);
617        }
618        html += '               </div>';
619        scope_body.find(".d-bar-left-list").html(html);
620    }
621    function renderResultsByState() {
622        var amount = post_ob.responses.length;
623        var amount_delivered = 0;
624        var amount_without_response = 0;
625        var amount_corrected = 0;
626        students_ar = [];
627        var html = '            <h3 class="delivered">' +
628            '                   <span class="d-arrow btn"></span>  ' +
629            '                   <span class="d-label btn">' + lang.classroom_project_post_filterby_state_label_1 + ' (<span>4</span>
629) </span>' +
630            '                   <div class="d-checkbox simple-checkbox asterisk"><input id="post-check-without-score" type="checkbox" /><label for="post-check-without-score"></label></div>' +
631            '               </h3>' +
632            '               <div class="d-container-students delivered">';
633        for (var i = 0;
634            i < amount;
635            i++) {
636            if (post_ob.responses[i].status === "delivered") {
637                html += getHtmlStudent(post_ob.responses[i]);
638                amount_delivered++;
639                students_ar.push(post_ob.responses[i]);
640            }
641        }
642        html += '               </div>';
643        html += '               <h3 class="without_response">' +
644            '                   <span class="d-arrow btn"></span>' +
645            '                   <span class="d-label btn">' + lang.classroom_project_post_filterby_state_label_2 + ' (<span>3</span>) </span>' +
646            '                   <div class="d-checkbox simple-checkbox asterisk">
646<input id="post-check-with-score" type="checkbox" /><label for="post-check-with-score"></label></div>' +
647            '               </h3>' +
648            '               <div class="d-container-students without_response">';
649        for (var i = 0;
650            i < amount;
651            i++) {
652            if (post_ob.responses[i].status !== "corrected" && post_ob.responses[i].status !== "delivered") {
653                html += getHtmlStudent(post_ob.responses[i]);
654                amount_without_response++;
655                students_ar.push(post_ob.responses[i]);
656            }
657        }
658        html += '               </div>';
659        html += '               <h3 class="corrected">' +
660            '                   <span class="d-arrow btn"></span>' +
661            '                   <span class="d-label btn">' + lang.classroom_project_post_filterby_state_label_3 + ' (<span>3</span>) </span>' +
662            '                   <div class="d-checkbox simple-checkbox asterisk"><input id="post-check-corrected" type="checkbox" /><label for="post-check-corrected"></label></div>' +
663            '               </h3>' +
664            '               <div class="d-container-students corrected">';
665        for (var i = 0;
666            i < amount;
667            i++) {
668            if (post_ob.responses[i].status === "corrected") {
669                html += getHtmlStudent(post_ob.responses[i]);
670                amount_corrected++;
671                students_ar.push(post_ob.responses[i]);
672            }
673        }
674        html += '               </div>';
675        scope_body.find(".d-bar-left-list").html(html);
676        if (amount_delivered === 0) {
677            scope_body.find(".d-bar-left-list h3.delivered").remove();
678            scope_body.find(".d-bar-left-list .d-container-students.delivered").first().remove();
679        } else {
680            scope_body.find(".d-bar-left-list h3.delivered .d-label span").html(amount_delivered);
681        }
682        if (amount_without_response === 0) {
683            scope_body.find(".d-bar-left-list h3.without_response").remove();
684            scope_body.find(".d-bar-left-list .d-container-students.without_response").remove();
685        } else {
686            scope_body.find(".d-bar-left-list h3.without_response .d-label span").html(amount_without_response);
687        }
688        if (amount_corrected === 0) {
689            scope_body.find(".d-bar-left-list h3.corrected").remove();
690            scope_body.find(".d-bar-left-list .d-container-students.corrected").remove();
691        } else {
692            scope_body.find(".d-bar-left-list h3.corrected .d-label span").last().html(amount_corrected);
693        }
694    }
695    function renderResultsByScore() {
696        var amount = post_ob.responses.length;
697        var amount_score = 0;
698        var amount_without_scored = 0;
699        students_ar = [];
700        var html = '               <h3>' +
701            '                   <span class="d-arrow btn"></span>  ' +
702            '                   <span class="d-label btn">' + lang.classroom_project_post_filterby_score_label_1 + ' (<span></span>
702) </span>' +
703            '                   <div class="d-checkbox simple-checkbox asterisk"><input id="post-check-without-score" type="checkbox" /><label for="post-check-without-score"></label></div>' +
704            '               </h3>' +
705            '               <div class="d-container-students">';
706        for (var i = 0;
707            i < amount;
708            i++) {
709            if (post_ob.responses[i].score === null) {
710                html += getHtmlStudent(post_ob.responses[i]);
711                amount_without_scored++;
712                students_ar.push(post_ob.responses[i]);
713            }
714        }
715        html += '               </div>';
716        html += '               <h3>' +
717            '                   <span class="d-arrow btn"></span>' +
718            '                   <span class="d-label btn">' + lang.classroom_project_post_filterby_score_label_2 + ' (<span></span>) </span>' +
719            '                   <div class="d-checkbox simple-checkbox asterisk"><input id="post-check-with-score" type="checkbox" /><label for="post-check-with-score"></label></div>' +
720            '               </h3>' +
721            '               <div class="d-container-students">';
722        for (var i = 0;
723            i < amount;
724            i++) {
725            if (post_ob.responses[i].score !== null) {
726                html += getHtmlStudent(post_ob.responses[i]);
727                amount_score++;
728                students_ar.push(post_ob.responses[i]);
729            }
730        }
731        '               </div>';
732        scope_body.find(".d-bar-left-list").html(html);
733        if (amount_without_scored === 0) {
734            scope_body.find(".d-bar-left-list h3").first().remove();
735        } else {
736            scope_body.find(".d-bar-left-list h3 .d-label span").first().html(amount_without_scored);
737        }
738        if (amount_score === 0) {
739            scope_body.find(".d-bar-left-list h3").last().remove();
740        } else {
741            scope_body.find(".d-bar-left-list h3 .d-label span").last().html(amount_score);
742        }
743    }
744    function buildAccordion() {
745        // accordion
746        $accordion = scope_body.find(".d-bar-left-list h3");
747        $accordion.click(function (e) {
748            var nodeName = String(e.target.nodeName).toLowerCase();
749            if (nodeName === "input" || nodeName === "label")
750                return;
751            //console.log(nodeName);
752            var $content = $(this).next();
753            if ($(this).hasClass("active")) {
754                $(this).removeClass("active");
755                $content.slideUp();
756            } else {
757                $(this).addClass("active");
758                $content.slideDown();
759            }
760
761        });
762        // check/uncheck groups
763        $accordion.find("input[type='checkbox']").on("change", function () {
764            var $content = $(this).closest("h3").next();
765            var checked = $(this).is(":checked");
766            console.log("changed: " + checked);
767            console.log($content);
768            $content.find("input[type='checkbox']").prop("checked", checked);
769        });
770        $accordion = scope_body.find(".d-bar-left-list h3").first().click();
771    }
772    function onExerciseHeight(event, data) {
773        try {
774            if (scope_body.find(".d-exercise[scope='" + data.scope + "']").length > 0) {
775                scope_body.find(".d-exercise[scope='" + data.scope + "'] .d-loader").remove();
776                scope_body.find(".d-exercise[scope='" + data.scope + "']").height(data.height + "px");
777                scope_body.find(".d-exercise[scope='" + data.scope + "'] iframe").addClass("loaded");
778            }
779            if (scope_body.find(".d-exercise-student[scope='" + data.scope + "']").length > 0) {
780                scope_body.find(".d-exercise-student[scope='" + data.scope + "'][qid='" + data.qid + "']").parent().find(".d-loader").remove();
781                scope_body.find(".d-exercise-student[scope='" + data.scope + "'][qid='" + data.qid + "']").height(data.height + "px");
782                scope_body.find(".d-exercise-student[scope='" + data.scope + "'][qid='" + data.qid + "'] iframe").addClass("loaded");
783            }
784        } catch (e) {
785            console.log(e);
786        }
787    }
788    function calcTaskResponses() {
789
790        if (!post_ob.responses.hasOwnProperty("amount_responses")) {
791
792            post_ob.amount_responses = post_ob.responses.length;
793            post_ob.amount_entregado = 0;
794            post_ob.amount_falta = 0;
795            post_ob.amount_devuelto = 0;
796            for (var m = 0; m < post_ob.amount_responses; m++) {
797                switch (post_ob.responses[m].status) {
798                    case "delivered":
799                        post_ob.amount_entregado++;
800                        break;
801                    case "corrected":
802                        //post_ob.amount_entregado++;
803                        post_ob.amount_devuelto++;
804                        break;
805                    case "undelivered":
806                    default:
807                        post_ob.amount_falta++;
808                        break;
809                }
810            }
811            if (post_ob.amount_entregado < 10)
812                post_ob.amount_entregado = "0" + post_ob.amount_entregado;
813            if (post_ob.amount_falta < 10)
814                post_ob.amount_falta = "0" + post_ob.amount_falta;
815            if (post_ob.amount_devuelto < 10)
816                post_ob.amount_devuelto = "0" + post_ob.amount_devuelto;
817        }
818    }
819
820    /**
821     * Constructor de módulo
822     * @returns {undefined}
823     */
824    function build(callback) {
825        builded = true;
826        // esqueleto de sección
827        scope.append(getHtmlSection());
828        scope_body = scope.find(">.d-teacher-classroom-project-post");
829        // modal return
830        mReturn = new TeacherClassroomProjectPostReturn(_this);
831        // order by
832        scope_body.find(".d-order-by-bg .d-order-by-btn").click(function () {
833            scope_body.find(".d-order-by-bg .d-order-by-btn").removeClass("active");
834            $(this).addClass("active");
835            renderResults();
836        });
837        // check all classroom
838        scope_body.find("#post-check-all-classroom").on("change", function () {
839            var checked = $(this).is(":checked");
840            scope_body.find(".d-bar-left-list input[type='checkbox']").prop("checked", checked);
841        });
842        $(window).off("on_exercise_height", onExerciseHeight).on("on_exercise_height", onExerciseHeight);
843        // help section
844        mTooltip.setTooltip(scope_body.find(".d-bar-left-content-header .d-btn-help"), lang.classroom_project_post_help);
845        // Devolver btn
846        scope_body.find(".d-bar-left-content-header .d-btn-return").click(function () {
847            if ($(this).hasClass("disabled"))
848                return;
849            //availableSoon();
850            var selected_ar = [];
851            scope_body.find(".d-bar-left-list .d-student input[type='checkbox']:checked").each(function () {
852                $(this).closest(".d-student").data().post_guid = post_ob.post.guid;
853                selected_ar.push($(this).closest(".d-student").data());
854            });
855            mReturn.show(selected_ar);
856        });
857        if (isFunction(callback)) {
858            callback();
859        }
860
861
862        // Show and hide left panel contents
863        scope.find('.d-button-collapse-bar-left-content').unbind('click').click(function () {
864            if (scope.find('.d-bar-left').hasClass('active')) {
865                scope.find('.d-bar-left').removeClass('active');
866            } else {
867                scope.find('.d-bar-left').addClass('active');
868                $('html,body').animate({ scrollTop: 0 }, 500, 'swing');
869            }
870        });
871        setTimeout(function () {
872            scope.find('.d-bar-left').removeClass('d-hide-temp');
873        }, 800);
874
875        // Mobile events of left panel contents
876        scope.on("swiperight", function (event) {
877            if ($('body.device-mobile').length > 0) {
878                if (!scope.find('.d-bar-left').hasClass('active')) {
879                    scope.find('.d-bar-left').addClass('active');
880                    $('html,body').animate({ scrollTop: 0 }, 500, 'swing');
881                }
882            }
883        }).on("swipeleft", function (event) {
884            if ($('body.device-mobile').length > 0) {
885                scope.find('.d-bar-left').removeClass('active');
886            }
887        });
888    }
889    /**
890     * Constructor
891     * @returns {undefined}
892     */
893    function init() {
894        // nada, latente hasta show
895    }
896    init();
897    // helpers
898    function getHtmlSection() {
899        return '<div class="d-teacher-classroom-project-post">' +
900            '   <div class="d-button-collapse-bar-left-content"></div>' +
901            ' <table border="0" width="100%"><tr>' +
902            '  <td width="510px" valign="top">' +
903            '   <div class="d-bar-left">' +
904            '       <div class="d-bar-left-content">' +
905            '           <div class="d-bar-left-content-header">' +
906            '               <div class="d-btn-return btn btn-bitmap">' + lang.classroom_project_post_btn_return + '</div>' +
907            '               <div class="d-btn-help btn btn-bitmap"></div>' +
908            '           </div>' +
909            '           <div class="d-bar-left-separator"></div>' +
910            '           <div class="d-bar-left-classroom">' +
911            '               <div class="d-avatar"></div>' +
912            '               <div class="d-name truncate"></div>' +
913            '               <div class="d-checkbox simple-checkbox asterisk"><input id="post-check-all-classroom" type="checkbox" /><label for="post-check-all-classroom"></label></div>' +
914            '           </div>' +
915            '           <div class="d-bar-left-order-by">' +
916            '               <div class="d-order-by-bg">' +
917            '                   <div class="d-order-by-btn btn" by="name">' + lang.classroom_project_post_filterby_name + '</div>' +
918            '                   <div class="d-order-by-btn active btn" by="state">' + lang.classroom_project_post_filterby_state + '</div>' +
919            '                   <div class="d-order-by-btn btn" by="score">' + lang.classroom_project_post_filterby_score + '</div>' +
920            '               </div>' +
921            '           </div>' +
922            '           <div class="d-bar-left-list">' +
923            '           </div>' +
924            '       </div>' +
925            '   </div>' +
926            '   </td><td valign="top">' +
927            '   <div class="d-post-container teacher">' +
928            '   </div>' +
929            '   <div class="d-post-container student">' +
930            '   </div>' +
931            '   </td>' +
932            '  </tr></table>' +
933            '</div>';
934    }
935
936    function getHtmlPostStudent(response) {
937        var card = "";
938        var points_html = (post_ob.post.type === "quizz") ? '<div class="d-points"><div>' + lang.classroom_project_post_points_label + '</div><span>-</span></div>' : '';
939        var time_html = "";
940        console.log(response);
941        if (post_ob.post.type === "quizz") {
942            if (response.hasOwnProperty("data")) {
943                if (typeof response.data === "string") {
944                    if (response.data !== "")
945                        response.data = JSON.parse(response.data);
946                }
947                if (response.data) {
948                    if (response.data.hasOwnProperty("time")) {
949                        time_html = '<div class="d-attemp-time"><div class="d-icon btn btn-bitmap"></div> <span>' + response.data.time + '</span></div>';
950                    }
951                }
952            }
953        }
954        var response_date = "";
955        if (response.last_response_at !== null) {
956            var info = lang.classroom_project_post_response_at + '<br> ' + response.response_at;
957            if (response.response_at !== response.last_response_at) {
958                info += '<br/><br/>' + lang.classroom_project_post_lastresponse_at + '<br/> ' + response.last_response_at;
959            }
960            response_date = '<div class="last-response-at">' + response.last_response_at + '<img src="css/img/btn_help.png" data="' + info + '" /> </div>';
961        }
962        var label_reset = (post_ob.post.type === "task") ? lang.classroom_project_post_reset_task : lang.classroom_project_post_reset_test;
963        var avatar = getHtmlStudentAvatar(response, "x-small");
964        card = '           <div class="d-card d-post" guid="' + response.classroom_student_guid + '">' +
965            '               <div class="d-header-task">' +
966            '                   <div class="d-icon-avatar">' + avatar + '</div>' +
967            '                   <div class="d-username">' + getStudentName(response) + '</div>' +
968            '                   ' + points_html +
969            '                   ' + time_html +
970            '                   ' + response_date +
971            '                   <div class="d-close btn btn-bitmap"></div>' +
972            '                   <div class="d-reset-test btn btn-bitmap standard-text-shadow-2 standard-shadow-1">' + label_reset + '</div>' +
973            '               </div>' +
974            '               <div class="d-content">' +
975            '               </div>' +
976            '               <div class="d-files"></div>' +
977            '               ' + getHtmlComments() +
978            '           </div> <!-- End CARD -->';
979        return card;
980    }
981
982    function getHtmlPost(post) {
983        var card = "";
984        var username = (post.is_student === "true") ? getStudentName(post) : getParentName(post);
985        var student_teacher_class = (post.is_student === "true") ? "student" : "teacher";
986        var avatar = (post.is_student === "true") ? getHtmlStudentAvatar(post, "x-small") : getHtmlTeacherAvatar(post, "x-small");
987        var options_btn = (post.is_owner === "true") ? '<div class="d-icon"></div>' : '';
988        var cromo_html = (post.cromo_guid !== null) ? '<div class="d-post-with-cromo"></div>' : '';
989        var end_at_html = (post.task_end_at !== null) ? '<div class="d-end-at standard-text-shadow-2">' + lang.classroom_project_post_task_end_at + mDatetime.getFormatedDateFromISO(post.task_end_at) + '</div>' : "";
990        if (post.creator_alias > 0) {
991            avatar = '<div class="alias alias' + post.creator_alias + '"></div>';
992            username = lang["classroom_project_post_alias" + post.creator_alias];
993        }
994        var htmlFiles = "";
995        if (post.hasOwnProperty("files")) {
996            htmlFiles += '<div class="d-files">';
997            for (var i = 0; i < post.files.length; i++) {
998                htmlFiles += getHtmlFile(post.files[i]);
999            }
1000            htmlFiles += '</div>';
1001        }
1002        switch (post.type) {
1003            case "task":
1004                card = '           <div class="d-card d-post d-task t_task" guid="' + post.guid + '">' +
1005                    '               <div class="d-header-task">' +
1006                    '                   <div class="d-icon-avatar">' + avatar + '</div>' +
1007                    '                   <div class="d-username">' + username + '</div>' +
1008                    '                   <div class="d-post-to">' + getPostToResumed(post) + '</div>' +
1009                    '                   <div class="d-time">' + getElapsedTimeMDM(post.created_at_mdm) + '</div>' +
1010                    '                   ' + getHtmlResponses(post) +
1011                    '                   <div class="btn d-action-config">' + options_btn + '</div>' +
1012                    '                       ' + getHtmlPostContextual(post) +
1013                    '                   <div class="d-wood-bar">' +
1014                    '                       <div class="d-icon"></div>' +
1015                    '                       <div class="d-points-label"><span class="d-amount">' + post.points + '</span><span class="d-label">' + lang.classroom_project_popup_post_points + '</span></div>' +
1016                    '                       ' + cromo_html +
1017                    '                       ' + end_at_html +
1018                    '                   </div>' +
1019                    '               </div>' +
1020                    '               <div class="d-content">' +
1021                    '                   <div class="d-message">' +
1022                    '                       <div class="d-title">' + post.title + '</div>' +
1023                    '                       <div class="d-description">' + post.description + '</div>' +
1024                    '                   </div>' +
1025                    '               </div>' +
1026                    '               ' + htmlFiles +
1027                    '               ' + getHtmlComments() +
1028                    '           </div> <!-- End CARD -->';
1029                break;
1030            case "quizz":
1031                var exercise_html = "";
1032                if (post.exercises) {
1033                    for (var i = 0; i < post.exercises.length; i++) {
1034                        exercise_html += '<div class="d-exercise" scope="' + post.exercises_scopes[i] + '">' + getHtmlLoader() + '</div>';
1035                    }
1036                }
1037                if (post.points === null)
1038                    post.points = 0;
1039                card = '           <div class="d-card d-post d-task t_quizzes" guid="' + post.guid + '">' +
1040                    '               <div class="d-header-task">' +
1041                    '                   <div class="d-icon-avatar">' + avatar + '</div>' +
1042                    '                   <div class="d-username">' + username + '</div>' +
1043                    '                   <div class="d-post-to">' + getPostToResumed(post) + '</div>' +
1044                    '                   <div class="d-time">' + getElapsedTimeMDM(post.created_at_mdm) + '</div>' +
1045                    '                   ' + getHtmlResponses(post) +
1046                    '                   <div class="btn d-action-config">' + options_btn + '</div>' +
1047                    '                       ' + getHtmlPostContextual(post) +
1048                    '                   <div class="d-wood-bar">' +
1049                    '                       <div class="d-quizz-icon"></div>' +
1050                    '                       <div class="d-points-label"><span class="d-amount">' + post.points + '</span><span class="d-label">' + lang.classroom_project_popup_post_points + '</span></div>' +
1051                    '                       ' + cromo_html +
1052                    '                       ' + end_at_html +
1053                    '                   </div>' +
1054                    '               </div>' +
1055                    '               <div class="d-content">' +
1056                    '                   <div class="d-message">' +
1057                    '                       ' + exercise_html +
1058                    '                   </div>' +
1059                    '               </div>' +
1060                    '               ' + getHtmlComments() +
1061                    '           </div> <!-- End CARD -->';
1062                break;
1063        }
1064        return card;
1065    }
1066
1067    function getHtmlComments() {
1068        var post = post_ob.post;
1069        return '<div class="d-comments">' +
1070            '   <div class="d-comment-list"></div>' +
1071            '   <div class="d-comment-add">' +
1072            '       <div class="d-avatar">' + getHtmlTeacherAvatar(post, "x-small") + '</div>' +
1073            '       <div class="d-comment" contenteditable="true" placeholder="' + lang.classroom_project_post_add_comment + '"></div>' +
1074            '       <div class="btn orange bt-comment">' + lang.classroom_project_comment_send + '</div>' +
1075            '       <div class="btn default bt-cancel">' + lang.classroom_project_comment_cancel + '</div>' +
1076            '   </div>' +
1077            '</div>';
1078    }
1079    function getHtmlComment(comment) {
1080
1081        var avatar = (comment.is_owner !== "true") ? getHtmlStudentAvatar(current_response, "x-small") : getHtmlTeacherAvatar(mDiscover.getUser(), "x-small");
1082        var remove_html = (comment.is_owner === "true") ? '<div class="d-remove btn btnBitmap"></div>' : '';
1083        var post = post_ob.post;
1084        return '   <div class="d-user-comment" guid="' + comment.guid + '">' +
1085            '       <div class="d-avatar">' + avatar + '</div>' +
1086            '       <div class="d-comment">' + comment.comment + '</div>' +
1087            '       ' + remove_html +
1088            '   </div>';
1089    }
1090
1091    function getHtmlStudents() {
1092        return '<div class="d-student empty" >' +
1093            '   <div class="d-icon"></div>' +
1094            '   <div class="d-message">' +
1095            lang.classroom_project_post_empty +
1096            '   </div>' +
1097            '</div>';
1098    }
1099    function getHtmlStudent(student) {
1100        var points = (post_ob.post.points !== null) ? post_ob.post.points : "-";
1101        var class_cromo = (student.cromo === 1) ? 'active' : '';
1102        var cromo_html = '';
1103        if (post_ob.post.cromo_guid !== null) {
1104            cromo_html = '   <div class="d-cromo">' +
1105                '       <div class="d-cromo-label">' + lang.classroom_project_post_cromo_label + '</div>' +
1106                '       <div class="d-cromo-icon ' + class_cromo + '" style="background-image:url(css/img/case/cromo-' + post_ob.post.cromo_icon + '.png);"></div>' +
1107                '   </div>';
1108        }
1109        return '<div class="d-student" guid="' + student.classroom_student_guid + '">' +
1110            '   <div class="d-avatar">' + getHtmlStudentAvatar(student, 'x-small') + '</div>' +
1111            '   <div class="d-name">' + getStudentName(student) + '</div>' +
1112            '   <div class="d-checkbox simple-checkbox asterisk"><input id="post-check-student-guid-' + student.classroom_student_guid + '" type="checkbox" /><label for="post-check-student-guid-' + student.classroom_student_guid + '"></label></div>' +
1113            '   <div class="d-calification">' +
1114            '       <div class="d-nota"></div>' +
1115            '   </div>' +
1116            '   ' + cromo_html +
1117            '   <div class="d-points">' +
1118            '       <div class="d-score-input"><input type="number" class="simple-input" value="' + student.score + '" min="100" max="1000" /></div>' +
1119            '       <div class="d-points-label">' + lang.classroom_project_post_points_label + '</div>' +
1120            '       <div class="d-points-number">' + points + '</div>' +
1121            '   </div>' +
1122            '</div>';
1123    }
1124    function getHtmlFile(file) {
1125        var fileSize = humanFileSize(file.sizeBytes, true);
1126        var fileSizeClass = (fileSize === "") ? "without-size" : "";
1127        return '<div class="d-file ' + fileSizeClass + '">' +
1128            '   <div class="d-icon-container">' +
1129            '       <div class="d-icon" style="background-image:url(' + file.iconUrl + ');"></div>' +
1130            '   </div>' +
1131            '   <div class="d-info">' +
1132            '       <div class="d-info-title truncate">' + file.name + '</div>' +
1133            '       <div class="d-info-type truncate">' + file.mimeType + '</div>' +
1134            '       <div class="d-info-size truncate">' + fileSize + '</div>' +
1135            '   </div>' +
1136            '   <div class="d-button btn-remove">X</div>' +
1137            '</div>';
1138    }
1139    function getHtmlResponses(post) {
1140
1141        calcTaskResponses();
1142        return '                   <div class="d-tracing">' +
1143            '                       <div class="d-tracing-done">' +
1144            '                           <div class="d-tracing-done-counter d-counter"><span>' + post_ob.amount_entregado + '</span></div>' +
1145            '                           <div class="d-tracing-done-label d-label">' + lang.classroom_project_post_saved_tracing_done + '</div>' +
1146            '                       </div>' +
1147            '                       <div class="d-tracing-missing">' +
1148            '                           <div class="d-tracing-missing d-counter"><span>' + post_ob.amount_falta + '</span></div>' +
1149            '                           <div class="d-tracing-missing-label d-label">' + lang.classroom_project_post_saved_tracing_missing + '</div>' +
1150            '                       </div>' +
1151            '                       <div class="d-tracing-corrected">' +
1152            '                           <div class="d-tracing-corrected d-counter"><span>' + post_ob.amount_devuelto + '</span></div>' +
1153            '                           <div class="d-tracing-corrected-label d-label">' + lang.classroom_project_post_saved_tracing_corrected + '</div>' +
1154            '                       </div>' +
1155            '                   </div>';
1156    }
1157
1158    function getHtmlPostContextual(post) {
1159        var open_li = (post.type === "message") ? '' : '<li><a href="javascript:void(0);" action="open">Abrir</a></li>';
1160        return '<div class="dropdown">' +
1161            '   <ul class="dropdown-content">' +
1162            '       ' + open_li +
1163            '       <li><a href="javascript:void(0);" action="edit">Editar</a></li>' +
1164            '       <li class="divider"></li>' +
1165            '       <li><a href="javascript:void(0);" action="remove">Borrar</a></li>' +
1166            '   </ul>' +
1167            '</div>';
1168    }
1169
1170    function getHtmlLoader() {
1171        return '<div class="d-loader"><img src="css/img/loading_gears.gif" /></div>';
1172    }
1173
1174
1175    // public methods
1176    this.show = show;
1177    // evento: devolución realizada
1178    this.onReturnComplete = function () {
1179        doStart();
1180    };
1181}
1182    ;

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.