<commit_before>/* Dispatch area - Should be eliminate after dispatching */

var markersGroup = new L.LayerGroup();
console.log("\n\n\n\n");
console.log("printining markersGroup");
console.log(markersGroup);
var isDispatching = false;
var isFilterOpen = false;
var placeIcon = L.icon({
	iconUrl: '/static/icons/place_marker.png',
	iconSize: [40, 40],
	iconAnchor: [20, 40],
	popupAnchor: [0,-40]
});

var dispatchingAmbulances = {};
var numberOfDispatchingAmbulances = 0;

var currentAddress;
var currentLocation;
var currentPatients;
var newPatientIndex;

var submitDispatching = function () {

    // submit form
    $('#dispatch-form-collapse').submit();

};

var beginDispatching = function () {

    isDispatching = true;
    var filtersDiv = $('#filtersDiv');
    isFilterOpen = filtersDiv.hasClass('show');
    console.log('Begin dispatching.');

    $('#dispatchBeginButton').hide();
    $('#dispatchSubmitButton').show();
    $('#dispatchCancelButton').show();

    // open filter and available ambulances
    filtersDiv.addClass('show');
    $('#ambulance_status').addClass('show');
    $('#ambulance_AV').addClass('show');

    // Update current location
    updateCurrentLocation(mymap.getCenter());

    // Update current address
    updateCurrentAddress(currentLocation);

    // Clear current currentPatients
    currentPatients = {};
    newPatientIndex = 0;

    // Initialize patient form
    $('#patients').empty();

    // add new patient form entry
    addPatientForm(newPatientIndex);

    // resize size
    resizeMap();

    // center map
    mymap.setView(currentLocation, mymap.getZoom());

}

var endDispatching = function () {

    isDispatching = false;
    dispatchingAmbulances = {};
    console.log('End dispatching.');

    markersGroup.clearLayers();

    $('#dispatchBeginButton').show();
    $('#dispatchSubmitButton').hide();
    $('#dispatchCancelButton').hide();

    // close dispatch panel
    $('#dispatchDiv').removeClass('show');

    if (!isFilterOpen) {
        // close filter panel
        $('#filtersDiv').removeClass('show');
    }

    // invalidate map size
    mymap.invalidateSize();

}

var removeFromDispatchingList = function(ambulance) {

    // delete from dispatching list
    delete dispatchingAmbulances[ambulance.id];
    numberOfDispatchingAmbulances--;

    // show message if last button
    if (numberOfDispatchingAmbulances == 0)
        $('#ambulance-selection-message').show();

}

var addToDispatchingList = function(ambulance) {

    // quick return if null or not dispatching
    if (ambulance == null || !isDispatching)
        return;

    // add ambulance to dispatching list
    console.log('Adding ambulance ' + ambulance.identifier + ' to dispatching list');

    // already in?
    if (ambulance.id in dispatchingAmbulances) {
        console.log('Already in dispatching list, skip');
        return;
    }

    // not available?
    if (ambulance.status != STATUS_AVAILABLE) {
        console.log('Ambulance is not available');
        bsalert('Can only dispatch available ambulances!');
        return;
    }

    // hide message if first button
    if (numberOfDispatchingAmbulances == 0)
        $('#ambulance-selection-message').hide();

    // add ambulance to list of dispatching ambulances
    dispatchingAmbulances[ambulance.id] = ambulance;
    numberOfDispatchingAmbulances++;

    // add button to ambulance dispatch grid
    $('#ambulance-selection').append(
        '<button id="dispatch-button-' + ambulance.id + '"'
        + ' value="' + ambulance.id + '"'
        + ' type="button" class="btn btn-sm '+ ambulance_buttons['AV'] + '"'
        + ' style="margin: 2px 2px;"'
        + ' draggable="true">'
        + ambulance.identifier
        + '</button>'
    );
    $('#dispatch-button-' + ambulance.id)
        .on('dragstart', function (e) {
            // on start of drag, copy information and fade button
            console.log('dragstart');
            this.style.opacity = '0.4';
            e.originalEvent.dataTransfer.setData("text/plain", ambulance.id);
        })
        .on('dragend', function (e) {
            console.log('dragend');
            if (e.originalEvent.dataTransfer.dropEffect == 'none') {
                // Remove button if not dropped back
                removeFromDispatchingList(ambulance);
                // Remove button
                $(this).remove();
            } else {
                // Restore opacity if dropped back in
                this.style.opacity = '1.0';
            }
        });
}

var updateCurrentLocation = function(location) {

    console.log('Setting current location to: ' + location.lat + ', ' + location.lng);

    // set currentLocation
    currentLocation = location;

    // update coordinates on form
    $('#curr-lat').html(currentLocation.lat.toFixed(6));
    $('#curr-lng').html(currentLocation.lng.toFixed(6));

    // remove existing marker
    markersGroup.clearLayers();

    // laydown marker
    var marker = L.marker(location,
        {
            icon: placeIcon,
            draggable: true
        })
        .addTo(markersGroup);
    markersGroup.addTo(mymap);

    // pan to location
    mymap.panTo(location);

    // events
    marker.on('dragend', function(e) {

			console.log("clicked in dblclick");
        updateCurrentLocation(marker.getLatLng());

        // update address?
        if ($('#update-address').prop('checked'))
            updateCurrentAddress(currentLocation);

    })

		mymap.on('contextmenu', function(e) {
			console.log("right click at:", e.latlng.lat, e.latlng.lng);
			console.log(e);
			updateCurrentLocation(e.latlng);
			// var popOpt = L.popup().setContent('
Hello world!
This is a nice popup.
');
			// popOpt.openOn(mymap);

		})

		// commented out by kaung to test double click
    // marker.on('dragend', function(e) {
		//
    //     // update current location
    //     updateCurrentLocation(marker.getLatLng());
		//
    //     // update address?
    //     if ($('#update-address').prop('checked'))
    //         updateCurrentAddress(currentLocation);
		//
    // })

}

var updateCurrentAddress = function(location) {

    var options = {
        types: 'address',
        limit: 1
    };
    geocoder.reverse(location, options,
        function (results, status) {

        if (status != "success") {
            bsalert("Could not geocode:\nError " + status + ", " + results['error']);
            return;
        }

        // quick return if found nothing
        if (results.length == 0) {
            console.log('Got nothing from geocode');
            return;
        }

        // parse features into current address
        currentAddress = geocoder.parse_feature(results[0]);

        console.log(
            'Setting currentAddress to:'
            + '\nnumber: ' + currentAddress['number']
            + '\nstreet: ' + currentAddress['street']
            + '\nunit: ' + currentAddress['unit']
            + '\nlocation: ' + currentAddress['location']['latitude']
            + ',' + currentAddress['location']['longitude']
            + '\nneighborhood: ' + currentAddress['neighborhood']
            + '\nzipcode: ' + currentAddress['zipcode']
            + '\ncity: ' + currentAddress['city']
            + '\nstate: ' + currentAddress['state']
            + '\ncountry: ' + currentAddress['country']
        );

        // set input text
        $('#street').val(currentAddress['street_address']);

    });

}

var updateCoordinates = function() {

    // when the user changes the street address
    var address =$('#street').val();

    // quick return if no address
    if (!address)
        return;

    // otherwise geocode and update
    var options = {
        types: 'address',
        limit: 1,
        autocomplete: 'true'
    };
    geocoder.geocode(address, options,
        function (results, status) {

            if (status != "success") {
                bsalert("Could not geocode:\nError " + status + ", " + results['error']);
                return;
            }

            // quick return if found nothing
            if (results.length == 0) {
                console.log('Got nothing from geocode');
                return;
            }

            // parse features into address
            var address = geocoder.parse_feature(results[0]);

            console.log(
                'Setting currentLocation to:'
                + '\nnumber: ' + address['number']
                + '\nstreet: ' + address['street']
                + '\nunit: ' + address['unit']
                + '\nlocation: ' + address['location']['latitude']
                + ',' + address['location']['longitude']
                + '\nneighborhood: ' + address['neighborhood']
                + '\nzipcode: ' + address['zipcode']
                + '\ncity: ' + address['city']
                + '\nstate: ' + address['state']
                + '\ncountry: ' + address['country']
            );

            // set current location
            updateCurrentLocation({
                lat: address['location']['latitude'],
                lng: address['location']['longitude']
            });

        });
}

function dispatchCall() {

    var form = {};

    // call information
    var street_address = $('#street').val().trim();
    form['details'] = $('#comment').val().trim();
    form['priority'] = $('input:radio[name=priority]:checked').val();

    // checks
    if (form["priority"] === undefined) {
        bsalert("Please select the priority level.");
        return;
    }
    if (numberOfDispatchingAmbulances == 0) {
        bsalert("Please dispatch at least one ambulance.");
        return;
    }

    // address information
    form['neighborhood'] = currentAddress['neighborhood'];
    form['city'] = currentAddress['city'];
    form['state'] = currentAddress['state'];
    form['country'] = currentAddress['country'];
    form['zipcode'] = currentAddress['zipcode'];
    form['location'] = currentAddress['location'];

    // Has the user modified the street address?
    if (street_address != currentAddress['street_address']) {

        // parse street address
        var address = geocoder.parse_street_address(street_address, form['country']);

        form['number'] = address['number'];
        form['street'] = address['street'];
        form['unit'] = address['unit'];

    } else {

        form['number'] = currentAddress['number'];
        form['street'] = currentAddress['street'];
        form['unit'] = currentAddress['unit'];

    }

    // Make sure blanks are undefined
    if (form['number'] == "") {
        form['number'] = undefined;
    }

    // ambulances
    var ambulances = [];
    for (var id in dispatchingAmbulances) {
        if (dispatchingAmbulances.hasOwnProperty(id))
            ambulances.push({ 'ambulance_id': id });
		}
    form['ambulancecall_set'] = ambulances;

    // patients
    var patients = [];
    for (var index in currentPatients)
        if (currentPatients.hasOwnProperty(index)) {
            var patient = currentPatients[index];
            var obj = { 'name': patient[0] };
            if (patient[1])
                // add age
                obj['age'] = parseInt(patient[1]);
            patients.push(obj);
        }
    form['patient_set'] = patients;

    // make json call
    var postJsonUrl = APIBaseUrl + 'call/';
    console.log("Form:");
    console.log(form);
    console.log("Will post:");
    console.log(JSON.stringify(form));

    var CSRFToken = Cookies.get('csrftoken');
    console.log('csrftoken = ' + CSRFToken);

    // retrieve csrf token
    $.ajaxSetup({
        beforeSend: function (xhr, settings) {
            if (!CSRFSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", CSRFToken);
            }
        }
    });

    // make ajax call
    $.ajax({
        url: postJsonUrl,
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        data: JSON.stringify(form),
        success: function (data) {

            // Log success
            console.log("Succesfully posted new call.");

            // End dispatching
            endDispatching();

        },
        error: function (jqXHR, textStatus, errorThrown) {

            // Log failure
            console.log("Failed to post new call.");
            console.log(jqXHR.responseText);

            // Show modal
            bsalert(jqXHR.responseText, 'alert-danger', 'Failure');

            // End dispatching
            endDispatching();

        }
    });
}

