<commit_before>$(function () {

    $body = $("body");
    $(document).on({
        ajaxStart: function () { $body.addClass("loading"); },
        ajaxStop: function () { $body.removeClass("loading"); }
    });

    GetRelatedClasses($("#selected-subject").val());

    $("#score-search-button").click(function () {
        LoadGridScores();
    });

    $("#selected-subject").on('change', function () {
        GetRelatedClasses($(this).val());
    });

    function GetRelatedClasses(subject) {
        $.ajax({
            url: "/Score/GetRelatedClasses",
            dataType: "json",
            data: { selectedSubject: subject }
        }).done(function (response) {
            if (response.classes.length > 0) {
                $("#selected-class").empty();
                $.each(response.classes, function (index, element) {
                    $('#selected-class')
                        .append($("<option></option>")
                                   .attr("value", element.Id)
                                   .text(element.Name));
                });
            }
        });
    }

    function LoadGridScores() {
        var selectedClass = $("#selected-class").val();
        var selectedYear = $("#selected-year").val();
        var selectedTrimester = $("#selected-trimester").val();
        var selectedSubject = $("#selected-subject").val();

        $.ajax({
            url: "/Score/LoadScores",
            dataType: "html",
            data: { selectedClass: selectedClass, selectedYear: selectedYear, selectedTrimester: selectedTrimester, selectedSubject: selectedSubject }
        }).done(function (response) {
            var jsonResult;
            try {
                jsonResult = JSON.parse(response);
                var errorMessage = $("#error-searching-scores .error-message");
                errorMessage.empty().html(jsonResult.responseText);
                errorMessage.show();
                errorMessage.fadeOut(5000);
            }
            catch (e) {
                $("#scores-container").empty().html(response);
                UpdateZeroAsistanceFields();
                CalculateAllAverageAndConcept();
                bindScoreGridEvents();
            };
        });
    }

    function PointsToCalculateExamPercentageAndScore(examPointsField) {
        var studentEntry = examPointsField.parent().parent();
        var examId = examPointsField.attr('data-exam-id');
        var examPercentageField = studentEntry.find("input.exam-percentage[data-exam-id='" + examId + "']");
        var examScoreField = studentEntry.find("input.exam-score[data-exam-id='" + examId + "']");

        if (examPercentageField != null && examPercentageField != undefined) {
            var examMaxPercentage = examPercentageField.attr('max');
            var examMaxPoints = examPointsField.attr('max');
            var score = Math.round(((parseFloat(examPointsField.val()) * 100) / parseFloat(examMaxPoints)) * 10) / 10;
            var percentage = Math.round((score * ((parseFloat(examMaxPercentage) / 100))) * 10) / 10;
            examScoreField.val(score);
            examPercentageField.val(percentage);
        }
    }

    function ScoreToCalculateExamPercentageAndPoints(examScoreField) {
        var studentEntry = examScoreField.parent().parent();
        var examId = examScoreField.attr('data-exam-id');
        var examPercentageField = studentEntry.find("input.exam-percentage[data-exam-id='" + examId + "']");
        var examPointsField = studentEntry.find("input.exam-points[data-exam-id='" + examId + "']");

        if (examPercentageField != null && examPercentageField != undefined) {
            var examMaxPercentage = examPercentageField.attr('max');
            var examMaxPoints = examPointsField.attr('max');

            var points = Math.round(((parseFloat(examScoreField.val()) * parseFloat(examMaxPoints)) / 100) * 10) / 10;
            var percentage = Math.round((parseFloat(examScoreField.val()) * (parseFloat(examMaxPercentage) / 100)) * 10) / 10;

            examPointsField.val(points);
            examPercentageField.val(percentage);
        }
    }

    function ScoreToCalculateExtraclassPercentage(extraclassScoreField)
    {
        var studentEntry = extraclassScoreField.parent().parent();
        var extraclassId = extraclassScoreField.attr('data-extraclass-id');
        var extraclassPercentageField = studentEntry.find("input.extraclass-percentage[data-extraclass-id='" + extraclassId + "']");

        if (extraclassPercentageField != null && extraclassPercentageField != undefined)
        {
            var extraclassMaxPercentage = extraclassPercentageField.attr('max');
            var percentage = Math.round((parseFloat(extraclassScoreField.val()) * (parseFloat(extraclassMaxPercentage) / 100)) * 10) / 10;
            extraclassPercentageField.val(percentage);
        }
    }

    function ScoreToCalculateDailyWorkPercentage(dailyWorkScoreField) {
        var studentEntry = dailyWorkScoreField.parent().parent();
        var dailyWorkPercentageField = studentEntry.find("#DailyWorkPercentage");

        if (dailyWorkPercentageField != null && dailyWorkPercentageField != undefined) {
            var dailyWorkMaxPercentage = dailyWorkPercentageField.attr('max');
            var percentage = Math.round((parseFloat(dailyWorkScoreField.val()) * (parseFloat(dailyWorkMaxPercentage) / 100)) * 10) / 10;
            dailyWorkPercentageField.val(percentage);
        }
    }

    function CalculateConcept(studentEntry) {
        var concept = 0;

        var examScoreFields = studentEntry.find("input.exam-score");
        examScoreFields.each(function () {
            concept += parseFloat($(this).val());
        });

        var extraclassPercentageFields = studentEntry.find("input.extraclass-score");
        extraclassPercentageFields.each(function () {
            concept += (parseFloat($(this).val()) * 100) / $(this).attr('max');
        });

        concept += parseFloat(studentEntry.find("#DailyWorkScore").val());
        var maxConceptPercentage = parseFloat(studentEntry.find("#ConceptPercentage").attr('max'));

        var roundConcept = Math.round(((concept / 4) * (maxConceptPercentage / 100)) * 10) / 10;

        if (roundConcept > maxConceptPercentage) {
            roundConcept = maxConceptPercentage;
        }

        return roundConcept;
    }

    function CalculateAverage(studentEntry) {
        var average = 0;

        var examPercentageFields = studentEntry.find("input.exam-percentage");
        examPercentageFields.each(function () {
            average += parseFloat($(this).val());
        });

        var extraclassPercentageFields = studentEntry.find("input.extraclass-percentage");
        extraclassPercentageFields.each(function () {
            average += parseFloat($(this).val());
        });

        average += parseFloat(studentEntry.find("#DailyWorkPercentage").val());
        average += parseFloat(studentEntry.find("#ConceptPercentage").val());
        average += parseFloat(studentEntry.find("#AssistancePercentage").val());

        return Math.round(average);
    }

    function CalculateAllAverageAndConcept()
    {
        var studentScores = $(".score-item");

        studentScores.each(function () {
            var concept = CalculateConcept($(this));
            $(this).find("#ConceptPercentage").val(concept);
            var average = CalculateAverage($(this));
            $(this).find("#Average").val(average);
        });
    }

    function CalculateAssitance(assistanceRelatedField) {
        var studentEntry = assistanceRelatedField.parent().parent();
        var Belated = studentEntry.find("#Belated").val();
        var Absences = studentEntry.find("#Absences").val();
        var AssistanceField = studentEntry.find("#AssistancePercentage");
        var NumberOfLessons = studentEntry.find("#NumberOfLessons").val();

        var percentage = ((parseInt(Absences) + (parseInt(Belated) / 3)) * 100) / parseInt(NumberOfLessons);
        var assistancePercentage = 0;

        if (percentage === 0)
        {
            assistancePercentage = 5;
        }
        else if (percentage >= 1 && percentage <= 12)
        {
            assistancePercentage = 4;
        }
        else if (percentage >= 13 && percentage <= 25)
        {
            assistancePercentage = 3;
        }
        else if (percentage >= 26 && percentage <= 38)
        {
            assistancePercentage = 2;
        }
        else if (percentage >= 39 && percentage <= 50)
        {
            assistancePercentage = 1;
        }

        AssistanceField.val(assistancePercentage);
    }

    function UpdateZeroAsistanceFields() {
        var studentScores = $(".score-item");

        studentScores.each(function () {
            var studentEntry = $(this);
            var AssistanceField = studentEntry.find("#AssistancePercentage");
            var MaxAssistancePercentage = AssistanceField.attr('max');

            if (AssistanceField.val() === '0' && MaxAssistancePercentage != null) {
                AssistanceField.val(MaxAssistancePercentage);
            }
        });
    }

    function bindScoreGridEvents() {

        $(".assistance-related-field").on('change', function () {
            CalculateAssitance($(this));
        });

        $(".exam-points").on('change', function () {
            PointsToCalculateExamPercentageAndScore($(this));
        });

        $(".exam-score").on('change', function () {
            ScoreToCalculateExamPercentageAndPoints($(this));
        });

        $(".extraclass-score").on('change', function () {
            ScoreToCalculateExtraclassPercentage($(this));
        });

        $(".daily-work-score").on('change', function () {
            ScoreToCalculateDailyWorkPercentage($(this));
        });

        $(".exam-score, .exam-points, .extraclass-score, .assistance-related-field, .daily-work-score, #AssistancePercentage").on('change', function () {
            var studentEntry = $(this).parent().parent();
            var concept = CalculateConcept(studentEntry);
            studentEntry.find("#ConceptPercentage").val(concept);
            var average = CalculateAverage(studentEntry);
            studentEntry.find("#Average").val(average);
        });

        $('.scores-save-button').on('click', function () {

            var studentScores = $(".score-item");
            var Scores = [];

            studentScores.each(function () {
                var studentEntry = $(this);
                var StudentId = studentEntry.find("#StudentId").val();
                var ScoreId = studentEntry.find("#ScoreId").val();
                var ClassId = $("#selected-class").val();
                var YearCreated = $("#selected-year").val();
                var RegisterProfileId = studentEntry.find("#RegisterProfileId").val();
                var DailyWorkPercentage = studentEntry.find("#DailyWorkPercentage").val();
                var DailyWorkScore = studentEntry.find("#DailyWorkScore").val();
                var Absences = studentEntry.find("#Absences").val();
                var Belated = studentEntry.find("#Belated").val();
                var AssistancePercentage = studentEntry.find("#AssistancePercentage").val();
                var ConceptPercentage = studentEntry.find("#ConceptPercentage").val();

                var examScoreFields = studentEntry.find(".exam-score");
                var ExamResults = [];

                examScoreFields.each(function () {
                    var examId = $(this).attr('data-exam-id');
                    var examScore = $(this).val();
                    var examPercentageField = studentEntry.find("input.exam-percentage[data-exam-id='" + examId + "']");
                    var examPointsField = studentEntry.find("input.exam-points[data-exam-id='" + examId + "']");

                    var Exam =
                    {
                        "ExamId": examId,
                        "ExamScore": examScore,
                        "ExamPoints": examPointsField.val(),
                        "ExamPercentage": examPercentageField.val(),
                    };

                    ExamResults.push(Exam);
                });

                var extraclassWorkFields = studentEntry.find(".extraclass-percentage");
                var ExtraclasWorkResults = [];

                extraclassWorkFields.each(function () {
                    var extraclassId = $(this).attr('data-extraclass-id');
                    var extraclassPercentage = $(this).val();
                    var extraclassPointsField = studentEntry.find("input.extraclass-score[data-extraclass-id='" + extraclassId + "']");

                    var ExtraclassWork =
                    {
                        "ExtraclassWorkId": extraclassId,
                        "ExtraclassWorkPercentage": extraclassPercentage,
                        "ExtraclassWorkScore": extraclassPointsField.val()
                    };

                    ExtraclasWorkResults.push(ExtraclassWork);
                });

                var ScoreModel =
                {
                    "Id": ScoreId,
                    "StudentId": StudentId,
                    "ClassId": ClassId,
                    "YearCreated": YearCreated,
                    "RegisterProfileId": RegisterProfileId,
                    "DailyWorkPercentage": DailyWorkPercentage,
                    "DailyWorkScore": DailyWorkScore,
                    "Absences": Absences,
                    "Belated": Belated,
                    "AssistancePercentage": AssistancePercentage,
                    "ConceptPercentage": ConceptPercentage,
                    "ExamResults": ExamResults,
                    "ExtraclasWorkResults": ExtraclasWorkResults
                };

                Scores.push(ScoreModel);
            })

            //Send a list of scores
            $.ajax({
                url: '/Score/Save/',
                data: JSON.stringify(Scores),
                type: 'POST',
                contentType: 'application/json; charset=utf-8',
                success: function (data) {
                    LoadGridScores();
                }
            });

        });

    }
})<commit_msg>Fix issue calculating absences<commit_after>$(function () {

    $body = $("body");
    $(document).on({
        ajaxStart: function () { $body.addClass("loading"); },
        ajaxStop: function () { $body.removeClass("loading"); }
    });

    GetRelatedClasses($("#selected-subject").val());

    $("#score-search-button").click(function () {
        LoadGridScores();
    });

    $("#selected-subject").on('change', function () {
        GetRelatedClasses($(this).val());
    });

    function GetRelatedClasses(subject) {
        $.ajax({
            url: "/Score/GetRelatedClasses",
            dataType: "json",
            data: { selectedSubject: subject }
        }).done(function (response) {
            if (response.classes.length > 0) {
                $("#selected-class").empty();
                $.each(response.classes, function (index, element) {
                    $('#selected-class')
                        .append($("<option></option>")
                                   .attr("value", element.Id)
                                   .text(element.Name));
                });
            }
        });
    }

    function LoadGridScores() {
        var selectedClass = $("#selected-class").val();
        var selectedYear = $("#selected-year").val();
        var selectedTrimester = $("#selected-trimester").val();
        var selectedSubject = $("#selected-subject").val();

        $.ajax({
            url: "/Score/LoadScores",
            dataType: "html",
            data: { selectedClass: selectedClass, selectedYear: selectedYear, selectedTrimester: selectedTrimester, selectedSubject: selectedSubject }
        }).done(function (response) {
            var jsonResult;
            try {
                jsonResult = JSON.parse(response);
                var errorMessage = $("#error-searching-scores .error-message");
                errorMessage.empty().html(jsonResult.responseText);
                errorMessage.show();
                errorMessage.fadeOut(5000);
            }
            catch (e) {
                $("#scores-container").empty().html(response);
                UpdateZeroAsistanceFields();
                CalculateAllAverageAndConcept();
                bindScoreGridEvents();
            };
        });
    }

    function PointsToCalculateExamPercentageAndScore(examPointsField) {
        var studentEntry = examPointsField.parent().parent();
        var examId = examPointsField.attr('data-exam-id');
        var examPercentageField = studentEntry.find("input.exam-percentage[data-exam-id='" + examId + "']");
        var examScoreField = studentEntry.find("input.exam-score[data-exam-id='" + examId + "']");

        if (examPercentageField != null && examPercentageField != undefined) {
            var examMaxPercentage = examPercentageField.attr('max');
            var examMaxPoints = examPointsField.attr('max');
            var score = Math.round(((parseFloat(examPointsField.val()) * 100) / parseFloat(examMaxPoints)) * 10) / 10;
            var percentage = Math.round((score * ((parseFloat(examMaxPercentage) / 100))) * 10) / 10;
            examScoreField.val(score);
            examPercentageField.val(percentage);
        }
    }

    function ScoreToCalculateExamPercentageAndPoints(examScoreField) {
        var studentEntry = examScoreField.parent().parent();
        var examId = examScoreField.attr('data-exam-id');
        var examPercentageField = studentEntry.find("input.exam-percentage[data-exam-id='" + examId + "']");
        var examPointsField = studentEntry.find("input.exam-points[data-exam-id='" + examId + "']");

        if (examPercentageField != null && examPercentageField != undefined) {
            var examMaxPercentage = examPercentageField.attr('max');
            var examMaxPoints = examPointsField.attr('max');

            var points = Math.round(((parseFloat(examScoreField.val()) * parseFloat(examMaxPoints)) / 100) * 10) / 10;
            var percentage = Math.round((parseFloat(examScoreField.val()) * (parseFloat(examMaxPercentage) / 100)) * 10) / 10;

            examPointsField.val(points);
            examPercentageField.val(percentage);
        }
    }

    function ScoreToCalculateExtraclassPercentage(extraclassScoreField)
    {
        var studentEntry = extraclassScoreField.parent().parent();
        var extraclassId = extraclassScoreField.attr('data-extraclass-id');
        var extraclassPercentageField = studentEntry.find("input.extraclass-percentage[data-extraclass-id='" + extraclassId + "']");

        if (extraclassPercentageField != null && extraclassPercentageField != undefined)
        {
            var extraclassMaxPercentage = extraclassPercentageField.attr('max');
            var percentage = Math.round((parseFloat(extraclassScoreField.val()) * (parseFloat(extraclassMaxPercentage) / 100)) * 10) / 10;
            extraclassPercentageField.val(percentage);
        }
    }

    function ScoreToCalculateDailyWorkPercentage(dailyWorkScoreField) {
        var studentEntry = dailyWorkScoreField.parent().parent();
        var dailyWorkPercentageField = studentEntry.find("#DailyWorkPercentage");

        if (dailyWorkPercentageField != null && dailyWorkPercentageField != undefined) {
            var dailyWorkMaxPercentage = dailyWorkPercentageField.attr('max');
            var percentage = Math.round((parseFloat(dailyWorkScoreField.val()) * (parseFloat(dailyWorkMaxPercentage) / 100)) * 10) / 10;
            dailyWorkPercentageField.val(percentage);
        }
    }

    function CalculateConcept(studentEntry) {
        var concept = 0;

        var examScoreFields = studentEntry.find("input.exam-score");
        examScoreFields.each(function () {
            concept += parseFloat($(this).val());
        });

        var extraclassPercentageFields = studentEntry.find("input.extraclass-score");
        extraclassPercentageFields.each(function () {
            concept += (parseFloat($(this).val()) * 100) / $(this).attr('max');
        });

        concept += parseFloat(studentEntry.find("#DailyWorkScore").val());
        var maxConceptPercentage = parseFloat(studentEntry.find("#ConceptPercentage").attr('max'));

        var roundConcept = Math.round(((concept / 4) * (maxConceptPercentage / 100)) * 10) / 10;

        if (roundConcept > maxConceptPercentage) {
            roundConcept = maxConceptPercentage;
        }

        return roundConcept;
    }

    function CalculateAverage(studentEntry) {
        var average = 0;

        var examPercentageFields = studentEntry.find("input.exam-percentage");
        examPercentageFields.each(function () {
            average += parseFloat($(this).val());
        });

        var extraclassPercentageFields = studentEntry.find("input.extraclass-percentage");
        extraclassPercentageFields.each(function () {
            average += parseFloat($(this).val());
        });

        average += parseFloat(studentEntry.find("#DailyWorkPercentage").val());
        average += parseFloat(studentEntry.find("#ConceptPercentage").val());
        average += parseFloat(studentEntry.find("#AssistancePercentage").val());

        return Math.round(average);
    }

    function CalculateAllAverageAndConcept()
    {
        var studentScores = $(".score-item");

        studentScores.each(function () {
            var concept = CalculateConcept($(this));
            $(this).find("#ConceptPercentage").val(concept);
            var average = CalculateAverage($(this));
            $(this).find("#Average").val(average);
        });
    }

    function CalculateAssitance(assistanceRelatedField) {
        var studentEntry = assistanceRelatedField.parent().parent();
        var Belated = studentEntry.find("#Belated").val();
        var Absences = studentEntry.find("#Absences").val();
        var AssistanceField = studentEntry.find("#AssistancePercentage");
        var NumberOfLessons = studentEntry.find("#NumberOfLessons").val();

        var percentage = ((parseInt(Absences) + (parseInt(Belated) / 3)) * 100) / parseInt(NumberOfLessons);
        var assistancePercentage = 0;

        if (percentage === 0)
        {
            assistancePercentage = 5;
        }
        else if (percentage > 0 && percentage <= 12)
        {
            assistancePercentage = 4;
        }
        else if (percentage > 12 && percentage <= 25)
        {
            assistancePercentage = 3;
        }
        else if (percentage > 25 && percentage <= 38)
        {
            assistancePercentage = 2;
        }
        else if (percentage > 38 && percentage <= 50)
        {
            assistancePercentage = 1;
        }

        AssistanceField.val(assistancePercentage);
    }

    function UpdateZeroAsistanceFields() {
        var studentScores = $(".score-item");

        studentScores.each(function () {
            var studentEntry = $(this);
            var AssistanceField = studentEntry.find("#AssistancePercentage");
            var MaxAssistancePercentage = AssistanceField.attr('max');

            if (AssistanceField.val() === '0' && MaxAssistancePercentage != null) {
                AssistanceField.val(MaxAssistancePercentage);
            }
        });
    }

    function bindScoreGridEvents() {

        $(".assistance-related-field").on('change', function () {
            CalculateAssitance($(this));
        });

        $(".exam-points").on('change', function () {
            PointsToCalculateExamPercentageAndScore($(this));
        });

        $(".exam-score").on('change', function () {
            ScoreToCalculateExamPercentageAndPoints($(this));
        });

        $(".extraclass-score").on('change', function () {
            ScoreToCalculateExtraclassPercentage($(this));
        });

        $(".daily-work-score").on('change', function () {
            ScoreToCalculateDailyWorkPercentage($(this));
        });

        $(".exam-score, .exam-points, .extraclass-score, .assistance-related-field, .daily-work-score, #AssistancePercentage").on('change', function () {
            var studentEntry = $(this).parent().parent();
            var concept = CalculateConcept(studentEntry);
            studentEntry.find("#ConceptPercentage").val(concept);
            var average = CalculateAverage(studentEntry);
            studentEntry.find("#Average").val(average);
        });

        $('.scores-save-button').on('click', function () {

            var studentScores = $(".score-item");
            var Scores = [];

            studentScores.each(function () {
                var studentEntry = $(this);
                var StudentId = studentEntry.find("#StudentId").val();
                var ScoreId = studentEntry.find("#ScoreId").val();
                var ClassId = $("#selected-class").val();
                var YearCreated = $("#selected-year").val();
                var RegisterProfileId = studentEntry.find("#RegisterProfileId").val();
                var DailyWorkPercentage = studentEntry.find("#DailyWorkPercentage").val();
                var DailyWorkScore = studentEntry.find("#DailyWorkScore").val();
                var Absences = studentEntry.find("#Absences").val();
                var Belated = studentEntry.find("#Belated").val();
                var AssistancePercentage = studentEntry.find("#AssistancePercentage").val();
                var ConceptPercentage = studentEntry.find("#ConceptPercentage").val();

                var examScoreFields = studentEntry.find(".exam-score");
                var ExamResults = [];

                examScoreFields.each(function () {
                    var examId = $(this).attr('data-exam-id');
                    var examScore = $(this).val();
                    var examPercentageField = studentEntry.find("input.exam-percentage[data-exam-id='" + examId + "']");
                    var examPointsField = studentEntry.find("input.exam-points[data-exam-id='" + examId + "']");

                    var Exam =
                    {
                        "ExamId": examId,
                        "ExamScore": examScore,
                        "ExamPoints": examPointsField.val(),
                        "ExamPercentage": examPercentageField.val(),
                    };

                    ExamResults.push(Exam);
                });

                var extraclassWorkFields = studentEntry.find(".extraclass-percentage");
                var ExtraclasWorkResults = [];

                extraclassWorkFields.each(function () {
                    var extraclassId = $(this).attr('data-extraclass-id');
                    var extraclassPercentage = $(this).val();
                    var extraclassPointsField = studentEntry.find("input.extraclass-score[data-extraclass-id='" + extraclassId + "']");

                    var ExtraclassWork =
                    {
                        "ExtraclassWorkId": extraclassId,
                        "ExtraclassWorkPercentage": extraclassPercentage,
                        "ExtraclassWorkScore": extraclassPointsField.val()
                    };

                    ExtraclasWorkResults.push(ExtraclassWork);
                });

                var ScoreModel =
                {
                    "Id": ScoreId,
                    "StudentId": StudentId,
                    "ClassId": ClassId,
                    "YearCreated": YearCreated,
                    "RegisterProfileId": RegisterProfileId,
                    "DailyWorkPercentage": DailyWorkPercentage,
                    "DailyWorkScore": DailyWorkScore,
                    "Absences": Absences,
                    "Belated": Belated,
                    "AssistancePercentage": AssistancePercentage,
                    "ConceptPercentage": ConceptPercentage,
                    "ExamResults": ExamResults,
                    "ExtraclasWorkResults": ExtraclasWorkResults
                };

                Scores.push(ScoreModel);
            })

            //Send a list of scores
            $.ajax({
                url: '/Score/Save/',
                data: JSON.stringify(Scores),
                type: 'POST',
                contentType: 'application/json; charset=utf-8',
                success: function (data) {
                    LoadGridScores();
                }
            });

        });

    }
})<|endoftext|>