// patient functions

var addPatient = function(index) {

    console.log('Adding patient index ' + index);

    var name = $('#patient-' + index + '-name').val().trim();
    var age = $('#patient-' + index + '-age').val().trim();

    // is name empty?
    if (!name) {
        bsalert('Empty name');
        return;
    }

    // add name
    currentPatients[index] = [name, age];
    newPatientIndex++;

    // change button symbol
    var symbol = $('#patient-' + index + '-symbol');
    symbol.removeClass('fa-plus');
    symbol.addClass('fa-minus');

    // change button action from add to remove
    $('#patients').find('#patient-' + index + '-button')
        .off()
        .on('click', function(e) { removePatient(index); });

    // add new form
    addPatientForm(newPatientIndex);

}

var removePatient = function(index) {

    console.log('Removing patient index ' + index);

    // remove from storage
    delete currentPatients[index];

    // remove from form
    $('#patients')
        .find('#patient-' + index + '-form')
        .remove();

}

var addPatientForm = function(index) {

    // add new patient form entry
    $('#patients').append(newPatientForm(index, 'fa-plus'));

    // bind addPatient to click
    $('#patients')
        .on('click',
            '#patient-' + index + '-button',
            function(e) { addPatient(index); });

}

var newPatientForm = function(index, symbol) {

    var html =
        '
' +
            '
' +
                '<input id="patient-' + index + '-name" ' +
                       'type="text" ' +
                       'class="form-control" ' +
                       'placeholder="Name">' +
            '
' +
            '
' +
                '<input id="patient-' + index + '-age" ' +
                       'type="number" min="0" ' +
                       'class="form-control" ' +
                       'placeholder="Age">' +
            '
' +
            '
' +
                '<button class="btn btn-default btn-block new-patient" ' +
                       ' type="button" ' +
                       ' id="patient-' + index + '-button">' +
                    '' +
                '</button>' +
            '
' +
        '
';

    // console.log('html = "' + html + '"');

    return html;

}

// Ready function
$(function() {

    // connect actions to inputs

    $("#street").change(function () {

        // update coordinates?
        if ($('#update-coordinates').prop('checked'))
            updateCoordinates();

    });

    $('#update-coordinates').change(function () {

        // update coordinates?
        if ($('#update-coordinates').prop('checked'))
            updateCoordinates();

    });

    $('#update-address').change(function () {

        // update address?
        if ($('#update-address').prop('checked'))
            updateCurrentAddress(currentLocation);

    });

    $('#dispatch-form-collapse').submit(function (e) {

        // prevent normal form submission
        e.preventDefault();

        // dispatch call
        dispatchCall();

    });

});

// CSRF functions

function CSRFSafeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
<commit_msg>map fix<commit_after>/* Dispatch area - Should be eliminate after dispatching */

var markersGroup = new L.LayerGroup();
console.log("\n\n\n\n");
console.log("printining markersGroup");
console.log(markersGroup);
var isDispatching = false;
var isFilterOpen = false;
var placeIcon = L.icon({
	iconUrl: '/static/icons/place_marker.png',
	iconSize: [40, 40],
	iconAnchor: [20, 40],
	popupAnchor: [0,-40]
});

var dispatchingAmbulances = {};
var numberOfDispatchingAmbulances = 0;

var currentAddress;
var currentLocation;
var currentPatients;
var newPatientIndex;

var submitDispatching = function () {

    // submit form
    $('#dispatch-form-collapse').submit();

};

var beginDispatching = function () {

    isDispatching = true;
    var filtersDiv = $('#filtersDiv');
    isFilterOpen = filtersDiv.hasClass('show');
    console.log('Begin dispatching.');

    $('#dispatchBeginButton').hide();
    $('#dispatchSubmitButton').show();
    $('#dispatchCancelButton').show();

    // open filter and available ambulances
    filtersDiv.addClass('show');
    $('#ambulance_status').addClass('show');
    $('#ambulance_AV').addClass('show');

    // Update current location
    updateCurrentLocation(mymap.getCenter());

    // Update current address
    updateCurrentAddress(currentLocation);

    // Clear current currentPatients
    currentPatients = {};
    newPatientIndex = 0;

    // Initialize patient form
    $('#patients').empty();

    // add new patient form entry
    addPatientForm(newPatientIndex);

    // resize size
    resizeMap();

    // center map
    mymap.setView(currentLocation, mymap.getZoom());

}

var endDispatching = function () {

    isDispatching = false;
    dispatchingAmbulances = {};
    console.log('End dispatching.');

    markersGroup.clearLayers();

    $('#dispatchBeginButton').show();
    $('#dispatchSubmitButton').hide();
    $('#dispatchCancelButton').hide();

    // close dispatch panel
    $('#dispatchDiv').removeClass('show');

    if (!isFilterOpen) {
        // close filter panel
        $('#filtersDiv').removeClass('show');
    }

    // invalidate map size
    mymap.invalidateSize();

}

var removeFromDispatchingList = function(ambulance) {

    // delete from dispatching list
    delete dispatchingAmbulances[ambulance.id];
    numberOfDispatchingAmbulances--;

    // show message if last button
    if (numberOfDispatchingAmbulances == 0)
        $('#ambulance-selection-message').show();

}

var addToDispatchingList = function(ambulance) {

    // quick return if null or not dispatching
    if (ambulance == null || !isDispatching)
        return;

    // add ambulance to dispatching list
    console.log('Adding ambulance ' + ambulance.identifier + ' to dispatching list');

    // already in?
    if (ambulance.id in dispatchingAmbulances) {
        console.log('Already in dispatching list, skip');
        return;
    }

    // not available?
    if (ambulance.status != STATUS_AVAILABLE) {
        console.log('Ambulance is not available');
        bsalert('Can only dispatch available ambulances!');
        return;
    }

    // hide message if first button
    if (numberOfDispatchingAmbulances == 0)
        $('#ambulance-selection-message').hide();

    // add ambulance to list of dispatching ambulances
    dispatchingAmbulances[ambulance.id] = ambulance;
    numberOfDispatchingAmbulances++;

    // add button to ambulance dispatch grid
    $('#ambulance-selection').append(
        '<button id="dispatch-button-' + ambulance.id + '"'
        + ' value="' + ambulance.id + '"'
        + ' type="button" class="btn btn-sm '+ ambulance_buttons['AV'] + '"'
        + ' style="margin: 2px 2px;"'
        + ' draggable="true">'
        + ambulance.identifier
        + '</button>'
    );
    $('#dispatch-button-' + ambulance.id)
        .on('dragstart', function (e) {
            // on start of drag, copy information and fade button
            console.log('dragstart');
            this.style.opacity = '0.4';
            e.originalEvent.dataTransfer.setData("text/plain", ambulance.id);
        })
        .on('dragend', function (e) {
            console.log('dragend');
            if (e.originalEvent.dataTransfer.dropEffect == 'none') {
                // Remove button if not dropped back
                removeFromDispatchingList(ambulance);
                // Remove button
                $(this).remove();
            } else {
                // Restore opacity if dropped back in
                this.style.opacity = '1.0';
            }
        });
}

var updateCurrentLocation = function(location) {

    console.log('Setting current location to: ' + location.lat + ', ' + location.lng);

    // set currentLocation
    currentLocation = location;

    // update coordinates on form
    $('#curr-lat').html(currentLocation.lat.toFixed(6));
    $('#curr-lng').html(currentLocation.lng.toFixed(6));

    // remove existing marker
    markersGroup.clearLayers();

    // laydown marker
    var marker = L.marker(location,
        {
            icon: placeIcon,
            draggable: true
        })
        .addTo(markersGroup);
    markersGroup.addTo(mymap);

    // pan to location
    mymap.panTo(location);

    // events
    marker.on('dragend', function(e) {

			console.log("clicked in dblclick");
        updateCurrentLocation(marker.getLatLng());

        // update address?
        if ($('#update-address').prop('checked'))
            updateCurrentAddress(currentLocation);

    })

		// commented out by kaung to test double click
    // marker.on('dragend', function(e) {
		//
    //     // update current location
    //     updateCurrentLocation(marker.getLatLng());
		//
    //     // update address?
    //     if ($('#update-address').prop('checked'))
    //         updateCurrentAddress(currentLocation);
		//
    // })

}
mymap.on('contextmenu', function(e) {
	console.log("right click at:", e.latlng.lat, e.latlng.lng);
	console.log(e);
	updateCurrentLocation(e.latlng);
	// var popOpt = L.popup().setContent('
Hello world!
This is a nice popup.
');
	// popOpt.openOn(mymap);
	if ($('#update-address').prop('checked'))
			updateCurrentAddress(currentLocation);
})

var updateCurrentAddress = function(location) {

    var options = {
        types: 'address',
        limit: 1
    };
    geocoder.reverse(location, options,
        function (results, status) {

        if (status != "success") {
            bsalert("Could not geocode:\nError " + status + ", " + results['error']);
            return;
        }

        // quick return if found nothing
        if (results.length == 0) {
            console.log('Got nothing from geocode');
            return;
        }

        // parse features into current address
        currentAddress = geocoder.parse_feature(results[0]);

        console.log(
            'Setting currentAddress to:'
            + '\nnumber: ' + currentAddress['number']
            + '\nstreet: ' + currentAddress['street']
            + '\nunit: ' + currentAddress['unit']
            + '\nlocation: ' + currentAddress['location']['latitude']
            + ',' + currentAddress['location']['longitude']
            + '\nneighborhood: ' + currentAddress['neighborhood']
            + '\nzipcode: ' + currentAddress['zipcode']
            + '\ncity: ' + currentAddress['city']
            + '\nstate: ' + currentAddress['state']
            + '\ncountry: ' + currentAddress['country']
        );

        // set input text
        $('#street').val(currentAddress['street_address']);

    });

}

var updateCoordinates = function() {

    // when the user changes the street address
    var address =$('#street').val();

    // quick return if no address
    if (!address)
        return;

    // otherwise geocode and update
    var options = {
        types: 'address',
        limit: 1,
        autocomplete: 'true'
    };
    geocoder.geocode(address, options,
        function (results, status) {

            if (status != "success") {
                bsalert("Could not geocode:\nError " + status + ", " + results['error']);
                return;
            }

            // quick return if found nothing
            if (results.length == 0) {
                console.log('Got nothing from geocode');
                return;
            }

            // parse features into address
            var address = geocoder.parse_feature(results[0]);

            console.log(
                'Setting currentLocation to:'
                + '\nnumber: ' + address['number']
                + '\nstreet: ' + address['street']
                + '\nunit: ' + address['unit']
                + '\nlocation: ' + address['location']['latitude']
                + ',' + address['location']['longitude']
                + '\nneighborhood: ' + address['neighborhood']
                + '\nzipcode: ' + address['zipcode']
                + '\ncity: ' + address['city']
                + '\nstate: ' + address['state']
                + '\ncountry: ' + address['country']
            );

            // set current location
            updateCurrentLocation({
                lat: address['location']['latitude'],
                lng: address['location']['longitude']
            });

        });
}

function dispatchCall() {

    var form = {};

    // call information
    var street_address = $('#street').val().trim();
    form['details'] = $('#comment').val().trim();
    form['priority'] = $('input:radio[name=priority]:checked').val();

    // checks
    if (form["priority"] === undefined) {
        bsalert("Please select the priority level.");
        return;
    }
    if (numberOfDispatchingAmbulances == 0) {
        bsalert("Please dispatch at least one ambulance.");
        return;
    }

    // address information
    form['neighborhood'] = currentAddress['neighborhood'];
    form['city'] = currentAddress['city'];
    form['state'] = currentAddress['state'];
    form['country'] = currentAddress['country'];
    form['zipcode'] = currentAddress['zipcode'];
    form['location'] = currentAddress['location'];

    // Has the user modified the street address?
    if (street_address != currentAddress['street_address']) {

        // parse street address
        var address = geocoder.parse_street_address(street_address, form['country']);

        form['number'] = address['number'];
        form['street'] = address['street'];
        form['unit'] = address['unit'];

    } else {

        form['number'] = currentAddress['number'];
        form['street'] = currentAddress['street'];
        form['unit'] = currentAddress['unit'];

    }

    // Make sure blanks are undefined
    if (form['number'] == "") {
        form['number'] = undefined;
    }

    // ambulances
    var ambulances = [];
    for (var id in dispatchingAmbulances) {
        if (dispatchingAmbulances.hasOwnProperty(id))
            ambulances.push({ 'ambulance_id': id });
		}
    form['ambulancecall_set'] = ambulances;

    // patients
    var patients = [];
    for (var index in currentPatients)
        if (currentPatients.hasOwnProperty(index)) {
            var patient = currentPatients[index];
            var obj = { 'name': patient[0] };
            if (patient[1])
                // add age
                obj['age'] = parseInt(patient[1]);
            patients.push(obj);
        }
    form['patient_set'] = patients;

    // make json call
    var postJsonUrl = APIBaseUrl + 'call/';
    console.log("Form:");
    console.log(form);
    console.log("Will post:");
    console.log(JSON.stringify(form));

    var CSRFToken = Cookies.get('csrftoken');
    console.log('csrftoken = ' + CSRFToken);

    // retrieve csrf token
    $.ajaxSetup({
        beforeSend: function (xhr, settings) {
            if (!CSRFSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", CSRFToken);
            }
        }
    });

    // make ajax call
    $.ajax({
        url: postJsonUrl,
        type: 'POST',
        dataType: 'json',
        contentType: 'application/json',
        data: JSON.stringify(form),
        success: function (data) {

            // Log success
            console.log("Succesfully posted new call.");

            // End dispatching
            endDispatching();

        },
        error: function (jqXHR, textStatus, errorThrown) {

            // Log failure
            console.log("Failed to post new call.");
            console.log(jqXHR.responseText);

            // Show modal
            bsalert(jqXHR.responseText, 'alert-danger', 'Failure');

            // End dispatching
            endDispatching();

        }
    });
}

// patient functions

var addPatient = function(index) {

    console.log('Adding patient index ' + index);

    var name = $('#patient-' + index + '-name').val().trim();
    var age = $('#patient-' + index + '-age').val().trim();

    // is name empty?
    if (!name) {
        bsalert('Empty name');
        return;
    }

    // add name
    currentPatients[index] = [name, age];
    newPatientIndex++;

    // change button symbol
    var symbol = $('#patient-' + index + '-symbol');
    symbol.removeClass('fa-plus');
    symbol.addClass('fa-minus');

    // change button action from add to remove
    $('#patients').find('#patient-' + index + '-button')
        .off()
        .on('click', function(e) { removePatient(index); });

    // add new form
    addPatientForm(newPatientIndex);

}

var removePatient = function(index) {

    console.log('Removing patient index ' + index);

    // remove from storage
    delete currentPatients[index];

    // remove from form
    $('#patients')
        .find('#patient-' + index + '-form')
        .remove();

}

var addPatientForm = function(index) {

    // add new patient form entry
    $('#patients').append(newPatientForm(index, 'fa-plus'));

    // bind addPatient to click
    $('#patients')
        .on('click',
            '#patient-' + index + '-button',
            function(e) { addPatient(index); });

}

var newPatientForm = function(index, symbol) {

    var html =
        '
' +
            '
' +
                '<input id="patient-' + index + '-name" ' +
                       'type="text" ' +
                       'class="form-control" ' +
                       'placeholder="Name">' +
            '
' +
            '
' +
                '<input id="patient-' + index + '-age" ' +
                       'type="number" min="0" ' +
                       'class="form-control" ' +
                       'placeholder="Age">' +
            '
' +
            '
' +
                '<button class="btn btn-default btn-block new-patient" ' +
                       ' type="button" ' +
                       ' id="patient-' + index + '-button">' +
                    '' +
                '</button>' +
            '
' +
        '
';

    // console.log('html = "' + html + '"');

    return html;

}

// Ready function
$(function() {

    // connect actions to inputs

    $("#street").change(function () {

        // update coordinates?
        if ($('#update-coordinates').prop('checked'))
            updateCoordinates();

    });

    $('#update-coordinates').change(function () {

        // update coordinates?
        if ($('#update-coordinates').prop('checked'))
            updateCoordinates();

    });

    $('#update-address').change(function () {

        // update address?
        if ($('#update-address').prop('checked'))
            updateCurrentAddress(currentLocation);

    });

    $('#dispatch-form-collapse').submit(function (e) {

        // prevent normal form submission
        e.preventDefault();

        // dispatch call
        dispatchCall();

    });

});

// CSRF functions

function CSRFSafeMethod(method) {
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}
<|endoftext|>


<commit_before>/* This is the central Dissemin JavaScript library */
/* Every function should be inside this file */

/* ***
 * Miscellaneous
 * *** */

/* On AJAX errors, we like to be informed via Sentry */
$(document).ajaxError( function (event, jqXHR, ajaxSettings, thrownError) {
    try {
        Sentry.captureMessage(thrownError || jqXHR.statusText, {
            extra: {
                type: ajaxSettings.type,
                url: ajaxSettings.url,
                data: ajaxSettings.data,
                status: jqXHR.status,
                error: thrownError || jqXHR.statusText,
                response: jqXHR.responseText.substring(0, 100)
            }
        });
    }
    catch (e)
    {
        console.log(thrownError);
        console.log(ajaxSettings);
    }
});

/* Returns the current csrf token from the cookie. This is the recommend method by django: https://docs.djangoproject.com/en/2.2/ref/csrf/#ajax */
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

/* ***
 * Navigation
 * *** */

/* When changing language in dropdown, submit the form */
$(function() {
    $("#select-language").change(function() {
        $("#select-language").submit();
    });
});

/* This is the ORCID Logout. Pass the orcid_base_domain as parameter */
function orcidLogout (orcid_base_domain) {
    $.ajax({ url: 'https://' + orcid_base_domaon + '/userStatus.json?logUserOut=true',
        dataType: 'jsonp',
        success: function(result,status,xhr) {
                    window.location.href = '{% url "account_logout" %}';
                },
        error: function (xhr, status, error) {
                    window.location.href = '{% url "account_logout" %}';
                }
    })
}

/* ***
 * Search
 * *** */

/* Our strategy is: Reload a part of the page and process any messages that get delivered */

/* Prevent standard behaviour of form and execute some JS */

$(function () {
    $('#searchPapers').submit(function (e) {
        e.preventDefault();

        $('#paperSearchResults').css('opacity', '0.5');

        $.ajax ({
            contentType : 'application/json',
            data : $(this).serializeArray(),
            dataType : 'json',
            method : 'GET',
            success : function (result) {
                $('#paperSearchResults').html(result.listPapers);
            },
            timeout : 5000, // 5 seconds
        });

        $('#paperSearchResults').css('opacity', '');

    });
});

/* ***
 * Statistic
 * *** */

/* Setting colors for the pie */
var stats_colors = ["#FCD206", "#B9C909", "#419BE8", "#dddddd", "#122B52"];
var stats_colors_aggregated = ["#43A000", "#DB1456"];

/* Instead of the full number, which has a lot of digits, we use abbreviations */
function readablizeNumber (number) {
    var units = ['', 'K', 'M', 'G', 'T', 'P'];
    var e = Math.floor(Math.log(number) / Math.log(1000));
    return Math.round((number / Math.pow(1000, e))) + " " + units[e];
}

/* Preprocessing Data */
function preProcessData(data) {
    // The pie only shows active OA categories, which have graph_value = value, while inactive ones have graph_value = 0.
    data.aggregated[0].graph_value = data.aggregated[1].graph_value = 0
    for (var i = 0; i < 5; i++) {
        detail = data.detailed[i]
        detail.graph_value = 0
        if (data.on_statuses.length === 0 || -1 !== $.inArray(detail.id, data.on_statuses)) {
            var j = i < 2 ? 0 : 1
            data.aggregated[j].graph_value += detail.value
            detail.graph_value = detail.value
        }
    }
    // Avoid division by zero when there are no results.
    data.num_tot = data.aggregated[0].graph_value + data.aggregated[1].graph_value
    if (data.num_tot === 0) {
        data.detailed[3].dummy = 1
        data.aggregated[1].dummy = 1
    }
}