<commit_before> "use strict";
Seed (
	{
		name : "Mold.Lib.Event",
		dna : "class",
		author : "Jan Kaufmann",
		description : "",
		include : [
			"Mold.Lib.EventStore"
		],
		compiler : {
			preparsePublics : true
		},
		version : 0.1
	},
	function(element){
		var _element = element;
		var that = this;
		var _isHTMLElement = _element instanceof  Element;
		var _elementEvents = [
			"blur", "change", "contextmenu", "copy", "cut", "dblclick", "error",
			"focus", "focusin", "focusout", "hashchange", "keydown", "keypress", "keyup",
			"load",  "paste", "reset", "resize", "scroll",
			"select", "submit", "textinput", "transitionend", "unload", "DOMAttrModified"
		];

		var _mouseEvents = [
			"click", "mousedown", "mouseenter", "mouseleave", "mousemove", "mouseout",
			"mouseover", "mouseup", "mousewheel", "wheel"
		];

		var _translateEvents = {
			"transitionend" : [ "msTransitionEnd", "webkitTransitionEnd", "oTransitionEnd" ]
		};

		_elementEvents = _elementEvents.concat(_mouseEvents);

		var _isElementEvent = function(event){
			if(_elementEvents.indexOf(event) > -1){
				return true;
			}else{
				return false;
			}
		}

		var _initEvent = function(event){
			if(_mouseEvents.indexOf(event) > -1){
				var evt = document.createEvent("MouseEvents");
				evt.initMouseEvent(event, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
				return evt;
			}

			return false;
		}

		var _isEventSupported = function(eventName) {
			eventName = eventName;
			var isSupported = (eventName in _element);
			if (!isSupported) {
				_element.setAttribute(eventName, 'return;');
				isSupported = typeof _element[eventName] == 'function';
				_element.removeAttribute(eventName, 'return;');
			}
			return isSupported;
		}

		var _getEventName = function(event){
			if(_translateEvents[event]){
				for(var i = 0; i < _translateEvents[event].length; i++){
					if(_isEventSupported(_translateEvents[event][i])){
						return _translateEvents[event][i];
					}
				}
				return event;
			}else{
				return event;
			}
		}

		var _firedActions = {};
		var _eid = Mold.getId();

		this.publics = {
			_eid : _eid,
			when : function(event, callback){
				var executeOn  = function(callback){
					_firedActions[event] = _firedActions[event] || {};
					var trigger = Mold.Lib.EventStore.getElementTrigger(_element, event);

					if(trigger.length > 0){

						callback();
					}else{
						var delayedCall = function(){
							callback();
							that.off(event, delayedCall);
						};
						that.on(event, delayedCall);
					}
				};

				if(callback){
					executeOn(callback);
				}

				_element.then = function(callback){
					executeOn(callback);
					return _element;
				};

				return _element;
			},

			at : function(event, callback, config){
				var trigger = Mold.Lib.EventStore.getElementTrigger(_element, event);
				_firedActions[event] = _firedActions[event] || {};
				if(!_firedActions[event][callback]){

					for(var i = 0; i < trigger.length; i++){
						if(config && config.triggerElement){
							config.triggerElement.trigger(trigger[i].event, trigger[i].data);
						}else{

							this.trigger(trigger[i].event, trigger[i].data);
						}

						_firedActions[event][callback] == true;
					}
				}
				this.on(event, callback, config);
				return _element;

			},
			delegate : function(event){
				return {
					to : function(triggerElement){
						that.on(event, function(e){
							triggerElement.trigger(event, e.data || false);
						});
					}
				};
			},
			bubble : function(event, data){
				if(_element.hasParents && _element.hasParents()){
					_element.eachParent(function(parent){
						parent.trigger(event, data);
					});
				}
			},
			on : function(event, callback, config){
				var executeOn  = function(callback){
					if(_isHTMLElement && _isElementEvent(event)){
						_element.addEventListener(_getEventName(event), callback);
					}
					Mold.Lib.EventStore.addElementEvent(_element,  event, callback);

					_firedActions[event] = true;
				};

				if(callback){
					executeOn(callback);
				}

				_element.then = function(callback){
					executeOn(callback);
					return _element;
				};

				return _element;
			},
			off : function(event, callback){
				if(_isHTMLElement && _isElementEvent(event)){
					_element.removeEventListener(_getEventName(event), callback);
				}
				if(event && callback){
					Mold.Lib.EventStore.removeElementEvent(_element, event, callback);
				}else{
					Mold.Lib.EventStore.removeEvents(_element);
				}

				return _element;
			},
			trigger : function(event, data, config){
				var output = false;
				if(!data || !data.id || data.id !== "event"){
					var eventData = {
						data : data || false,
						event : event,
						id : "event",
						config : config || false
					};
				}else{
					var eventData = data;
				}

				var events = [];

				if(config && config.exclude && config.exclude.indexOf(event) > -1){

				}else{
					events = Mold.Lib.EventStore.getElementEvent(_element,  event) || [];
					var all = Mold.Lib.EventStore.getElementEvent(_element, "all");
					if(all){
						events = events.concat(all);
					}
				}
				var i = 0, eventsLen =events.length;
				var eventObject = false;
				for(; i < eventsLen;  i++){
					if(_isHTMLElement && _isElementEvent(event)){
						eventObject = _initEvent(event);
						if(eventObject){

							_element.dispatchEvent(eventObject);
						}
					}else{
						output = events[i].call(this,eventData) || output;
					}
				}
				Mold.Lib.EventStore.saveTrigger(_element, event, data);
				return output || _element;
			}

		}

		return this;
	}
);<commit_msg>Methode "once" added, attach an event only once<commit_after> "use strict";
Seed (
	{
		name : "Mold.Lib.Event",
		dna : "class",
		author : "Jan Kaufmann",
		description : "",
		include : [
			"Mold.Lib.EventStore"
		],
		compiler : {
			preparsePublics : true
		},
		version : 0.1
	},
	function(element){
		var _element = element;
		var that = this;
		var _isHTMLElement = _element instanceof  Element;
		var _elementEvents = [
			"blur", "change", "contextmenu", "copy", "cut", "dblclick", "error",
			"focus", "focusin", "focusout", "hashchange", "keydown", "keypress", "keyup",
			"load",  "paste", "reset", "resize", "scroll",
			"select", "submit", "textinput", "transitionend", "unload", "DOMAttrModified"
		];

		var _mouseEvents = [
			"click", "mousedown", "mouseenter", "mouseleave", "mousemove", "mouseout",
			"mouseover", "mouseup", "mousewheel", "wheel"
		];

		var _translateEvents = {
			"transitionend" : [ "msTransitionEnd", "webkitTransitionEnd", "oTransitionEnd" ]
		};

		_elementEvents = _elementEvents.concat(_mouseEvents);

		var _isElementEvent = function(event){
			if(_elementEvents.indexOf(event) > -1){
				return true;
			}else{
				return false;
			}
		}

		var _initEvent = function(event){
			if(_mouseEvents.indexOf(event) > -1){
				var evt = document.createEvent("MouseEvents");
				evt.initMouseEvent(event, true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null);
				return evt;
			}

			return false;
		}

		var _isEventSupported = function(eventName) {
			eventName = eventName;
			var isSupported = (eventName in _element);
			if (!isSupported) {
				_element.setAttribute(eventName, 'return;');
				isSupported = typeof _element[eventName] == 'function';
				_element.removeAttribute(eventName, 'return;');
			}
			return isSupported;
		}

		var _getEventName = function(event){
			if(_translateEvents[event]){
				for(var i = 0; i < _translateEvents[event].length; i++){
					if(_isEventSupported(_translateEvents[event][i])){
						return _translateEvents[event][i];
					}
				}
				return event;
			}else{
				return event;
			}
		}

		var _firedActions = {};
		var _eid = Mold.getId();

		this.publics = {
			_eid : _eid,
			when : function(event, callback){
				var executeOn  = function(callback){
					_firedActions[event] = _firedActions[event] || {};
					var trigger = Mold.Lib.EventStore.getElementTrigger(_element, event);

					if(trigger.length > 0){

						callback();
					}else{
						var delayedCall = function(){
							callback();
							that.off(event, delayedCall);
						};
						that.on(event, delayedCall);
					}
				};

				if(callback){
					executeOn(callback);
				}

				_element.then = function(callback){
					executeOn(callback);
					return _element;
				};

				return _element;
			},

			at : function(event, callback, config){
				var trigger = Mold.Lib.EventStore.getElementTrigger(_element, event);
				_firedActions[event] = _firedActions[event] || {};
				if(!_firedActions[event][callback]){

					for(var i = 0; i < trigger.length; i++){
						if(config && config.triggerElement){
							config.triggerElement.trigger(trigger[i].event, trigger[i].data);
						}else{

							this.trigger(trigger[i].event, trigger[i].data);
						}

						_firedActions[event][callback] == true;
					}
				}
				this.on(event, callback, config);
				return _element;

			},
			delegate : function(event){
				return {
					to : function(triggerElement){
						that.on(event, function(e){
							triggerElement.trigger(event, e.data || false);
						});
					}
				};
			},
			bubble : function(event, data){
				if(_element.hasParents && _element.hasParents()){
					_element.eachParent(function(parent){
						parent.trigger(event, data);
					});
				}
			},
			once : function(event, callback, config){
				var element = Mold.Lib.EventStore.getElementEvent(_element,  event);
				if(!element || element.toString() !== callback.toString()){
					this.on(event, callback, config);
				}
			},
			on : function(event, callback, config){
				var executeOn  = function(callback){
					if(_isHTMLElement && _isElementEvent(event)){
						_element.addEventListener(_getEventName(event), callback);
					}
					Mold.Lib.EventStore.addElementEvent(_element,  event, callback);

					_firedActions[event] = true;
				};

				if(callback){
					executeOn(callback);
				}

				_element.then = function(callback){
					executeOn(callback);
					return _element;
				};

				return _element;
			},
			off : function(event, callback){
				if(_isHTMLElement && _isElementEvent(event)){
					_element.removeEventListener(_getEventName(event), callback);
				}
				if(event && callback){
					Mold.Lib.EventStore.removeElementEvent(_element, event, callback);
				}else{
					Mold.Lib.EventStore.removeEvents(_element);
				}

				return _element;
			},
			trigger : function(event, data, config){
				var output = false,
					events = [];

				if(!data || !data.id || data.id !== "event"){
					var eventData = {
						data : data || false,
						event : event,
						id : "event",
						config : config || false
					};
				}else{
					var eventData = data;
				}

				if(config && config.exclude && config.exclude.indexOf(event) > -1){

				}else{
					events = Mold.Lib.EventStore.getElementEvent(_element,  event) || [];
					var all = Mold.Lib.EventStore.getElementEvent(_element, "all");
					if(all){
						events = events.concat(all);
					}
				}

				var i = 0,
					eventsLen =events.length,
					eventObject = {};

				for(; i < eventsLen;  i++){
					if(_isHTMLElement && _isElementEvent(event)){
						eventObject = _initEvent(event);
						if(eventObject){

							_element.dispatchEvent(eventObject);
						}
					}else{
						output = events[i].call(this,eventData) || output;
					}
				}
				Mold.Lib.EventStore.saveTrigger(_element, event, data);
				return output || _element;
			}

		}

		return this;
	}
);<|endoftext|>


<commit_before>(function($) {
    var months = new Array(12);
    months[0] = "January";
    months[1] = "February";
    months[2] = "March";
    months[3] = "April";
    months[4] = "May";
    months[5] = "June";
    months[6] = "July";
    months[7] = "August";
    months[8] = "September";
    months[9] = "October";
    months[10] = "November";
    months[11] = "December";

    var form = $('#form-cart');
    if(!form.length)
        return;

    function setup_period_range(e) {
        var days = Number(e.attr('data-steps'));

        var period_start = new Date(e.parent().parent().attr('data-period-start'));
        var label = e.prevAll('p');

        function format_date(d) {
            return d.getDate() + ' ' + months[d.getMonth()];
        }
        function set_label(values) {
            if(!values) {
                values = e.slider('values');
            }
            var txt = "from ";
            var d = new Date(period_start);
            d.setDate(d.getDate() + values[0]);
            txt += format_date(d) + " to ";
            d.setDate(d.getDate() + (values[1]-values[0]));
            txt += format_date(d);
            label.text(txt);
        }
        /*
         * questi sono gli input da mantenere sincronizzati con i valore dello
         * slider
         */
        var inputs = $('input[type=hidden]', e.parent());
        /*
         * questa funzione viene chiamata anche su elementi clonati dove è già
         * presente il markup dello slider; la chiamata .html('') anche se poco
         * elegante mi permette di fare tabula rasa e ripartire da zero.
         */
        function cap_values(slider, handle, values) {
            var hix = handle.data('index.uiSliderHandle');
            var max = slider.slider('option', 'max');
            var min = slider.slider('option', 'min');
            if(hix == 1) {
                values = [ values[1] - 3, values[1] ];
            }
            else {
                values = [ values[0], values[0] + 3 ];
            }
            if(values[0] <= min) {
                values[0] = min;
                values[1] = min + 3;
            }
            else if(values[1] >= max) {
                values[0] = max - 3;
                values[1] = max;
            }
            return values;
        }
        e.html('').slider({
            range: true,
            min: 0,
            max: days,
            values: [ Number(inputs.eq(0).val()), Number(inputs.eq(1).val())],
            slide: function(evt, ui) {
                var values = ui.values;
                var diff = values[1] - values[0];
                if(diff < 3) {
                    var w = $(this);
                    w.slider('values', cap_values(w, $(ui.handle), values));
                }
                else {
                    set_label(values);
                    inputs.eq(0).val(values[0]);
                    inputs.eq(1).val(values[1]);
                    $('input[type=text]', e.parent().next()).change();
                }
            },
            change: function(evt, ui) {
                if(!evt.originalEvent)
                    return;
                var w = $(this);
                var values = ui.values;
                var diff = values[1] - values[0];
                if(diff < 3) {
                    values = cap_values(w, $(ui.handle), values);
                    w.slider('values', values);
                }
                set_label(values);
                inputs.eq(0).val(values[0]);
                inputs.eq(1).val(values[1]);
                $('input[type=text]', e.parent().next()).change();
            }
        });
        set_label();
    };

    function setup_reservation_rows(rows) {
        $(rows).each(function() {
            var reservation = $(this);
            $('.room-type select', reservation).change(function(e) {
                $('td[data-fare]', reservation).attr('data-fare', $('option:selected', this).val());
                $('input[type=text]', reservation).change();
            }).change();

            setup_period_range($('.period', reservation));
        });
    }

    setup_reservation_rows($('.hotel-reservation-type', form));

    $('.cart-hotel-another-reservation', form).click(function(e) {
        e.preventDefault();
        var type = $(this).attr('data-type');
        var rows = $('tr[data-reservation-type=' + type + ']', form);

        var orig = rows.eq(rows.length-1);
        var main = orig.clone();

        orig.parents('tbody')
            .append(main)

        setup_reservation_rows(main);
        setup_cart_input($('input', main));
    });

    function calcTotal() {

        function _clearTotals() {
            $('fieldset .total', form)
                .data('total', 0)
                .children('b')
                .html('€ 0');
        }

        form.ajaxSubmit({
            url: '/p3/cart/calculator/',
            dataType: 'json',
            success: function(data, text, jqHXR) {
                _clearTotals()

                /*
                 * data contiene il totale generale, lo sconto ottenuto tramite
                 * coupon e il dettaglio dei costi dei singoli biglietti
                 */
                var feedback = $('.coupon .cms span');
                feedback.text((data.coupon || 0 ) != 0 ? 'coupon accepted' : '');
                $('.coupon .total b', form).html('€ ' + (data.coupon || 0));
                $('.grand.total b', form).html('€ ' + (data.total || 0));
                $('.hotel-reservations td[data-fare]', form).next().html('');
                $('.hotel-reservations tr').removeClass('error');
                $('.hotel-reservations tr .errors').html('');

                /*
                 * ...il problema con i costi dei singoli biglietti è quello di
                 * mostrare per ogni prenotazione alberghiera il prezzo
                 * corrispondente.
                 * Il prezzo degli altri biglietti non varia con i parametri
                 * inseriti dall'utente, ad esempio non abbiamo lo sconto
                 * quantità, quindi posso mostrare il prezzo del singolo
                 * biglietto in anticipo inserendolo nell'html. Con le
                 * prenotazioni alberghiere invece il prezzo varia sia con il
                 * tipo di camera (ma qui sono fare diverse è la nostra UI che
                 * le vuol far vedere su una singola riga) sia con il periodo
                 * di pernottamento, inoltre possiamo avere più biglietti dello
                 * stesso tipo ma con periodi diversi (ad esempio potrei voler
                 * prenotare 1 biglietto HB3 per le date X e Y e 1 biglietto
                 * sempre HB3 ma per le date X' e Y')
                 */
                function update_total(parent, value) {
                    var e = $('.total', parent);
                    var total = e.data('total') + Number(value);
                    e.data('total', total);
                    e.children('b').html('€ ' + total.toFixed(2));
                }
                $(data.tickets).each(function() {
                    var code = this[0];
                    var params = this[1];
                    var total = this[2];
                    /*
                     * per tutti i biglietti, ad eccezioni delle prenotazioni
                     * alberghiere, posso limitarmi ad aggiungere il valore nel
                     * totale di sezione (identificato con la prima lettera del
                     * codice tariffa)...
                     */
                    var group = '';
                    switch(code.substr(0, 1)) {
                        case 'H':
                            if(code.length == 3)
                                group = 'H';
                            break;
                        case 'T':
                            if(code.length == 4)
                                group = 'T';
                            break;
                        case 'P':
                            group = 'P';
                            break;
                    }
                    switch(group) {
                        case 'H':
                            /*
                             * ...ma per le tariffe alberghiere devo anche
                             * mostrare il valore del biglietto nella riga
                             * corrispondente. E non basta usare il codice
                             * tariffa, devo fare anche il match con il periodo
                             */
                            $('.hotel-reservations td[data-fare=' + code + ']', form).each(function() {
                                var qty = $(this);
                                if($('input[type=text]', qty).val() == params.qty) {
                                    // ho trovato un input con la stessa quantità e
                                    // lo stesso codice tariffa, ora devo
                                    // controllare il periodo
                                    var period = $('.period', qty.prev()).slider('values');
                                    if(params.period[0] == period[0] && params.period[1] == period[1]) {
                                        // trovato!
                                        var price = qty.next();
                                        price.html('€ ' + total);
                                        update_total(price.parents('.hotel-reservations'), total);
                                    }
                                }
                            });
                            break;
                        case 'T':
                            update_total($('.conference-tickets', form), total);
                            break;
                        case 'P':
                            update_total($('.partner-program', form), total);
                            break;
                        default:
                            update_total($('.other-goodies', form), total);
                            break;
                    }
                });
            },
            error: function(response) {
                var err = null;
                if(response.status == 400) {
                    try {
                        err = JSON.parse(response.responseText);
                    }
                    catch(_) {
                    }
                }

                _clearTotals();
                if(err == null) {
                    alert(response.responseText);
                    return;
                }

                /* la validazione della form passata ha ritornato un errore,
                 * devo mostrare i messaggi accanto ai campi corrispondenti
                 */

                /* XXX: in teoria qualunque campo della form potrebbe avere
                 * problemi di validazione, in pratica solo quelli relativi
                 * alle prenotazioni alberghiere.
                 */

                function hotel_row_error(type, ix, msg) {
                    var row = $('tr[data-reservation-type=' + type + ']', form)
                        .eq(ix)
                        .addClass('error');
                    var fare_cell = $('td[data-fare]', row);
                    var feedback = $('.errors', fare_cell);
                    if(feedback.length) {
                        feedback.html(msg);
                    }
                    else {
                        $('

')
                            .appendTo(fare_cell)
                            .html(msg);
                    }
                }
                for(var fname in err) {
                    switch(fname) {
                        case 'bed_reservations':
                        case 'room_reservations':
                            var type = fname.split('_')[0];
                            for(var ix=0; ix<err[fname].length; ix++) {
                                var p = err[fname][ix].split(':');
                                hotel_row_error(type, p[0], p[1]);
                            }
                            break;
                        case '__all__':
                            break;
                        default:
                            // ops qualcosa di inatteso
                            throw("invalid field");
                            break;
                    }
                }
                return;
            }
        });
    }
    function setup_cart_input(inputs) {
        inputs
            .change(calcTotal)
            .not('[name=coupon]')
            .keypress(function(e) {
                if((e.which < 48 || e.which > 57) && e.which != 13 && e.which != 0 && e.which != 8) {
                    e.preventDefault()
                }
            });
    }
    setup_cart_input($('input', form));

    function _enableFares(personal) {
        $('.conference-tickets td.fare', form).each(function() {
            var td = $(this);
            var fare_code = td.attr('data-fare');
            var e = ((fare_code.substr(3, 1) == 'C' && !personal) || (fare_code.substr(3, 1) != 'C' && personal));
            var inputs = $('input', td);
            if(e) {
                td.removeClass('disabled');
                inputs.attr('disabled', false);
            }
            else {
                td.addClass('disabled');
                inputs.attr('disabled', true);
            }
        });
    }
    $('#id_order_type').change(function() {
        _enableFares($(this).val() != 'deductible');
        calcTotal();
    });

    if(document.location.search.substr(0, 3) == '?f=') {
        var highligh_fare = document.location.search.substr(3);
        var i = $('td[data-fare=' + highligh_fare + '] input');
        if(!i.val())
            i.val(1);
        i.addClass('selected')
            .focus()
            .parents('tr')
            .addClass('selected');
        i.eq(0)[0].scrollIntoView();
    }

    $('#id_order_type').change();
})(jQuery);
<commit_msg>modificato il messaggio per rendere più chiaro il periodo di checkin/checkout<commit_after>(function($) {
    var months = new Array(12);
    months[0] = "January";
    months[1] = "February";
    months[2] = "March";
    months[3] = "April";
    months[4] = "May";
    months[5] = "June";
    months[6] = "July";
    months[7] = "August";
    months[8] = "September";
    months[9] = "October";
    months[10] = "November";
    months[11] = "December";

    var form = $('#form-cart');
    if(!form.length)
        return;

    function setup_period_range(e) {
        var days = Number(e.attr('data-steps'));

        var period_start = new Date(e.parent().parent().attr('data-period-start'));
        var label = e.prevAll('p');

        function format_date(d) {
            return d.getDate() + ' ' + months[d.getMonth()];
        }
        function set_label(values) {
            if(!values) {
                values = e.slider('values');
            }
            var checkin = new Date(period_start);
            checkin.setDate(checkin.getDate() + values[0]);

            var checkout = new Date(period_start);
            checkout.setDate(checkout.getDate() + values[1]);

            var txt = "checkin " + format_date(checkin) + ", ";
            txt += "checkout " + format_date(checkout) + " morning ";
            txt += "(" + ((checkout-checkin) / (60000 * 60 * 24)) + " nights)";
            label.html(txt);
        }
        /*
         * questi sono gli input da mantenere sincronizzati con i valore dello
         * slider
         */
        var inputs = $('input[type=hidden]', e.parent());
        /*
         * questa funzione viene chiamata anche su elementi clonati dove è già
         * presente il markup dello slider; la chiamata .html('') anche se poco
         * elegante mi permette di fare tabula rasa e ripartire da zero.
         */
        function cap_values(slider, handle, values) {
            var hix = handle.data('index.uiSliderHandle');
            var max = slider.slider('option', 'max');
            var min = slider.slider('option', 'min');
            if(hix == 1) {
                values = [ values[1] - 3, values[1] ];
            }
            else {
                values = [ values[0], values[0] + 3 ];
            }
            if(values[0] <= min) {
                values[0] = min;
                values[1] = min + 3;
            }
            else if(values[1] >= max) {
                values[0] = max - 3;
                values[1] = max;
            }
            return values;
        }
        e.html('').slider({
            range: true,
            min: 0,
            max: days,
            values: [ Number(inputs.eq(0).val()), Number(inputs.eq(1).val())],
            slide: function(evt, ui) {
                var values = ui.values;
                var diff = values[1] - values[0];
                if(diff < 3) {
                    var w = $(this);
                    w.slider('values', cap_values(w, $(ui.handle), values));
                }
                else {
                    set_label(values);
                    inputs.eq(0).val(values[0]);
                    inputs.eq(1).val(values[1]);
                    $('input[type=text]', e.parent().next()).change();
                }
            },
            change: function(evt, ui) {
                if(!evt.originalEvent)
                    return;
                var w = $(this);
                var values = ui.values;
                var diff = values[1] - values[0];
                if(diff < 3) {
                    values = cap_values(w, $(ui.handle), values);
                    w.slider('values', values);
                }
                set_label(values);
                inputs.eq(0).val(values[0]);
                inputs.eq(1).val(values[1]);
                $('input[type=text]', e.parent().next()).change();
            }
        });
        set_label();
    };

    function setup_reservation_rows(rows) {
        $(rows).each(function() {
            var reservation = $(this);
            $('.room-type select', reservation).change(function(e) {
                $('td[data-fare]', reservation).attr('data-fare', $('option:selected', this).val());
                $('input[type=text]', reservation).change();
            }).change();

            setup_period_range($('.period', reservation));
        });
    }

    setup_reservation_rows($('.hotel-reservation-type', form));

    $('.cart-hotel-another-reservation', form).click(function(e) {
        e.preventDefault();
        var type = $(this).attr('data-type');
        var rows = $('tr[data-reservation-type=' + type + ']', form);

        var orig = rows.eq(rows.length-1);
        var main = orig.clone();

        orig.parents('tbody')
            .append(main)

        setup_reservation_rows(main);
        setup_cart_input($('input', main));
    });

    function calcTotal() {

        function _clearTotals() {
            $('fieldset .total', form)
                .data('total', 0)
                .children('b')
                .html('€ 0');
        }

        form.ajaxSubmit({
            url: '/p3/cart/calculator/',
            dataType: 'json',
            success: function(data, text, jqHXR) {
                _clearTotals()

                /*
                 * data contiene il totale generale, lo sconto ottenuto tramite
                 * coupon e il dettaglio dei costi dei singoli biglietti
                 */
                var feedback = $('.coupon .cms span');
                feedback.text((data.coupon || 0 ) != 0 ? 'coupon accepted' : '');
                $('.coupon .total b', form).html('€ ' + (data.coupon || 0));
                $('.grand.total b', form).html('€ ' + (data.total || 0));
                $('.hotel-reservations td[data-fare]', form).next().html('');
                $('.hotel-reservations tr').removeClass('error');
                $('.hotel-reservations tr .errors').html('');

                /*
                 * ...il problema con i costi dei singoli biglietti è quello di
                 * mostrare per ogni prenotazione alberghiera il prezzo
                 * corrispondente.
                 * Il prezzo degli altri biglietti non varia con i parametri
                 * inseriti dall'utente, ad esempio non abbiamo lo sconto
                 * quantità, quindi posso mostrare il prezzo del singolo
                 * biglietto in anticipo inserendolo nell'html. Con le
                 * prenotazioni alberghiere invece il prezzo varia sia con il
                 * tipo di camera (ma qui sono fare diverse è la nostra UI che
                 * le vuol far vedere su una singola riga) sia con il periodo
                 * di pernottamento, inoltre possiamo avere più biglietti dello
                 * stesso tipo ma con periodi diversi (ad esempio potrei voler
                 * prenotare 1 biglietto HB3 per le date X e Y e 1 biglietto
                 * sempre HB3 ma per le date X' e Y')
                 */
                function update_total(parent, value) {
                    var e = $('.total', parent);
                    var total = e.data('total') + Number(value);
                    e.data('total', total);
                    e.children('b').html('€ ' + total.toFixed(2));
                }
                $(data.tickets).each(function() {
                    var code = this[0];
                    var params = this[1];
                    var total = this[2];
                    /*
                     * per tutti i biglietti, ad eccezioni delle prenotazioni
                     * alberghiere, posso limitarmi ad aggiungere il valore nel
                     * totale di sezione (identificato con la prima lettera del
                     * codice tariffa)...
                     */
                    var group = '';
                    switch(code.substr(0, 1)) {
                        case 'H':
                            if(code.length == 3)
                                group = 'H';
                            break;
                        case 'T':
                            if(code.length == 4)
                                group = 'T';
                            break;
                        case 'P':
                            group = 'P';
                            break;
                    }
                    switch(group) {
                        case 'H':
                            /*
                             * ...ma per le tariffe alberghiere devo anche
                             * mostrare il valore del biglietto nella riga
                             * corrispondente. E non basta usare il codice
                             * tariffa, devo fare anche il match con il periodo
                             */
                            $('.hotel-reservations td[data-fare=' + code + ']', form).each(function() {
                                var qty = $(this);
                                if($('input[type=text]', qty).val() == params.qty) {
                                    // ho trovato un input con la stessa quantità e
                                    // lo stesso codice tariffa, ora devo
                                    // controllare il periodo
                                    var period = $('.period', qty.prev()).slider('values');
                                    if(params.period[0] == period[0] && params.period[1] == period[1]) {
                                        // trovato!
                                        var price = qty.next();
                                        price.html('€ ' + total);
                                        update_total(price.parents('.hotel-reservations'), total);
                                    }
                                }
                            });
                            break;
                        case 'T':
                            update_total($('.conference-tickets', form), total);
                            break;
                        case 'P':
                            update_total($('.partner-program', form), total);
                            break;
                        default:
                            update_total($('.other-goodies', form), total);
                            break;
                    }
                });
            },
            error: function(response) {
                var err = null;
                if(response.status == 400) {
                    try {
                        err = JSON.parse(response.responseText);
                    }
                    catch(_) {
                    }
                }

                _clearTotals();
                if(err == null) {
                    alert(response.responseText);
                    return;
                }

                /* la validazione della form passata ha ritornato un errore,
                 * devo mostrare i messaggi accanto ai campi corrispondenti
                 */

                /* XXX: in teoria qualunque campo della form potrebbe avere
                 * problemi di validazione, in pratica solo quelli relativi
                 * alle prenotazioni alberghiere.
                 */

                function hotel_row_error(type, ix, msg) {
                    var row = $('tr[data-reservation-type=' + type + ']', form)
                        .eq(ix)
                        .addClass('error');
                    var fare_cell = $('td[data-fare]', row);
                    var feedback = $('.errors', fare_cell);
                    if(feedback.length) {
                        feedback.html(msg);
                    }
                    else {
                        $('

')
                            .appendTo(fare_cell)
                            .html(msg);
                    }
                }
                for(var fname in err) {
                    switch(fname) {
                        case 'bed_reservations':
                        case 'room_reservations':
                            var type = fname.split('_')[0];
                            for(var ix=0; ix<err[fname].length; ix++) {
                                var p = err[fname][ix].split(':');
                                hotel_row_error(type, p[0], p[1]);
                            }
                            break;
                        case '__all__':
                            break;
                        default:
                            // ops qualcosa di inatteso
                            throw("invalid field");
                            break;
                    }
                }
                return;
            }
        });
    }
    function setup_cart_input(inputs) {
        inputs
            .change(calcTotal)
            .not('[name=coupon]')
            .keypress(function(e) {
                if((e.which < 48 || e.which > 57) && e.which != 13 && e.which != 0 && e.which != 8) {
                    e.preventDefault()
                }
            });
    }
    setup_cart_input($('input', form));

    function _enableFares(personal) {
        $('.conference-tickets td.fare', form).each(function() {
            var td = $(this);
            var fare_code = td.attr('data-fare');
            var e = ((fare_code.substr(3, 1) == 'C' && !personal) || (fare_code.substr(3, 1) != 'C' && personal));
            var inputs = $('input', td);
            if(e) {
                td.removeClass('disabled');
                inputs.attr('disabled', false);
            }
            else {
                td.addClass('disabled');
                inputs.attr('disabled', true);
            }
        });
    }
    $('#id_order_type').change(function() {
        _enableFares($(this).val() != 'deductible');
        calcTotal();
    });

    if(document.location.search.substr(0, 3) == '?f=') {
        var highligh_fare = document.location.search.substr(3);
        var i = $('td[data-fare=' + highligh_fare + '] input');
        if(!i.val())
            i.val(1);
        i.addClass('selected')
            .focus()
            .parents('tr')
            .addClass('selected');
        i.eq(0)[0].scrollIntoView();
    }

    $('#id_order_type').change();
})(jQuery);
<|endoftext|>


<commit_before>var label = require("./label");
var layout = require("./layout");
var tnode = require("./node");

var tree = function () {
 "use strict";

    var conf = {
	duration         : 500,      // Duration of the transitions
	label            : label.text(),
	layout           : layout.vertical(),
	on_click         : function () {},
	on_dbl_click     : function () {},
	on_mouseover    : function () {},
	link_color       : 'steelblue',
	node_color       : 'steelblue',
	node_circle_size : 4.5,
    };

    // Keep track of the focused node
    // TODO: Would it be better to have multiple focused nodes? (ie use an array)
    var focused_node;

    // Extra delay in the transitions (TODO: Needed?)
    var delay = 0;

    // Ease of the transitions
    var ease = "cubic-in-out";

    // If labels should be skipped
    // TODO: Replace this with a valid tree.label that does nothing
    // var skip_labels = false;

    // TODO: Don't know if this is useful or not
    // Probably this can go and see if this can be set with the API
    var curr_species = "Homo_sapiens";

    // By node data
    var sp_counts = {};

    var scale = false;

    // The id of the tree container
    var div_id;

    // The tree visualization (svg)
    var svg;
    var vis;

    // TODO: For now, counts are given only for leaves
    // but it may be good to allow counts for internal nodes
    var counts = {};

    // The full tree
    var base = {
	tree : undefined,
	data : undefined,
	nodes : undefined,
	links : undefined
    };

    // The curr tree. Needed to re-compute the links / nodes positions of subtrees
    var curr = {
	tree : undefined,
	data : undefined,
	nodes : undefined,
	links : undefined
    };

    // The cbak returned
    var tree = function (div) {
	div_id = d3.select(div).attr("id");

        var tree_div = d3.select(div)
            .append("div")
	    .attr("class", "tnt_groupDiv");

	var cluster = conf.layout.cluster;

	var n_leaves = curr.tree.get_all_leaves().length;

	var max_leaf_label_length = function (tree) {
	    var max = 0;
	    var leaves = tree.get_all_leaves();
	    for (var i=0; i<leaves.length; i++) {
		var label_width = conf.label.width()(leaves[i]);
		if (label_width > max) {
		    max = label_width;
		}
	    }
	    return max;
	};

	var max_label_length = max_leaf_label_length(curr.tree);
	conf.layout.max_leaf_label_width(max_label_length);

	// Cluster size is the result of...
	// total width of the vis - transform for the tree - max_leaf_label_width - horizontal transform of the label
	// TODO: Substitute 15 by the horizontal transform of the nodes
	var cluster_size_params = {
	    n_leaves : n_leaves,
	    label_height : d3.functor(conf.label.height())(),
	    label_padding : 15
	};

	conf.layout.adjust_cluster_size(cluster_size_params);

	var diagonal = conf.layout.diagonal();
	var transform = conf.layout.transform_node;

	svg = tree_div
	    .append("svg")
	    .attr("width", conf.layout.width())
//	    .attr("height", (n_leaves * label.height()()) + 20)
	    .attr("height", conf.layout.height(cluster_size_params) + 30)
	    .attr("fill", "none");

	vis = svg
	    .append("g")
	    .attr("id", "tnt_st_" + div_id)
	    .attr("transform",
		  "translate(" +
		  conf.layout.translate_vis()[0] +
		  "," +
		  conf.layout.translate_vis()[1] +
		  ")");

	curr.nodes = cluster.nodes(curr.data);
	conf.layout.scale_branch_lengths(curr);
	curr.links = cluster.links(curr.nodes);

	// LINKS
	var link = vis.selectAll("path.tree_link")
	    .data(curr.links, function(d){return d.target._id});

	link
	    .enter()
	    .append("path")
	    .attr("class", "tree_link")
	    .attr("id", function(d) {
	    	return "tree_link_" + div_id + "_" + d.target._id;
	    })
	    .style("stroke", function (d) {
		return d3.functor(conf.link_color)(tnode(d.source), tnode(d.target));
	    })
	    .attr("d", diagonal);

	// NODES
	var node = vis.selectAll("g.tnode")
	    .data(curr.nodes, function(d) {return d._id});

	var new_node = node
	    .enter().append("g")
	    .attr("class", function(n) {
		if (n.children) {
		    if (n.depth == 0) {
			return "root tnode"
		    } else {
			return "inner tnode"
		    }
		} else {
		    return "leaf tnode"
		}
	    })
	    .attr("id", function(d) {
		return "tnode_" + div_id + "_" + d._id
	    })
	    .attr("transform", transform);

	new_node
	    .append('circle')
	    .attr("r", function (d) {
		return d3.functor(conf.node_circle_size)(tnode(d));
	    })
	    .attr('fill', function (d) {
		return d3.functor(conf.node_color)(tnode(d));
	    })
	    .attr('stroke', function (d) {
		return d3.functor(conf.node_color)(tnode(d));
	    })
	    .attr('stroke-width', '2px');

	new_node.on("click", function (node) {
	    conf.on_click.call(this, tnode(node));
	});

	new_node.on("mouseover", function (node) {
	    conf.on_mouseover.call(this, tnode(node));
	});

	new_node.on("dblclick", function (node) {
	    conf.on_dbl_click.call(this, tnode(node));
	});

	new_node
	    .each (function (d) {
	    	conf.label.call(this, tnode(d));
	    });

	// Update plots an updated tree
	api.method ('update', function() {
	    var cluster = conf.layout.cluster;
	    var diagonal = conf.layout.diagonal();
	    var transform = conf.layout.transform_node;

	    var max_label_length = max_leaf_label_length(curr.tree);
	    conf.layout.max_leaf_label_width(max_label_length);

	    // Cluster size is the result of...
	    // total width of the vis - transform for the tree - max_leaf_label_width - horizontal transform of the label
	// TODO: Substitute 15 by the transform of the nodes (probably by selecting one node assuming all the nodes have the same transform
	    var n_leaves = curr.tree.get_all_leaves().length;
	    var cluster_size_params = {
		n_leaves : n_leaves,
		label_height : d3.functor(conf.label.height())(),
		label_padding : 15
	    };
	    conf.layout.adjust_cluster_size(cluster_size_params);

	    svg
		.transition()
		.duration(conf.duration)
		.ease(ease)
		.attr("height", conf.layout.height(cluster_size_params) + 30); // height is in the layout

	    vis
		.transition()
		.duration(conf.duration)
		.attr("transform",
		      "translate(" +
		      conf.layout.translate_vis()[0] +
		      "," +
		      conf.layout.translate_vis()[1] +
		      ")");

	    curr.nodes = cluster.nodes(curr.data);
	    conf.layout.scale_branch_lengths(curr);
	    curr.links = cluster.links(curr.nodes);

        // NODES
	    var node = vis.selectAll("g.tnode")
		.data(curr.nodes, function(d) {return d._id});

	    // LINKS
	    var link = vis.selectAll("path.tree_link")
		.data(curr.links, function(d){return d.target._id});

	    var exit_link = link
		.exit()
		.remove();

	    // New links are inserted in the prev positions
	    link
		.enter()
		.append("path")
		.attr("class", "tree_link")
		.attr("id", function (d) {
		    return "tree_link_" + div_id + "_" + d.target._id;
		})
		// .attr("fill", "none")
		.attr("stroke", function (d) {
		    return d3.functor(conf.link_color)(tnode(d.source), tnode(d.target));
		})
		.attr("d", diagonal);

	    link
	    //  TODO: Here we will be moving links that have been already moved in the previous filter
	    //  if transitions are slow, this is a good place to optimize
	    	.transition()
		.ease(ease)
	    	.duration(conf.duration)
	    	.attr("d", diagonal);

	    // New nodes are created without radius
	    // The radius is created after the links
	    var new_node = node
		.enter()
		.append("g")
		.attr("class", function(n) {
		    if (n.children) {
			if (n.depth == 0) {
			    return "root tnode"
			} else {
			    return "inner tnode"
			}
		    } else {
			return "leaf tnode"
		    }
		})
		.attr("id", function (d) {
		    return "tnode_" + div_id + "_" + d._id;
		})
		.attr("transform", transform);

	    new_node
		.append('circle')
		.attr("r", 1e-6)
		.attr('stroke', function (d) {
		    return d3.functor(conf.node_color)(tnode(d));
		})
		.attr('stroke-width', '2px')
		.transition()
		.duration(conf.duration)
		.attr("r", function (d) {
		    return d3.functor(conf.node_circle_size)(tnode(d));
		});

	    new_node.on("click", function (node) {
		conf.on_click.call(this, tnode(node));
	    });

	    new_node.on("mouse_over", function (node) {
		conf.on_mouse_over(this, tnode(node));
	    });

	    new_node.on("dblclick", function (node) {
		conf.on_dbl_click.call(this, tnode(node));
	    });

	    // node color, size and labels are dynamic properties
	    node
		.select("circle")
		.transition()
		.attr('fill', function (d) {
		    return d3.functor(conf.node_color)(tnode(d));
		})
		.attr('r', function (d) {
		    return d3.functor(conf.node_circle_size)(tnode(d));
		})
		// node strokes are dynamic properties
		.attr('stroke', function (d) {
		    return d3.functor(conf.node_color)(tnode(d));
		});

	    // TODO: Shouldn't this be done only on new nodes? Old nodes should already have the labels
	    node
		.each (conf.label.remove)
		    .each (function (d) {
			conf.label.call(this, tnode(d));
		    });

	    node
		.transition()
		.ease(ease)
		.duration(conf.duration)
		.attr("transform", transform);

	    // Exiting nodes are just removed
	    node
		.exit()
		.remove();
	});
    };

    // API
    //var api = tnt.utils.api (tree)
    //	.getset (conf)

  //  tree.duration         = 500;      // Duration of the transitions
  //  tree.label            = label.text();
  //  tree.layout           = layout.vertical();
  //  tree.on_click         = function () {};
  //  tree.on_dbl_click     = function () {};
  //  tree.on_mouseover    = function () {};
  //  tree.link_color       = 'steelblue';
  //  node_color       = 'steelblue';
  //  node_circle_size = 4.5;

    // TODO: Rewrite data using getset / finalizers & transforms
    tree.data = function (d) {
	if (!arguments.length) {
	    return base.data;
	}

	// The original data is stored as the base and curr data
	base.data = d;
	curr.data = d;

	// Set up a new tree based on the data
	var newtree = tnode(base.data);

	tree.root(newtree);
	return tree;
    };

    // TODO: Rewrite tree using getset / finalizers & transforms
    tree.root = function (t) {
    	if (!arguments.length) {
    	    return curr.tree;
    	}

	// The original tree is stored as the base, prev and curr tree
    	base.tree = t;
	curr.tree = base.tree;
//	prev.tree = base.tree;
    	return tree;
    };

    tree.subtree = function (curr_nodes) {
	var subtree = base.tree.subtree(curr_nodes);
	curr.data = subtree.data();
	curr.tree = subtree;

	return tree;
    };

    tree.focus_node = function (node) {
	// find
	var found_node = tree.root().find_node_by_field(node.id(), '_id');
	focused_node = found_node
	tree.subtree(found_node.get_all_leaves());

	return tree;
    };

    tree.has_focus = function (node) {
	return ((focused_node !== undefined) && (focused_node.id() === node.id()));
    };

    tree.release_focus = function () {
	tree.data (base.data);
	focused_node = undefined;
	return tree;
    };

//    tree.tooltip = function () {
//	// var tooltip = tnt.tooltip().type("table");
//	var tooltip = tnt.tooltip.table();
//	var tree_tooltip = function (node) {
//	    node = node.data();
//	    var obj = {};
//	    obj.header = {
//		label : "Name",
//		value : node.name
//	    };
//	    obj.rows = [];
//	    obj.rows.push({
//		label : "_id",
//		value : node._id
//	    });
//	    obj.rows.push({
//		label : "Depth",
//		value : node.depth
//	    });
//	    obj.rows.push({
//		label : "Length",
//		value : node.length
//	    });
//	    obj.rows.push({
//		label : "N.Children",
//		value : node.children ? node.children.length : 0
//	    });
//	    tooltip.call(this, obj);
//	};
//
//	return tree_tooltip;
//    });

	// set default conf
	console.log(conf);
	for(var key in conf){
		console.log("key " +key);
		tree[key]= conf[key];
	}
	console.log(tree);
	console.log("--");

    return tree;
};

module.exports = tree;
<commit_msg>transformed api.method('update')<commit_after>var label = require("./label");
var layout = require("./layout");
var tnode = require("./node");

var tree = function () {
 "use strict";

    var conf = {
	duration         : 500,      // Duration of the transitions
	label            : label.text(),
	layout           : layout.vertical(),
	on_click         : function () {},
	on_dbl_click     : function () {},
	on_mouseover    : function () {},
	link_color       : 'steelblue',
	node_color       : 'steelblue',
	node_circle_size : 4.5,
    };

    // Keep track of the focused node
    // TODO: Would it be better to have multiple focused nodes? (ie use an array)
    var focused_node;

    // Extra delay in the transitions (TODO: Needed?)
    var delay = 0;

    // Ease of the transitions
    var ease = "cubic-in-out";

    // If labels should be skipped
    // TODO: Replace this with a valid tree.label that does nothing
    // var skip_labels = false;

    // TODO: Don't know if this is useful or not
    // Probably this can go and see if this can be set with the API
    var curr_species = "Homo_sapiens";

    // By node data
    var sp_counts = {};

    var scale = false;

    // The id of the tree container
    var div_id;

    // The tree visualization (svg)
    var svg;
    var vis;

    // TODO: For now, counts are given only for leaves
    // but it may be good to allow counts for internal nodes
    var counts = {};

    // The full tree
    var base = {
	tree : undefined,
	data : undefined,
	nodes : undefined,
	links : undefined
    };

    // The curr tree. Needed to re-compute the links / nodes positions of subtrees
    var curr = {
	tree : undefined,
	data : undefined,
	nodes : undefined,
	links : undefined
    };

    // The cbak returned
    var tree = function (div) {
	div_id = d3.select(div).attr("id");

        var tree_div = d3.select(div)
            .append("div")
	    .attr("class", "tnt_groupDiv");

	var cluster = conf.layout.cluster;

	var n_leaves = curr.tree.get_all_leaves().length;

	var max_leaf_label_length = function (tree) {
	    var max = 0;
	    var leaves = tree.get_all_leaves();
	    for (var i=0; i<leaves.length; i++) {
		var label_width = conf.label.width()(leaves[i]);
		if (label_width > max) {
		    max = label_width;
		}
	    }
	    return max;
	};

	var max_label_length = max_leaf_label_length(curr.tree);
	conf.layout.max_leaf_label_width(max_label_length);

	// Cluster size is the result of...
	// total width of the vis - transform for the tree - max_leaf_label_width - horizontal transform of the label
	// TODO: Substitute 15 by the horizontal transform of the nodes
	var cluster_size_params = {
	    n_leaves : n_leaves,
	    label_height : d3.functor(conf.label.height())(),
	    label_padding : 15
	};

	conf.layout.adjust_cluster_size(cluster_size_params);

	var diagonal = conf.layout.diagonal();
	var transform = conf.layout.transform_node;

	svg = tree_div
	    .append("svg")
	    .attr("width", conf.layout.width())
//	    .attr("height", (n_leaves * label.height()()) + 20)
	    .attr("height", conf.layout.height(cluster_size_params) + 30)
	    .attr("fill", "none");

	vis = svg
	    .append("g")
	    .attr("id", "tnt_st_" + div_id)
	    .attr("transform",
		  "translate(" +
		  conf.layout.translate_vis()[0] +
		  "," +
		  conf.layout.translate_vis()[1] +
		  ")");

	curr.nodes = cluster.nodes(curr.data);
	conf.layout.scale_branch_lengths(curr);
	curr.links = cluster.links(curr.nodes);

	// LINKS
	var link = vis.selectAll("path.tree_link")
	    .data(curr.links, function(d){return d.target._id});

	link
	    .enter()
	    .append("path")
	    .attr("class", "tree_link")
	    .attr("id", function(d) {
	    	return "tree_link_" + div_id + "_" + d.target._id;
	    })
	    .style("stroke", function (d) {
		return d3.functor(conf.link_color)(tnode(d.source), tnode(d.target));
	    })
	    .attr("d", diagonal);

	// NODES
	var node = vis.selectAll("g.tnode")
	    .data(curr.nodes, function(d) {return d._id});

	var new_node = node
	    .enter().append("g")
	    .attr("class", function(n) {
		if (n.children) {
		    if (n.depth == 0) {
			return "root tnode"
		    } else {
			return "inner tnode"
		    }
		} else {
		    return "leaf tnode"
		}
	    })
	    .attr("id", function(d) {
		return "tnode_" + div_id + "_" + d._id
	    })
	    .attr("transform", transform);

	new_node
	    .append('circle')
	    .attr("r", function (d) {
		return d3.functor(conf.node_circle_size)(tnode(d));
	    })
	    .attr('fill', function (d) {
		return d3.functor(conf.node_color)(tnode(d));
	    })
	    .attr('stroke', function (d) {
		return d3.functor(conf.node_color)(tnode(d));
	    })
	    .attr('stroke-width', '2px');

	new_node.on("click", function (node) {
	    conf.on_click.call(this, tnode(node));
	});

	new_node.on("mouseover", function (node) {
	    conf.on_mouseover.call(this, tnode(node));
	});

	new_node.on("dblclick", function (node) {
	    conf.on_dbl_click.call(this, tnode(node));
	});

	new_node
	    .each (function (d) {
	    	conf.label.call(this, tnode(d));
	    });

	// Update plots an updated tree
	tree.update = function() {
	    var cluster = conf.layout.cluster;
	    var diagonal = conf.layout.diagonal();
	    var transform = conf.layout.transform_node;

	    var max_label_length = max_leaf_label_length(curr.tree);
	    conf.layout.max_leaf_label_width(max_label_length);

	    // Cluster size is the result of...
	    // total width of the vis - transform for the tree - max_leaf_label_width - horizontal transform of the label
	// TODO: Substitute 15 by the transform of the nodes (probably by selecting one node assuming all the nodes have the same transform
	    var n_leaves = curr.tree.get_all_leaves().length;
	    var cluster_size_params = {
		n_leaves : n_leaves,
		label_height : d3.functor(conf.label.height())(),
		label_padding : 15
	    };
	    conf.layout.adjust_cluster_size(cluster_size_params);

	    svg
		.transition()
		.duration(conf.duration)
		.ease(ease)
		.attr("height", conf.layout.height(cluster_size_params) + 30); // height is in the layout

	    vis
		.transition()
		.duration(conf.duration)
		.attr("transform",
		      "translate(" +
		      conf.layout.translate_vis()[0] +
		      "," +
		      conf.layout.translate_vis()[1] +
		      ")");

	    curr.nodes = cluster.nodes(curr.data);
	    conf.layout.scale_branch_lengths(curr);
	    curr.links = cluster.links(curr.nodes);

        // NODES
	    var node = vis.selectAll("g.tnode")
		.data(curr.nodes, function(d) {return d._id});

	    // LINKS
	    var link = vis.selectAll("path.tree_link")
		.data(curr.links, function(d){return d.target._id});

	    var exit_link = link
		.exit()
		.remove();

	    // New links are inserted in the prev positions
	    link
		.enter()
		.append("path")
		.attr("class", "tree_link")
		.attr("id", function (d) {
		    return "tree_link_" + div_id + "_" + d.target._id;
		})
		// .attr("fill", "none")
		.attr("stroke", function (d) {
		    return d3.functor(conf.link_color)(tnode(d.source), tnode(d.target));
		})
		.attr("d", diagonal);

	    link
	    //  TODO: Here we will be moving links that have been already moved in the previous filter
	    //  if transitions are slow, this is a good place to optimize
	    	.transition()
		.ease(ease)
	    	.duration(conf.duration)
	    	.attr("d", diagonal);

	    // New nodes are created without radius
	    // The radius is created after the links
	    var new_node = node
		.enter()
		.append("g")
		.attr("class", function(n) {
		    if (n.children) {
			if (n.depth == 0) {
			    return "root tnode"
			} else {
			    return "inner tnode"
			}
		    } else {
			return "leaf tnode"
		    }
		})
		.attr("id", function (d) {
		    return "tnode_" + div_id + "_" + d._id;
		})
		.attr("transform", transform);

	    new_node
		.append('circle')
		.attr("r", 1e-6)
		.attr('stroke', function (d) {
		    return d3.functor(conf.node_color)(tnode(d));
		})
		.attr('stroke-width', '2px')
		.transition()
		.duration(conf.duration)
		.attr("r", function (d) {
		    return d3.functor(conf.node_circle_size)(tnode(d));
		});

	    new_node.on("click", function (node) {
		conf.on_click.call(this, tnode(node));
	    });

	    new_node.on("mouse_over", function (node) {
		conf.on_mouse_over(this, tnode(node));
	    });

	    new_node.on("dblclick", function (node) {
		conf.on_dbl_click.call(this, tnode(node));
	    });

	    // node color, size and labels are dynamic properties
	    node
		.select("circle")
		.transition()
		.attr('fill', function (d) {
		    return d3.functor(conf.node_color)(tnode(d));
		})
		.attr('r', function (d) {
		    return d3.functor(conf.node_circle_size)(tnode(d));
		})
		// node strokes are dynamic properties
		.attr('stroke', function (d) {
		    return d3.functor(conf.node_color)(tnode(d));
		});

	    // TODO: Shouldn't this be done only on new nodes? Old nodes should already have the labels
	    node
		.each (conf.label.remove)
		    .each (function (d) {
			conf.label.call(this, tnode(d));
		    });

	    node
		.transition()
		.ease(ease)
		.duration(conf.duration)
		.attr("transform", transform);

	    // Exiting nodes are just removed
	    node
		.exit()
		.remove();
	};
    };

    // API
    //var api = tnt.utils.api (tree)
    //	.getset (conf)

  //  tree.duration         = 500;      // Duration of the transitions
  //  tree.label            = label.text();
  //  tree.layout           = layout.vertical();
  //  tree.on_click         = function () {};
  //  tree.on_dbl_click     = function () {};
  //  tree.on_mouseover    = function () {};
  //  tree.link_color       = 'steelblue';
  //  node_color       = 'steelblue';
  //  node_circle_size = 4.5;

    // TODO: Rewrite data using getset / finalizers & transforms
    tree.data = function (d) {
	if (!arguments.length) {
	    return base.data;
	}

	// The original data is stored as the base and curr data
	base.data = d;
	curr.data = d;

	// Set up a new tree based on the data
	var newtree = tnode(base.data);

	tree.root(newtree);
	return tree;
    };

    // TODO: Rewrite tree using getset / finalizers & transforms
    tree.root = function (t) {
    	if (!arguments.length) {
    	    return curr.tree;
    	}

	// The original tree is stored as the base, prev and curr tree
    	base.tree = t;
	curr.tree = base.tree;
//	prev.tree = base.tree;
    	return tree;
    };

    tree.subtree = function (curr_nodes) {
	var subtree = base.tree.subtree(curr_nodes);
	curr.data = subtree.data();
	curr.tree = subtree;

	return tree;
    };

    tree.focus_node = function (node) {
	// find
	var found_node = tree.root().find_node_by_field(node.id(), '_id');
	focused_node = found_node
	tree.subtree(found_node.get_all_leaves());

	return tree;
    };

    tree.has_focus = function (node) {
	return ((focused_node !== undefined) && (focused_node.id() === node.id()));
    };

    tree.release_focus = function () {
	tree.data (base.data);
	focused_node = undefined;
	return tree;
    };

//    tree.tooltip = function () {
//	// var tooltip = tnt.tooltip().type("table");
//	var tooltip = tnt.tooltip.table();
//	var tree_tooltip = function (node) {
//	    node = node.data();
//	    var obj = {};
//	    obj.header = {
//		label : "Name",
//		value : node.name
//	    };
//	    obj.rows = [];
//	    obj.rows.push({
//		label : "_id",
//		value : node._id
//	    });
//	    obj.rows.push({
//		label : "Depth",
//		value : node.depth
//	    });
//	    obj.rows.push({
//		label : "Length",
//		value : node.length
//	    });
//	    obj.rows.push({
//		label : "N.Children",
//		value : node.children ? node.children.length : 0
//	    });
//	    tooltip.call(this, obj);
//	};
//
//	return tree_tooltip;
//    });

	// set default conf
	console.log(conf);
	for(var key in conf){
		console.log("key " +key);
		tree[key]= conf[key];
	}
	console.log(tree);
	console.log("--");

    return tree;
};

module.exports = tree;
<|endoftext|>


<commit_before>// Add your code here

//Placing at the bottom, adding the rest of the JS at top

$.getJSON( "http://mks-frontend-gallery.herokuapp.com/", function( json ) {
    console.log(json);
});<commit_msg>Added the example and review from class, need to focus on JSON this week to better understand.<commit_after>// Add your code here

$(document).ready(function(){
	var animals = [];

	$.getJSON( "https://mks-frontend-gallery.herokuapp.com/", function( json ) {
	  for (var i in json) {
	  	$(".gallery").append("

");
	  }
	  var ids = [];
	  $.each( json, function ( key, val ) {

	    for (var x = 0; x < val.animals.length; x++) {
	    	ids.push(
	    		val.animals[x]
	    	);
	    }

	    $.unique(ids);
	  });
	  for (i in ids) {
	  	$(".filters").append("
" + ids[i]+ "
");
	  }
	  console.log(ids);
	}).done(function(){
		console.log("done")
		$('.filter-button').click(function(){
			$(this).toggleClass("active");
			$("." + this.id).fadeToggle(1000, "swing", function(){console.log("fade is done")});
		});
	}).fail(function(){
		console.log("fail")
	});

});

//Placing at the bottom, adding the rest of the JS at top

//$.getJSON( "http://mks-frontend-gallery.herokuapp.com/", function( json ) {
//    console.log(json);
//});

<|endoftext|>


<commit_before>'use strict';

/* App Module */

var <%= angularAppName %> = angular.module('<%= angularAppName %>', ['ngResource', 'ngRoute']);

<%= angularAppName %>
    .config(function ($routeProvider) {
        $routeProvider
            .when('/login', {
                templateUrl: 'views/login.html',
                controller: 'LoginController'
            })
            .when('/settings', {
                templateUrl: 'views/settings.html',
                controller: 'SettingsController'
            })
            .when('/password', {
                templateUrl: 'views/password.html',
                controller: 'PasswordController'
            })
            .when('/sessions', {
                templateUrl: 'views/sessions.html',
                controller: 'SessionsController'
            })
            .when('/metrics', {
                templateUrl: 'views/metrics.html',
                controller: 'MetricsController'
            })
            .when('/logs', {
                templateUrl: 'views/logs.html',
                controller: 'LogsController'
            })
            .when('/logout', {
                templateUrl: 'views/main.html',
                controller: 'LogoutController'
            })
            .otherwise({
                templateUrl: 'views/main.html',
                controller: 'MainController'
            })

    });
<commit_msg>#18 improve spring security disconnection<commit_after>'use strict';

/* App Module */

var <%= angularAppName %> = angular.module('<%= angularAppName %>', ['ngResource', 'ngRoute']);

<%= angularAppName %>
    .config(function ($routeProvider, $httpProvider) {
        $routeProvider
            .when('/login', {
                templateUrl: 'views/login.html',
                controller: 'LoginController'
            })
            .when('/settings', {
                templateUrl: 'views/settings.html',
                controller: 'SettingsController'
            })
            .when('/password', {
                templateUrl: 'views/password.html',
                controller: 'PasswordController'
            })
            .when('/sessions', {
                templateUrl: 'views/sessions.html',
                controller: 'SessionsController'
            })
            .when('/metrics', {
                templateUrl: 'views/metrics.html',
                controller: 'MetricsController'
            })
            .when('/logs', {
                templateUrl: 'views/logs.html',
                controller: 'LogsController'
            })
            .when('/logout', {
                templateUrl: 'views/main.html',
                controller: 'LogoutController'
            })
            .otherwise({
                templateUrl: 'views/main.html',
                controller: 'MainController'
            })

        // Handle the 401 error
        var interceptor = ['$rootScope', '$q', function(scope, $q) {

            function success(response) {
                return response;
            }

            function error(response) {
                var status = response.status;

                if (status == 401) {
                    window.location = "login.html";
                    return;
                }
                // otherwise
                return $q.reject(response);

            }

            return function(promise) {
                return promise.then(success, error);
            }

        }];
        $httpProvider.responseInterceptors.push(interceptor);

    });
<|endoftext|>