/* Showing the Pie itself, which is rendered with d3js */
function showStatsPie (data, chart_id, legend_id) {
    preProcessData(data)

    var detailed_data = data.detailed
    var aggregated_data = data.aggregated
    var w = 201, h = 145;
	var r = 100, mr = 50, imr = 45, ir = 40; // radii
    var color = d3.scale.ordinal().range(stats_colors);
    var color_agg = d3.scale.ordinal().range(stats_colors_aggregated);

	// Create the svg element

    var vis = d3.select("#"+chart_id)
        .append("svg:svg")
            .attr("width", w)
            .attr("height", h)
        .append("svg:g")
            .attr("transform", "translate(" + r + "," + r + ")"); //move the center of the pie chart from 0, 0 to radius, radius

	var parts = vis.selectAll("g.chart")
		.data([detailed_data, aggregated_data])
		.enter()
			.append("svg:g")
				.attr("class", "chart");

	// Outer detailed statistics

    var arc = d3.svg.arc() //this will create <path> elements for us using arc data
        .outerRadius(r)
		.innerRadius(mr);

    var pie = d3.layout.pie() //this will create arc data for us given a list of values
        .value(function(d) { return d.dummy || d.graph_value; }) //we must tell it out to access the value of each element in our data array
		.sort(null)
		.startAngle(-Math.PI/2)
		.endAngle(Math.PI/2);

    var arcs = d3.select(parts[0][0]).selectAll("g.slice") //this selects all <g> elements with class slice (there aren't any yet)
        .data(pie) //associate the generated pie data (an array of arcs, each having startAngle, endAngle and value properties)
        .enter() //this will create <g> elements for every "extra" data element that should be associated with a selection. The result is creating a <g> for every object in the data array
            .append("svg:g") //create a group to hold each slice (we will have a <path> and a <text> element associated with each slice)
                .attr("class", "slice") //allow us to style things in the slices (like text)
            .each(function(d) { this._current = d.value; });

    var paths = arcs.append("svg:path")
                .attr("fill", function(d, i) { return color(i); } ) //set the color for each slice to be chosen from the color function defined above
                .attr("d", arc); //this creates the actual SVG path using the associated data (pie) with the arc drawing function

	// Outer labels
    function translateText(thisArc, d) {
        //set the label's origin to the center of the arc
        //we have to make sure to set these before calling arc.centroid
        d.innerRadius = mr;
        d.outerRadius = r;
        return "translate(" + thisArc.centroid(d) + ")";//this gives us a pair of coordinates like [50, 50]
    }
    function textForLabel(d, i) {
         return (d.data.graph_value === 0 ? "" : readablizeNumber(d.data.graph_value));
    }
	var arcs_text = d3.select(parts[0][0]).selectAll()
        .data(pie)
        .enter()
        .append("svg:g")
        .attr("class", "statsSliceNumber");

    arcs_text.append("svg:text") //add a label to each slice
            .attr("transform", function(d) { return translateText(arc,d); })
            .attr("text-anchor", "middle") //center the text on it's origin
            .text(textForLabel);

	// Inner aggregated statistics

	var arc2 = d3.svg.arc()
        .outerRadius(imr)
		.innerRadius(ir);

	var arcs2 = d3.select(parts[0][1]).selectAll("g.slice")
        .data(pie)
        .enter()
        .append("svg:g")
        .attr("class", "slice");

    arcs2.append("svg:path")
        .attr("fill", function(d, i) { return color_agg(i); } )
        .attr("d", arc2);

	var arcs2_text = d3.select(parts[0][1]).selectAll()
        .data(pie)
        .enter()
        .append("svg:g")
        .attr("class", "statsSliceLegend");

    function lineX(d,i) {
        return arc2.centroid(d)[0];
    }
    function lineY1(d,i) {
        return arc2.centroid(d)[1]+5;
    }
    function lineY2(d,i) {
        return 2 + i*20;
    }
    function hideZero(d) {
        return d.data.graph_value ? null : "none"
    }
    arcs2_text.append("svg:line")
        .attr("x1", lineX)
        .attr("x2", lineX)
        .attr("y1", lineY1)
        .attr("y2", lineY2)
        .attr("style", "stroke:rgb(0,0,0);stroke-width:1");

    arcs2_text.style("display", hideZero)

    function transformAggregatedText(d, i) {
        d.innerRadius = 0;
        d.outerRadius = r/2;
        return "translate(" + arc2.centroid(d)[0] + ", "+ (15 + i*20) +")";
    }
    arcs2_text.append("svg:text")
        .attr("transform", transformAggregatedText)
        .attr("text-anchor", "middle")
        .text(function(d, i) { return aggregated_data[i].label });

	var captions = d3.select("#"+legend_id)

    function updatePie(data) {
        preProcessData(data)

        var arcs = d3.select(parts[0][0]).datum(data.detailed)
        var arcs2 = d3.select(parts[0][1]).datum(data.aggregated)
        var selectArcs = function(elt) { return arcs.selectAll(elt).data(pie).transition() }
        var selectArcs2 = function(elt) { return arcs2.selectAll(elt).data(pie).transition() }

        selectArcs("path")
            .attr("d", arc);
        selectArcs("text")
            .attr("transform",function(d) { return translateText(arc,d) })
            .text(textForLabel);
        selectArcs2("g.statsSliceLegend").style("display", hideZero)
        selectArcs2("path")
            .attr("d", arc2)
        selectArcs2("line")
            .attr("x1", lineX)
            .attr("x2", lineX)
            .attr("y1", lineY1)
            .attr("y2", lineY2);
        selectArcs2("text")
            .attr("transform", transformAggregatedText);
        captions.datum(data.detailed).selectAll("span.detail")
            .data(pie)
            .transition()
		    .text(function(d) { return formatNumbersThousands(d.data.value); });
    }

    return updatePie;
}

/* Insert thousand separator for better readability */
function formatNumbersThousands(value) {
    var thousandSeparator = get_format('THOUSAND_SEPARATOR');
    // Formatting with thousand separator is coming from
    // https://stackoverflow.com/a/2901298
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);
}
<commit_msg>Update pie after ajax request<commit_after>/* This is the central Dissemin JavaScript library */
/* Every function should be inside this file */

/* ***
 * Miscellaneous
 * *** */

/* On AJAX errors, we like to be informed via Sentry */
$(document).ajaxError( function (event, jqXHR, ajaxSettings, thrownError) {
    try {
        Sentry.captureMessage(thrownError || jqXHR.statusText, {
            extra: {
                type: ajaxSettings.type,
                url: ajaxSettings.url,
                data: ajaxSettings.data,
                status: jqXHR.status,
                error: thrownError || jqXHR.statusText,
                response: jqXHR.responseText.substring(0, 100)
            }
        });
    }
    catch (e)
    {
        console.log(thrownError);
        console.log(ajaxSettings);
    }
});

/* Returns the current csrf token from the cookie. This is the recommend method by django: https://docs.djangoproject.com/en/2.2/ref/csrf/#ajax */
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie !== '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = cookies[i].trim();
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) === (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

/* ***
 * Navigation
 * *** */

/* When changing language in dropdown, submit the form */
$(function() {
    $("#select-language").change(function() {
        $("#select-language").submit();
    });
});

/* This is the ORCID Logout. Pass the orcid_base_domain as parameter */
function orcidLogout (orcid_base_domain) {
    $.ajax({ url: 'https://' + orcid_base_domaon + '/userStatus.json?logUserOut=true',
        dataType: 'jsonp',
        success: function(result,status,xhr) {
                    window.location.href = '{% url "account_logout" %}';
                },
        error: function (xhr, status, error) {
                    window.location.href = '{% url "account_logout" %}';
                }
    })
}

/* ***
 * Search
 * *** */

/* Our strategy is: Reload a part of the page and process any messages that get delivered */

/* Prevent standard behaviour of form and execute some JS */

$(function () {
    $('#searchPapers').submit(function (e) {
        e.preventDefault();

        $('#paperSearchResults').css('opacity', '0.5');

        $.ajax ({
            contentType : 'application/json',
            data : $(this).serializeArray(),
            dataType : 'json',
            method : 'GET',
            success : function (result) {
                $('#paperSearchResults').html(result.listPapers);
                updateStats(result.stats);
            },
            timeout : 5000, // 5 seconds
        });

        $('#paperSearchResults').css('opacity', '');

    });
});

/* ***
 * Statistic
 * *** */

/* Setting colors for the pie */
var stats_colors = ["#FCD206", "#B9C909", "#419BE8", "#dddddd", "#122B52"];
var stats_colors_aggregated = ["#43A000", "#DB1456"];

/* Instead of the full number, which has a lot of digits, we use abbreviations */
function readablizeNumber (number) {
    var units = ['', 'K', 'M', 'G', 'T', 'P'];
    var e = Math.floor(Math.log(number) / Math.log(1000));
    return Math.round((number / Math.pow(1000, e))) + " " + units[e];
}

/* Preprocessing Data */
function preProcessData(data) {
    // The pie only shows active OA categories, which have graph_value = value, while inactive ones have graph_value = 0.
    data.aggregated[0].graph_value = data.aggregated[1].graph_value = 0
    for (var i = 0; i < 5; i++) {
        detail = data.detailed[i]
        detail.graph_value = 0
        if (data.on_statuses.length === 0 || -1 !== $.inArray(detail.id, data.on_statuses)) {
            var j = i < 2 ? 0 : 1
            data.aggregated[j].graph_value += detail.value
            detail.graph_value = detail.value
        }
    }
    // Avoid division by zero when there are no results.
    data.num_tot = data.aggregated[0].graph_value + data.aggregated[1].graph_value
    if (data.num_tot === 0) {
        data.detailed[3].dummy = 1
        data.aggregated[1].dummy = 1
    }
}

/* Showing the Pie itself, which is rendered with d3js */
function showStatsPie (data, chart_id, legend_id) {
    preProcessData(data)

    var detailed_data = data.detailed
    var aggregated_data = data.aggregated
    var w = 201, h = 145;
	var r = 100, mr = 50, imr = 45, ir = 40; // radii
    var color = d3.scale.ordinal().range(stats_colors);
    var color_agg = d3.scale.ordinal().range(stats_colors_aggregated);

	// Create the svg element

    var vis = d3.select("#"+chart_id)
        .append("svg:svg")
            .attr("width", w)
            .attr("height", h)
        .append("svg:g")
            .attr("transform", "translate(" + r + "," + r + ")"); //move the center of the pie chart from 0, 0 to radius, radius

	var parts = vis.selectAll("g.chart")
		.data([detailed_data, aggregated_data])
		.enter()
			.append("svg:g")
				.attr("class", "chart");

	// Outer detailed statistics

    var arc = d3.svg.arc() //this will create <path> elements for us using arc data
        .outerRadius(r)
		.innerRadius(mr);

    var pie = d3.layout.pie() //this will create arc data for us given a list of values
        .value(function(d) { return d.dummy || d.graph_value; }) //we must tell it out to access the value of each element in our data array
		.sort(null)
		.startAngle(-Math.PI/2)
		.endAngle(Math.PI/2);

    var arcs = d3.select(parts[0][0]).selectAll("g.slice") //this selects all <g> elements with class slice (there aren't any yet)
        .data(pie) //associate the generated pie data (an array of arcs, each having startAngle, endAngle and value properties)
        .enter() //this will create <g> elements for every "extra" data element that should be associated with a selection. The result is creating a <g> for every object in the data array
            .append("svg:g") //create a group to hold each slice (we will have a <path> and a <text> element associated with each slice)
                .attr("class", "slice") //allow us to style things in the slices (like text)
            .each(function(d) { this._current = d.value; });

    var paths = arcs.append("svg:path")
                .attr("fill", function(d, i) { return color(i); } ) //set the color for each slice to be chosen from the color function defined above
                .attr("d", arc); //this creates the actual SVG path using the associated data (pie) with the arc drawing function

	// Outer labels
    function translateText(thisArc, d) {
        //set the label's origin to the center of the arc
        //we have to make sure to set these before calling arc.centroid
        d.innerRadius = mr;
        d.outerRadius = r;
        return "translate(" + thisArc.centroid(d) + ")";//this gives us a pair of coordinates like [50, 50]
    }
    function textForLabel(d, i) {
         return (d.data.graph_value === 0 ? "" : readablizeNumber(d.data.graph_value));
    }
	var arcs_text = d3.select(parts[0][0]).selectAll()
        .data(pie)
        .enter()
        .append("svg:g")
        .attr("class", "statsSliceNumber");

    arcs_text.append("svg:text") //add a label to each slice
            .attr("transform", function(d) { return translateText(arc,d); })
            .attr("text-anchor", "middle") //center the text on it's origin
            .text(textForLabel);

	// Inner aggregated statistics

	var arc2 = d3.svg.arc()
        .outerRadius(imr)
		.innerRadius(ir);

	var arcs2 = d3.select(parts[0][1]).selectAll("g.slice")
        .data(pie)
        .enter()
        .append("svg:g")
        .attr("class", "slice");

    arcs2.append("svg:path")
        .attr("fill", function(d, i) { return color_agg(i); } )
        .attr("d", arc2);

	var arcs2_text = d3.select(parts[0][1]).selectAll()
        .data(pie)
        .enter()
        .append("svg:g")
        .attr("class", "statsSliceLegend");

    function lineX(d,i) {
        return arc2.centroid(d)[0];
    }
    function lineY1(d,i) {
        return arc2.centroid(d)[1]+5;
    }
    function lineY2(d,i) {
        return 2 + i*20;
    }
    function hideZero(d) {
        return d.data.graph_value ? null : "none"
    }
    arcs2_text.append("svg:line")
        .attr("x1", lineX)
        .attr("x2", lineX)
        .attr("y1", lineY1)
        .attr("y2", lineY2)
        .attr("style", "stroke:rgb(0,0,0);stroke-width:1");

    arcs2_text.style("display", hideZero)

    function transformAggregatedText(d, i) {
        d.innerRadius = 0;
        d.outerRadius = r/2;
        return "translate(" + arc2.centroid(d)[0] + ", "+ (15 + i*20) +")";
    }
    arcs2_text.append("svg:text")
        .attr("transform", transformAggregatedText)
        .attr("text-anchor", "middle")
        .text(function(d, i) { return aggregated_data[i].label });

	var captions = d3.select("#"+legend_id)

    function updatePie(data) {
        preProcessData(data)

        var arcs = d3.select(parts[0][0]).datum(data.detailed)
        var arcs2 = d3.select(parts[0][1]).datum(data.aggregated)
        var selectArcs = function(elt) { return arcs.selectAll(elt).data(pie).transition() }
        var selectArcs2 = function(elt) { return arcs2.selectAll(elt).data(pie).transition() }

        selectArcs("path")
            .attr("d", arc);
        selectArcs("text")
            .attr("transform",function(d) { return translateText(arc,d) })
            .text(textForLabel);
        selectArcs2("g.statsSliceLegend").style("display", hideZero)
        selectArcs2("path")
            .attr("d", arc2)
        selectArcs2("line")
            .attr("x1", lineX)
            .attr("x2", lineX)
            .attr("y1", lineY1)
            .attr("y2", lineY2);
        selectArcs2("text")
            .attr("transform", transformAggregatedText);
        captions.datum(data.detailed).selectAll("span.detail")
            .data(pie)
            .transition()
		    .text(function(d) { return formatNumbersThousands(d.data.value); });
    }

    return updatePie;
}

/* Insert thousand separator for better readability */
function formatNumbersThousands(value) {
    var thousandSeparator = get_format('THOUSAND_SEPARATOR');
    // Formatting with thousand separator is coming from
    // https://stackoverflow.com/a/2901298
    return value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, thousandSeparator);
}
<|endoftext|>


<commit_before>
Number.prototype.pad = function(size){
	// Unfortunate padding function....
	if(typeof(size) !== "number"){size = 2;}
	var s = String(this);
	while (s.length < size) s = "0" + s;
	return s;
}

function MailPile() {
	this.msgcache = [];
	this.searchcache = [];
}

MailPile.prototype.add = function() {}
MailPile.prototype.attach = function() {}
MailPile.prototype.compose = function() {}
MailPile.prototype.delete = function() {}
MailPile.prototype.extract = function() {}
MailPile.prototype.filter = function() {}
MailPile.prototype.help = function() {}
MailPile.prototype.load = function() {}
MailPile.prototype.mail = function() {}
MailPile.prototype.forward = function() {}
MailPile.prototype.next = function() {}
MailPile.prototype.order = function() {}
MailPile.prototype.optimize = function() {}
MailPile.prototype.previous = function() {}
MailPile.prototype.print = function() {}
MailPile.prototype.reply = function() {}
MailPile.prototype.rescan = function() {}
MailPile.prototype.gpgrecv = function() {}
MailPile.prototype.search = function(q) {
	var that = this;
	$("#qbox").val(q);
	this.json_get("search", {"q": q}, function(data) {
		$("#results tbody").empty();
		for (var i = 0; i < data.results.length; i++) {
			msg_info = data.results[i].msg_info;
			msg_tags = data.results[i].msg_tags;
			d = new Date(parseInt(msg_info[4], 36)*1000)
			zpymd = d.getFullYear() + "-" + (d.getMonth()+1).pad(2) + "-" + d.getDate().pad(2);
			ymd = d.getFullYear() + "-" + (d.getMonth()+1) + "-" + d.getDate();
			taghrefs = msg_tags.map(function(e){ return '' + e + ''}).join(" ");
			tr = $('

');
			tr.addClass((i%2==0)?"even":"odd");
			tr.append('<input type="checkbox" name="msg_' + msg_info[0] + '"/>	');
			tr.append('' + msg_info[5] + '	');
			tr.append('' + msg_info[6] + '	');
			tr.append('' + taghrefs + '	');
			tr.append('' + zpymd + '	');
			$("#results tbody").append(tr);
		}
		that.chatter(data.chatter);
	});
}
MailPile.prototype.set = function() {}
MailPile.prototype.tag = function() {}
MailPile.prototype.addtag = function() {}
MailPile.prototype.unset = function() {}
MailPile.prototype.update = function() {}
MailPile.prototype.view = function(idx, msgid) {
	var that = this;
	this.json_get("view", {"idx": idx, "msgid": msgid}, function(data) {
		$("#results").empty();
		$that.chatter(data.chatter);
	})
}

MailPile.prototype.json_get = function(cmd, params, callback) {
	var url;
	if (cmd == "view") {
		url = "/=" + params["idx"] + "/" + params["msgid"] + ".json";
	} else {
		url = "/_/" + cmd + ".json";
	}
	$.getJSON(url, params, callback);
}

MailPile.prototype.chatter = function(text) {
	$("#chatter").empty();
	for (var i = 0; i < text.length; i++) {
		$("#chatter").append(text[i] + "\n");
	}
}

var mailpile = new MailPile();

// Non-exposed functions: www, setup
<commit_msg>JS: Create the results table if need be.<commit_after>
Number.prototype.pad = function(size){
	// Unfortunate padding function....
	if(typeof(size) !== "number"){size = 2;}
	var s = String(this);
	while (s.length < size) s = "0" + s;
	return s;
}

function MailPile() {
	this.msgcache = [];
	this.searchcache = [];
}

MailPile.prototype.add = function() {}
MailPile.prototype.attach = function() {}
MailPile.prototype.compose = function() {}
MailPile.prototype.delete = function() {}
MailPile.prototype.extract = function() {}
MailPile.prototype.filter = function() {}
MailPile.prototype.help = function() {}
MailPile.prototype.load = function() {}
MailPile.prototype.mail = function() {}
MailPile.prototype.forward = function() {}
MailPile.prototype.next = function() {}
MailPile.prototype.order = function() {}
MailPile.prototype.optimize = function() {}
MailPile.prototype.previous = function() {}
MailPile.prototype.print = function() {}
MailPile.prototype.reply = function() {}
MailPile.prototype.rescan = function() {}
MailPile.prototype.gpgrecv = function() {}
MailPile.prototype.search = function(q) {
	var that = this;
	$("#qbox").val(q);
	this.json_get("search", {"q": q}, function(data) {
		if ($("#results").length == 0) {
			$("#content").prepend('

');
		}
		$("#results tbody").empty();
		for (var i = 0; i < data.results.length; i++) {
			msg_info = data.results[i].msg_info;
			msg_tags = data.results[i].msg_tags;
			d = new Date(parseInt(msg_info[4], 36)*1000)
			zpymd = d.getFullYear() + "-" + (d.getMonth()+1).pad(2) + "-" + d.getDate().pad(2);
			ymd = d.getFullYear() + "-" + (d.getMonth()+1) + "-" + d.getDate();
			taghrefs = msg_tags.map(function(e){ return '' + e + ''}).join(" ");
			tr = $('

');
			tr.addClass((i%2==0)?"even":"odd");
			tr.append('<input type="checkbox" name="msg_' + msg_info[0] + '"/>	');
			tr.append('' + msg_info[5] + '	');
			tr.append('' + msg_info[6] + '	');
			tr.append('' + taghrefs + '	');
			tr.append('' + zpymd + '	');
			$("#results tbody").append(tr);
		}
		that.chatter(data.chatter);
	});
}
MailPile.prototype.set = function() {}
MailPile.prototype.tag = function() {}
MailPile.prototype.addtag = function() {}
MailPile.prototype.unset = function() {}
MailPile.prototype.update = function() {}
MailPile.prototype.view = function(idx, msgid) {
	var that = this;
	this.json_get("view", {"idx": idx, "msgid": msgid}, function(data) {
		if ($("#results").length == 0) {
			$("#content").prepend('

');
		}
		$("#results").empty();
		$that.chatter(data.chatter);
	})
}

MailPile.prototype.json_get = function(cmd, params, callback) {
	var url;
	if (cmd == "view") {
		url = "/=" + params["idx"] + "/" + params["msgid"] + ".json";
	} else {
		url = "/_/" + cmd + ".json";
	}
	$.getJSON(url, params, callback);
}

MailPile.prototype.chatter = function(text) {
	$("#chatter").empty();
	for (var i = 0; i < text.length; i++) {
		$("#chatter").append(text[i] + "\n");
	}
}

var mailpile = new MailPile();

// Non-exposed functions: www, setup
<|endoftext|>


<commit_before>/*
 * Copyright (c) 2016 Bastien Brunnenstein
 * This source code is licensed under the BSD 3-Clause License found in the
 * LICENSE file in the root directory of this repository.
 */

// Enums from C#
var State = {
  New: 0x01,
  Confirmed: 0x02,
  Pending: 0x04,
  Resolved: 0x08
}

var Category = {
  Red: 0x01,
  Orange: 0x02,
  Yellow: 0x04,
  Green: 0x08,
  Cyan: 0x10,
  Blue: 0x20,
  Purple: 0x40
}

// Conversion utilities
function stateFromInt(i) {
  var s;
  for (s in State) {
    if (State[s] == i) return s;
  }
}

function categoryFromInt(i) {
  var s;
  for (s in Category) {
    if (Category[s] == i) return s;
  }
}

// HTML blocks
var bLoading = $("#b-loading");
var bError = $("#b-error");
var bAuth = $("#b-auth");
var bIssues = $("#b-issues");

// Auth
var aAnon;
var aUsername;
var aApiKey;

var aPermissions;

// Global issue list
var issueList;
var issueListFiltered;

var scenes;
var reporters;
var assignees;

// Filters
var fScene = null;
var fReporter = null;
var fAssignee = null;
var fState;
var fCategory;

// Hooks
function mwConnect() {
  bLoading.toggle(true);
  bAuth.toggle(false);

  aAnon = false;
  aUsername = $("#issue-user").val();
  aApiKey = $("#issue-key").val();

  doConnect();

  if ($("#issue-remember").is(':checked')) {
    localStorage.setItem("user", aUsername);
    localStorage.setItem("key", aApiKey);
  }
  else {
    localStorage.clear();
  }
}

function mwConnectAnon() {
  bLoading.toggle(true);
  bAuth.toggle(false);

  aAnon = true;
  aUsername = "Anonymous";
  aApiKey = "";

  doConnect();
}

function mwCloseError() {
  bError.toggle(false);
}

function mwUpdateFilters() {
  updateFilters();
  rebuildIssueList();
}

// Flow
function doConnect() {
  // Load all issues
  ajaxAuth()
    .always(function() {
      bLoading.toggle(false);
    })
    .done(function( result ) {
      if (!aAnon && !result.valid) {
        bAuth.toggle(true);
        showError("Authentication failed");
        return;
      }

      if (aPermissions.indexOf("admin") === -1
        && aPermissions.indexOf("view") === -1) {
        bAuth.toggle(true);
        showError("You don't have the permission to view the issue list");
        return;
      }

      bLoading.toggle(true);
      ajaxRefreshIssues()
        .always(function() {
          bLoading.toggle(false);
        })
        .done(function() {
          bIssues.toggle(true);
        })
        .fail(function() {
          bAuth.toggle(true);
        });
    })
    .fail(function() {
      bAuth.toggle(true);
    });
}

// Content creation
function showError(message) {
  $("#issue-error-text").text(message);
  bError.toggle(true);
}

function createDomForIssue(issue) {
  var dom = $("<li>");
  dom.addClass("list-group-item");

  // Title
  var title = $("<h4>").text("#" + issue.id + " " + issue.title);
  dom.append(title);

  // Badge
  var state = stateFromInt(issue.state);
  var category = categoryFromInt(issue.category);

  title.prepend($("<i>").addClass("issue-badge")
    .css("background-image",
      ("url('img/"+category+"-"+state+".png')").toLowerCase())
    .attr("title", category+" "+state));

  // Screenshot
  if (issue.hasScreenshot) {
    dom.append(
      $("<img>").attr("src", "issue/"+issue.id+"/screenshot"));
  }

  // Scene
  dom.append($("<p>").addClass("issue-scene")
    .text(issue.scene).prepend($("<i>").text("Scene: ")));

  // Description
  if (issue.description) {
    dom.append($("<p>").addClass("issue-description")
      .text(issue.description));
  }

  // Reporter
  dom.append($("<p>").addClass("issue-reporter")
    .text(issue.reporter).prepend($("<i>").text("Reporter: ")));

  // Assignee
  if (issue.assignee) {
    dom.append($("<p>").addClass("issue-assignee")
      .text(issue.assignee).prepend($("<i>").text("Assignee: ")));
  }

  // Add invisible clear at the end to prevent overflow
  dom.append($("<div>").addClass("clear"));

  return dom;
}

function refreshIssueList(list) {
  issueList = list;

  // Find every unique scene / reporter / assignee
  scenes = [];
  reporters = [];
  assignees = [];

  issueList.forEach(function(issue) {
    if (scenes.indexOf(issue.scene) === -1)
      scenes.push(issue.scene);
    if (reporters.indexOf(issue.reporter) === -1)
      reporters.push(issue.reporter);
    if (issue.assignee && assignees.indexOf(issue.assignee) === -1)
      assignees.push(issue.assignee);
  });

  scenes.sort();
  reporters.sort();
  assignees.sort();

  // Regex to remove "Assets/"
  var ex = /^Assets\//;

  var sceneSelect = $("#scene-filter");
  sceneSelect.html("");
  sceneSelect.append($("<option>").prop("value", "*").text("Show everything"));
  scenes.forEach(function(scene) {
    sceneSelect.append($("<option>").prop("value", scene).text(
      !!ex.exec(scene) ? scene.substr(7) : scene));
  });
  if (fScene) sceneSelect.val(fScene);

  var reporterSelect = $("#reporter-filter");
  reporterSelect.html("");
  reporterSelect.append($("<option>").prop("value", "*").text("Show everything"));
  reporters.forEach(function(reporter) {
    reporterSelect.append($("<option>").prop("value", reporter).text(reporter));
  });
  if (fReporter) reporterSelect.val(fReporter);

  var assigneeSelect = $("#assignee-filter");
  assigneeSelect.html("");
  assigneeSelect.append($("<option>").prop("value", "*").text("Show everything"));
  assigneeSelect.append($("<option>").prop("value", "-").text("Only show unassigned issues"));
  assignees.forEach(function(assignee) {
    assigneeSelect.append($("<option>").prop("value", assignee).text(assignee));
  });
  if (fAssignee) assigneeSelect.val(fAssignee);

  updateFilters();
}

function updateFilters() {
  fScene = $("#scene-filter").val();
  if (fScene === "*") fScene = null;

  fReporter = $("#reporter-filter").val();
  if (fReporter === "*") fReporter = null;

  fAssignee = $("#assignee-filter").val();
  if (fAssignee === "*") fAssignee = null;

  fState = 0;
  if (!$("#state-new").hasClass("filter-disabled")) fState |= State.New;
  if (!$("#state-confirmed").hasClass("filter-disabled")) fState |= State.Confirmed;
  if (!$("#state-pending").hasClass("filter-disabled")) fState |= State.Pending;
  if (!$("#state-resolved").hasClass("filter-disabled")) fState |= State.Resolved;

  fCategory = 0;
  if (!$("#cat-red").hasClass("filter-disabled")) fCategory |= Category.Red;
  if (!$("#cat-orange").hasClass("filter-disabled")) fCategory |= Category.Orange;
  if (!$("#cat-yellow").hasClass("filter-disabled")) fCategory |= Category.Yellow;
  if (!$("#cat-green").hasClass("filter-disabled")) fCategory |= Category.Green;
  if (!$("#cat-cyan").hasClass("filter-disabled")) fCategory |= Category.Cyan;
  if (!$("#cat-blue").hasClass("filter-disabled")) fCategory |= Category.Blue;
  if (!$("#cat-purple").hasClass("filter-disabled")) fCategory |= Category.Purple;

  issueListFiltered = [];

  issueList.forEach(function(issue) {
    if (fScene && issue.scene !== fScene) return;
    if (fReporter && issue.reporter !== fReporter) return;
    if (fAssignee && ((!issue.assignee && fAssignee === "-")
        || issue.assignee !== fAssignee)) return;
    if ((fState & issue.state) === 0) return;
    if ((fCategory & issue.category) === 0) return;

    issueListFiltered.push(issue);
  });
}

function rebuildIssueList() {
  var list = $("#issue-list");
  list.html("");

  issueListFiltered.forEach(function(issue) {
    list.append(createDomForIssue(issue));
  });
}

// Ajax calls
function ajaxAuth() {
  return $.ajax({
    method: "GET",
    url: "issue/auth",
    dataType: "json",
    data: { user: aUsername, key: aApiKey }
  })
    .done(function( result ) {
      aPermissions = result.permissions;
    })
    .fail(function( xhr ) {
      showError("Request failed : "+ xhr.statusText);
      console.error(xhr);
    });
}

function ajaxRefreshIssues() {
  return $.ajax({
    method: "GET",
    url: "issue",
    dataType: "json",
    data: { user: aUsername, key: aApiKey }
  })
    .done(function( result ) {
      refreshIssueList(result.list);
      rebuildIssueList();
    })
    .fail(function( xhr ) {
      showError("Request failed : "+ xhr.statusText);
      console.error(xhr);
    });
}

$(document).ready(function() {
  bLoading.toggle(false);
  bAuth.toggle(true);

  // Hooks
  $("#issue-cat-cont > a").on("click", function(event) {
    $(this).toggleClass("filter-disabled");
    mwUpdateFilters();
  });
  $("#issue-state-cont > a").on("click", function(event) {
    $(this).toggleClass("filter-disabled");
    mwUpdateFilters();
  });

  // Disable resolved by default
  $("#state-resolved").toggleClass("filter-disabled");

  // Load credentials from localStorage
  var key = localStorage.getItem("key");
  if (key) {
    $("#issue-key").val(key);

    $("#issue-remember").prop('checked', true);

    var user = localStorage.getItem("user");
    if (user) { $("#issue-user").val(user); }
  }

})
<commit_msg>Fix typo for unassigned issues filter<commit_after>/*
 * Copyright (c) 2016 Bastien Brunnenstein
 * This source code is licensed under the BSD 3-Clause License found in the
 * LICENSE file in the root directory of this repository.
 */

// Enums from C#
var State = {
  New: 0x01,
  Confirmed: 0x02,
  Pending: 0x04,
  Resolved: 0x08
}

var Category = {
  Red: 0x01,
  Orange: 0x02,
  Yellow: 0x04,
  Green: 0x08,
  Cyan: 0x10,
  Blue: 0x20,
  Purple: 0x40
}

// Conversion utilities
function stateFromInt(i) {
  var s;
  for (s in State) {
    if (State[s] == i) return s;
  }
}

function categoryFromInt(i) {
  var s;
  for (s in Category) {
    if (Category[s] == i) return s;
  }
}

// HTML blocks
var bLoading = $("#b-loading");
var bError = $("#b-error");
var bAuth = $("#b-auth");
var bIssues = $("#b-issues");

// Auth
var aAnon;
var aUsername;
var aApiKey;

var aPermissions;

// Global issue list
var issueList;
var issueListFiltered;

var scenes;
var reporters;
var assignees;

// Filters
var fScene = null;
var fReporter = null;
var fAssignee = null;
var fState;
var fCategory;

// Hooks
function mwConnect() {
  bLoading.toggle(true);
  bAuth.toggle(false);

  aAnon = false;
  aUsername = $("#issue-user").val();
  aApiKey = $("#issue-key").val();

  doConnect();

  if ($("#issue-remember").is(':checked')) {
    localStorage.setItem("user", aUsername);
    localStorage.setItem("key", aApiKey);
  }
  else {
    localStorage.clear();
  }
}

function mwConnectAnon() {
  bLoading.toggle(true);
  bAuth.toggle(false);

  aAnon = true;
  aUsername = "Anonymous";
  aApiKey = "";

  doConnect();
}

function mwCloseError() {
  bError.toggle(false);
}

function mwUpdateFilters() {
  updateFilters();
  rebuildIssueList();
}

// Flow
function doConnect() {
  // Load all issues
  ajaxAuth()
    .always(function() {
      bLoading.toggle(false);
    })
    .done(function( result ) {
      if (!aAnon && !result.valid) {
        bAuth.toggle(true);
        showError("Authentication failed");
        return;
      }

      if (aPermissions.indexOf("admin") === -1
        && aPermissions.indexOf("view") === -1) {
        bAuth.toggle(true);
        showError("You don't have the permission to view the issue list");
        return;
      }

      bLoading.toggle(true);
      ajaxRefreshIssues()
        .always(function() {
          bLoading.toggle(false);
        })
        .done(function() {
          bIssues.toggle(true);
        })
        .fail(function() {
          bAuth.toggle(true);
        });
    })
    .fail(function() {
      bAuth.toggle(true);
    });
}

// Content creation
function showError(message) {
  $("#issue-error-text").text(message);
  bError.toggle(true);
}

function createDomForIssue(issue) {
  var dom = $("<li>");
  dom.addClass("list-group-item");

  // Title
  var title = $("<h4>").text("#" + issue.id + " " + issue.title);
  dom.append(title);

  // Badge
  var state = stateFromInt(issue.state);
  var category = categoryFromInt(issue.category);

  title.prepend($("<i>").addClass("issue-badge")
    .css("background-image",
      ("url('img/"+category+"-"+state+".png')").toLowerCase())
    .attr("title", category+" "+state));

  // Screenshot
  if (issue.hasScreenshot) {
    dom.append(
      $("<img>").attr("src", "issue/"+issue.id+"/screenshot"));
  }

  // Scene
  dom.append($("<p>").addClass("issue-scene")
    .text(issue.scene).prepend($("<i>").text("Scene: ")));

  // Description
  if (issue.description) {
    dom.append($("<p>").addClass("issue-description")
      .text(issue.description));
  }

  // Reporter
  dom.append($("<p>").addClass("issue-reporter")
    .text(issue.reporter).prepend($("<i>").text("Reporter: ")));

  // Assignee
  if (issue.assignee) {
    dom.append($("<p>").addClass("issue-assignee")
      .text(issue.assignee).prepend($("<i>").text("Assignee: ")));
  }

  // Add invisible clear at the end to prevent overflow
  dom.append($("<div>").addClass("clear"));

  return dom;
}

function refreshIssueList(list) {
  issueList = list;

  // Find every unique scene / reporter / assignee
  scenes = [];
  reporters = [];
  assignees = [];

  issueList.forEach(function(issue) {
    if (scenes.indexOf(issue.scene) === -1)
      scenes.push(issue.scene);
    if (reporters.indexOf(issue.reporter) === -1)
      reporters.push(issue.reporter);
    if (issue.assignee && assignees.indexOf(issue.assignee) === -1)
      assignees.push(issue.assignee);
  });

  scenes.sort();
  reporters.sort();
  assignees.sort();

  // Regex to remove "Assets/"
  var ex = /^Assets\//;

  var sceneSelect = $("#scene-filter");
  sceneSelect.html("");
  sceneSelect.append($("<option>").prop("value", "*").text("Show everything"));
  scenes.forEach(function(scene) {
    sceneSelect.append($("<option>").prop("value", scene).text(
      !!ex.exec(scene) ? scene.substr(7) : scene));
  });
  if (fScene) sceneSelect.val(fScene);

  var reporterSelect = $("#reporter-filter");
  reporterSelect.html("");
  reporterSelect.append($("<option>").prop("value", "*").text("Show everything"));
  reporters.forEach(function(reporter) {
    reporterSelect.append($("<option>").prop("value", reporter).text(reporter));
  });
  if (fReporter) reporterSelect.val(fReporter);

  var assigneeSelect = $("#assignee-filter");
  assigneeSelect.html("");
  assigneeSelect.append($("<option>").prop("value", "*").text("Show everything"));
  assigneeSelect.append($("<option>").prop("value", "-").text("Only show unassigned issues"));
  assignees.forEach(function(assignee) {
    assigneeSelect.append($("<option>").prop("value", assignee).text(assignee));
  });
  if (fAssignee) assigneeSelect.val(fAssignee);

  updateFilters();
}

function updateFilters() {
  fScene = $("#scene-filter").val();
  if (fScene === "*") fScene = null;

  fReporter = $("#reporter-filter").val();
  if (fReporter === "*") fReporter = null;

  fAssignee = $("#assignee-filter").val();
  if (fAssignee === "*") fAssignee = null;

  fState = 0;
  if (!$("#state-new").hasClass("filter-disabled")) fState |= State.New;
  if (!$("#state-confirmed").hasClass("filter-disabled")) fState |= State.Confirmed;
  if (!$("#state-pending").hasClass("filter-disabled")) fState |= State.Pending;
  if (!$("#state-resolved").hasClass("filter-disabled")) fState |= State.Resolved;

  fCategory = 0;
  if (!$("#cat-red").hasClass("filter-disabled")) fCategory |= Category.Red;
  if (!$("#cat-orange").hasClass("filter-disabled")) fCategory |= Category.Orange;
  if (!$("#cat-yellow").hasClass("filter-disabled")) fCategory |= Category.Yellow;
  if (!$("#cat-green").hasClass("filter-disabled")) fCategory |= Category.Green;
  if (!$("#cat-cyan").hasClass("filter-disabled")) fCategory |= Category.Cyan;
  if (!$("#cat-blue").hasClass("filter-disabled")) fCategory |= Category.Blue;
  if (!$("#cat-purple").hasClass("filter-disabled")) fCategory |= Category.Purple;

  issueListFiltered = [];

  issueList.forEach(function(issue) {
    if (fScene && issue.scene !== fScene) return;
    if (fReporter && issue.reporter !== fReporter) return;
    if (fAssignee && ((!issue.assignee && fAssignee !== "-")
        || (issue.assignee && issue.assignee !== fAssignee))) return;
    if ((fState & issue.state) === 0) return;
    if ((fCategory & issue.category) === 0) return;

    issueListFiltered.push(issue);
  });
}

function rebuildIssueList() {
  var list = $("#issue-list");
  list.html("");

  issueListFiltered.forEach(function(issue) {
    list.append(createDomForIssue(issue));
  });
}

// Ajax calls
function ajaxAuth() {
  return $.ajax({
    method: "GET",
    url: "issue/auth",
    dataType: "json",
    data: { user: aUsername, key: aApiKey }
  })
    .done(function( result ) {
      aPermissions = result.permissions;
    })
    .fail(function( xhr ) {
      showError("Request failed : "+ xhr.statusText);
      console.error(xhr);
    });
}

function ajaxRefreshIssues() {
  return $.ajax({
    method: "GET",
    url: "issue",
    dataType: "json",
    data: { user: aUsername, key: aApiKey }
  })
    .done(function( result ) {
      refreshIssueList(result.list);
      rebuildIssueList();
    })
    .fail(function( xhr ) {
      showError("Request failed : "+ xhr.statusText);
      console.error(xhr);
    });
}

$(document).ready(function() {
  bLoading.toggle(false);
  bAuth.toggle(true);

  // Hooks
  $("#issue-cat-cont > a").on("click", function(event) {
    $(this).toggleClass("filter-disabled");
    mwUpdateFilters();
  });
  $("#issue-state-cont > a").on("click", function(event) {
    $(this).toggleClass("filter-disabled");
    mwUpdateFilters();
  });

  // Disable resolved by default
  $("#state-resolved").toggleClass("filter-disabled");

  // Load credentials from localStorage
  var key = localStorage.getItem("key");
  if (key) {
    $("#issue-key").val(key);

    $("#issue-remember").prop('checked', true);

    var user = localStorage.getItem("user");
    if (user) { $("#issue-user").val(user); }
  }

})
<|endoftext|>


<commit_before>// Queue handler for ajax requests
ajax_handler = [];

// Abort any unfinished ajax requests
function kill_ajax() {
    $.each(ajax_handler, function( index, value ) { value.abort() });
    ajax_handler.length = 0;
}

// Submit for all records
function run_records(form_data) {

    var records = [ "Recent", "Historical", "Malware", "SafeBrowsing", "Search" ];

    $.each(records, function( index, record ) {
        // Clear out old information from DOM elements and submit new ajax requests
        $(record).empty();

        // Push additional form data to differentiate ajax requests
        form_data.push({name: 'record_type', value: record});

        send_ajax(form_data, record);

        // Pop off additional form data to in preparation for next request
        form_data.pop();
    });
}

// Submit request for record
function send_ajax(form_data, record){

    var record_element = "#" + record + "Panel";

    ajax_handler.push(
        $.ajax({
            type:"POST",
            url:"/pivoteer/",
            data: form_data,
            beforeSend: function(xhr, settings) {
                $(record_element).html("
Retrieving data
");
                $('a[href='+record_element+']').find("span").attr("class", "glyphicon glyphicon-hourglass");
            },

            error: function (){
                $( record_element ).html('
Unable to retrieve records
');
                $('a[href='+record_element+']').find("span").attr("class", "glyphicon glyphicon-exclamation-sign");
            },

            success: function (task){
                if (task.errors) {
                    $( record_element ).html(task.errors.indicator);
                    $('a[href='+record_element+']').find("span").attr("class", "glyphicon glyphicon-exclamation-sign");
                } else {
                    poll_ajax(task.id, record_element);
                }
            }
        })
    );
}

// Poll for record completion
function poll_ajax(task, record_element){

    var parameters = {task_id: task};

    $.ajax({
        type:"POST",
        url:"/pivoteer/tasks/",
        data: parameters,

        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        },

        error: function (){
            $(record_element).html('
Unable to retrieve records
');
        },

        success: function (task_results){
            if (task_results.status == 'loading') {
                setTimeout(function() { poll_ajax(task, record_element); }, 6000); // wait 3 seconds then call ajax request again
            } else {
                $(record_element).html(task_results);
                initialize_table(record_element);
                $('a[href='+record_element+']').find("span").attr("class", "glyphicon glyphicon-ok-sign");
            }
        }

    });
}

// Initiate data table elements on returned records
function initialize_table(record_element) {

    if (record_element == '#RecentPanel') {
        $('#CR_table').dataTable({
            "iDisplayLength":  15,
            "info":            false,
            "bLengthChange":   false,
            "bFilter":         false
        });

    } else if (record_element == "#HistoricalPanel") {
        $('#HR_table').dataTable({
            "iDisplayLength":  50,
            "info":            false,
            "bLengthChange":   false
        });

        $('#HW_table').dataTable({
            "iDisplayLength":  10,
            "info":            false,
            "bLengthChange":   false,
            "bFilter":         false
        });

    } else if (record_element == "#MalwarePanel") {
        $('#MR_table').dataTable({
            "iDisplayLength":  50,
            "info":            false,
            "bLengthChange":   false
        });
    } else if (record_element == "#SafeBrowsingPanel") {
        $('#SS_table').dataTable({
            "iDisplayLength": 50,
            "info": false,
            "bLengthChange": false
        });
    } else if (record_element == "#SearchPanel") {
        $('#SR_table').dataTable({
            "iDisplayLength":  50,
            "info":            false,
            "bLengthChange":   false
        })
    }
}

// Cookie Handling Using jQuery
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

var csrftoken = getCookie('csrftoken');
// End Cookie Handling

// Custom method on form submission to begin research
$('#research_indicator').submit(function( event ){
    event.preventDefault();
    kill_ajax();

    $("#pivot_navigator").show();

    // Populate data for ajax and DOM manipulation
    var entry = $('input[name=indicator]').val();
    var form_data = $('#research_indicator').serializeArray();

    // Clear out pivot navigation menu and insert new initial entry
    $("#pivot_navigator").empty().append("
" + entry + "
");

    run_records(form_data);
});

$('#content').on('click', '.pivot', function( event ){
    kill_ajax();

    $("#pivot_navigator").show();

    var pivot = $(this).text();
    var pivot_data = [{name: "indicator", value: pivot}, {name: "csrfmiddlewaretoken", value: csrftoken}];

    // Check if this is a back pivot or a new pivot
    if ($(this).hasClass('tracking')){
        $( '.pivot' ).parent().slice($(this).parent().index() + 1).remove();
    }
    else {
        $("#pivot_navigator").append("
" + pivot + "
");
    }

    run_records(pivot_data);
});

// Manipulate displayed elements upon initial page load
$( document ).ready(function() {
    $("#pivot_navigator").hide();
});

$("#export").on( "click", "a", function(event) {
    // Capture link event
    event.preventDefault();

    // Grab reference to link within event context
    var link = $(this);
    var linkURL = link.attr("href");
    var current_pivot = $("#pivot_navigator").find("li").last().find("span").text();
    var fullURL = linkURL + "?indicator=" + current_pivot;
    window.open(fullURL);
});<commit_msg>Fixed bug in export button where multiple query parameters were being sent incorrectly<commit_after>// Queue handler for ajax requests
ajax_handler = [];

// Abort any unfinished ajax requests
function kill_ajax() {
    $.each(ajax_handler, function( index, value ) { value.abort() });
    ajax_handler.length = 0;
}

// Submit for all records
function run_records(form_data) {

    var records = [ "Recent", "Historical", "Malware", "SafeBrowsing", "Search" ];

    $.each(records, function( index, record ) {
        // Clear out old information from DOM elements and submit new ajax requests
        $(record).empty();

        // Push additional form data to differentiate ajax requests
        form_data.push({name: 'record_type', value: record});

        send_ajax(form_data, record);

        // Pop off additional form data to in preparation for next request
        form_data.pop();
    });
}

// Submit request for record
function send_ajax(form_data, record){

    var record_element = "#" + record + "Panel";

    ajax_handler.push(
        $.ajax({
            type:"POST",
            url:"/pivoteer/",
            data: form_data,
            beforeSend: function(xhr, settings) {
                $(record_element).html("
Retrieving data
");
                $('a[href='+record_element+']').find("span").attr("class", "glyphicon glyphicon-hourglass");
            },

            error: function (){
                $( record_element ).html('
Unable to retrieve records
');
                $('a[href='+record_element+']').find("span").attr("class", "glyphicon glyphicon-exclamation-sign");
            },

            success: function (task){
                if (task.errors) {
                    $( record_element ).html(task.errors.indicator);
                    $('a[href='+record_element+']').find("span").attr("class", "glyphicon glyphicon-exclamation-sign");
                } else {
                    poll_ajax(task.id, record_element);
                }
            }
        })
    );
}

// Poll for record completion
function poll_ajax(task, record_element){

    var parameters = {task_id: task};

    $.ajax({
        type:"POST",
        url:"/pivoteer/tasks/",
        data: parameters,

        beforeSend: function(xhr, settings) {
            if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
                xhr.setRequestHeader("X-CSRFToken", csrftoken);
            }
        },

        error: function (){
            $(record_element).html('
Unable to retrieve records
');
        },

        success: function (task_results){
            if (task_results.status == 'loading') {
                setTimeout(function() { poll_ajax(task, record_element); }, 6000); // wait 3 seconds then call ajax request again
            } else {
                $(record_element).html(task_results);
                initialize_table(record_element);
                $('a[href='+record_element+']').find("span").attr("class", "glyphicon glyphicon-ok-sign");
            }
        }

    });
}

// Initiate data table elements on returned records
function initialize_table(record_element) {

    if (record_element == '#RecentPanel') {
        $('#CR_table').dataTable({
            "iDisplayLength":  15,
            "info":            false,
            "bLengthChange":   false,
            "bFilter":         false
        });

    } else if (record_element == "#HistoricalPanel") {
        $('#HR_table').dataTable({
            "iDisplayLength":  50,
            "info":            false,
            "bLengthChange":   false
        });

        $('#HW_table').dataTable({
            "iDisplayLength":  10,
            "info":            false,
            "bLengthChange":   false,
            "bFilter":         false
        });

    } else if (record_element == "#MalwarePanel") {
        $('#MR_table').dataTable({
            "iDisplayLength":  50,
            "info":            false,
            "bLengthChange":   false
        });
    } else if (record_element == "#SafeBrowsingPanel") {
        $('#SS_table').dataTable({
            "iDisplayLength": 50,
            "info": false,
            "bLengthChange": false
        });
    } else if (record_element == "#SearchPanel") {
        $('#SR_table').dataTable({
            "iDisplayLength":  50,
            "info":            false,
            "bLengthChange":   false
        })
    }
}

// Cookie Handling Using jQuery
function getCookie(name) {
    var cookieValue = null;
    if (document.cookie && document.cookie != '') {
        var cookies = document.cookie.split(';');
        for (var i = 0; i < cookies.length; i++) {
            var cookie = jQuery.trim(cookies[i]);
            // Does this cookie string begin with the name we want?
            if (cookie.substring(0, name.length + 1) == (name + '=')) {
                cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                break;
            }
        }
    }
    return cookieValue;
}

function csrfSafeMethod(method) {
    // these HTTP methods do not require CSRF protection
    return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
}

var csrftoken = getCookie('csrftoken');
// End Cookie Handling

// Custom method on form submission to begin research
$('#research_indicator').submit(function( event ){
    event.preventDefault();
    kill_ajax();

    $("#pivot_navigator").show();

    // Populate data for ajax and DOM manipulation
    var entry = $('input[name=indicator]').val();
    var form_data = $('#research_indicator').serializeArray();

    // Clear out pivot navigation menu and insert new initial entry
    $("#pivot_navigator").empty().append("
" + entry + "
");

    run_records(form_data);
});

$('#content').on('click', '.pivot', function( event ){
    kill_ajax();

    $("#pivot_navigator").show();

    var pivot = $(this).text();
    var pivot_data = [{name: "indicator", value: pivot}, {name: "csrfmiddlewaretoken", value: csrftoken}];

    // Check if this is a back pivot or a new pivot
    if ($(this).hasClass('tracking')){
        $( '.pivot' ).parent().slice($(this).parent().index() + 1).remove();
    }
    else {
        $("#pivot_navigator").append("
" + pivot + "
");
    }

    run_records(pivot_data);
});

// Manipulate displayed elements upon initial page load
$( document ).ready(function() {
    $("#pivot_navigator").hide();
});

$("#export").on( "click", "a", function(event) {
    // Capture link event
    event.preventDefault();

    // Grab reference to link within event context
    var link = $(this);
    var linkURL = link.attr("href");
    var current_pivot = $("#pivot_navigator").find("li").last().find("span").text();
    var fullURL = linkURL + "&indicator=" + current_pivot;
    window.open(fullURL);
});<|endoftext|>


<commit_before>// The settings.js file contains the parameters of this website... You can change this as example for testing...
settings = {
	"api":{
		"schema":{
			"list":"https://api.hcr01.io/extern/monitor/hcrs",
			"details":"https://api.hcr01.io/extern/monitor/hcrs/{id}/details"
		}
	},
	"languages":["en_US", "de_DE"],
	"preferredLanguage":"en_US"
};
<commit_msg>api updates<commit_after>// The settings.js file contains the parameters of this website... You can change this as example for testing...
settings = {
	"api":{
		"schema":{
			"list":"https://api.hcr01.io/v0.1/hcrs",
			"details":"https://api.hcr01.io/v0.1/hcrs/{id}"
		}
	},
	"languages":["en_US", "de_DE"],
	"preferredLanguage":"en_US"
};
<|endoftext|>


<commit_before>let platTmpl = document.createElement('template');
platTmpl.innerHTML = `

`;

class PlatformPop extends HTMLElement {

  constructor() {
    super(); // always call super() first in the constructor.

    // Attach a shadow root to the element.
    let shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.appendChild(platTmpl.content.cloneNode(true));
  }

  static get observedAttributes() {
    return ['platform'];
  }

  get platform() {
    return this.hasAttribute('platform');
  }

  set platform(val) {
    if (val) {
      this.setAttribute('platform', val);

      if (val === 'Samsung' || val === 'Android' || val === 'ios') {
        this.shadowRoot.querySelector('img').src="~/assets/images/android-screen.png";
      }
      else if (val === 'Progressive Web App') {
        this.shadowRoot.querySelector('img').src="~/assets/images/pwa-screen.png";
      }
      else if (val === 'Microsoft Teams') {
        this.shadowRoot.querySelector('img').src="~/assets/images/teams-screen.png";
      }
      else {
        this.shadowRoot.querySelector('img').src="~/assets/images/pwabuilder-screen.png";
      }
    } else {
      this.removeAttribute('platform');
    }
  }

}

window.customElements.define('platform-pop', PlatformPop);<commit_msg>chore(): path fix again<commit_after>let platTmpl = document.createElement('template');
platTmpl.innerHTML = `

`;

class PlatformPop extends HTMLElement {

  constructor() {
    super(); // always call super() first in the constructor.

    // Attach a shadow root to the element.
    let shadowRoot = this.attachShadow({mode: 'open'});
    shadowRoot.appendChild(platTmpl.content.cloneNode(true));
  }

  static get observedAttributes() {
    return ['platform'];
  }

  get platform() {
    return this.hasAttribute('platform');
  }

  set platform(val) {
    if (val) {
      this.setAttribute('platform', val);

      if (val === 'Samsung' || val === 'Android' || val === 'ios') {
        this.shadowRoot.querySelector('img').src="/static/Images/android-screen.png";
      }
      else if (val === 'Progressive Web App') {
        this.shadowRoot.querySelector('img').src="/static/Images/pwa-screen.png";
      }
      else if (val === 'Microsoft Teams') {
        this.shadowRoot.querySelector('img').src="/static/Images/teams-screen.png";
      }
      else {
        this.shadowRoot.querySelector('img').src="/static/Images/pwabuilder-screen.png";
      }
    } else {
      this.removeAttribute('platform');
    }
  }

}

window.customElements.define('platform-pop', PlatformPop);<|endoftext|>