diff options
Diffstat (limited to 'web/js/duplicates.js')
-rw-r--r-- | web/js/duplicates.js | 206 |
1 files changed, 206 insertions, 0 deletions
diff --git a/web/js/duplicates.js b/web/js/duplicates.js new file mode 100644 index 000000000..4ed54846c --- /dev/null +++ b/web/js/duplicates.js @@ -0,0 +1,206 @@ +$(function() { + + // Store a reference to the "duplicate" report pins so we can + // quickly remove them when we’re finished showing duplicates. + var current_duplicate_markers; + + // Report ID will be available on report inspect page, + // but undefined on new report page. + var report_id = $("#report_inspect_form .js-report-id").text() || undefined; + + function refresh_duplicate_list() { + // This function will return a jQuery Promise, so callbacks can be + // hooked onto it, once the ajax request as completed. + var dfd = $.Deferred(); + + var nearby_url; + var url_params = { + filter_category: $('select[name="category"]').val(), + latitude: $('input[name="latitude"]').val(), + longitude: $('input[name="longitude"]').val() + }; + + if ( report_id ) { + nearby_url = '/report/' + report_id + '/nearby.json'; + url_params.distance = 1000; // Inspectors might want to see reports fairly far away (1000 metres) + url_params.pin_size = 'small'; // How it's always been + } else { + nearby_url = '/around/nearby'; + url_params.distance = 250; // Only want to bother public with very nearby reports (250 metres) + url_params.pin_size = 'normal'; + } + + $.ajax({ + url: nearby_url, + data: url_params, + dataType: 'json' + }).done(function(response) { + if ( response.pins.length ){ + render_duplicate_list(response); + render_duplicate_pins(response); + } else { + remove_duplicate_pins(); + remove_duplicate_list(); + } + dfd.resolve(); + }).fail(function(){ + remove_duplicate_pins(); + remove_duplicate_list(); + dfd.reject(); + }); + + return dfd.promise(); + } + + function render_duplicate_list(api_response) { + var $reports = $( api_response.reports_list ); + + var duplicate_of = $('#report_inspect_form [name="duplicate_of"]').val(); + if ( duplicate_of ) { + $reports.filter('[data-report-id="' + duplicate_of + '"]') + .addClass("item-list__item--selected"); + } + + $("#js-duplicate-reports ul").empty().prepend( $reports ); + fixmystreet.set_up.fancybox_images(); + + $('#js-duplicate-reports').hide().removeClass('hidden').slideDown(); + if ( $('#problem_form').length ) { + $('.js-hide-if-invalid-category').slideUp(); + } + + // Highlight map pin when hovering associated list item. + var timeout; + $reports.on('mouseenter', function(){ + var id = parseInt( $(this).data('reportId'), 10 ); + clearTimeout( timeout ); + fixmystreet.maps.markers_highlight( id ); + }).on('mouseleave', function(){ + timeout = setTimeout( fixmystreet.maps.markers_highlight, 50 ); + }); + + // Add a "select this report" button, when on the report inspect form. + if ( $('#report_inspect_form').length ) { + $reports.each(function(){ + var $button = $('<button>').addClass('btn btn--small btn--primary'); + $button.text(translation_strings.this_report); + $button.on('click', function(e) { + e.preventDefault(); // Prevent button from submitting parent form + var report_id = $(this).closest('li').data('reportId'); + $('#report_inspect_form [name="duplicate_of"]').val(report_id); + $(this).closest('li') + .addClass('item-list__item--selected') + .siblings('.item-list__item--selected') + .removeClass('item-list__item--selected'); + }); + $(this).find('.item-list__item--expandable__actions').append($button); + }); + } + + // Add a "track this report" button when on the regular reporting form. + if ( $('#problem_form').length ) { + $reports.each(function() { + var $li = $(this); + var id = parseInt( $li.data('reportId'), 10 ); + var alert_url = '/alert/subscribe?id=' + encodeURIComponent(id); + var $button = $('<a>').addClass('btn btn--small btn--primary'); + $button.text(translation_strings.this_is_the_problem); + $button.attr('href', alert_url); + $button.on('click', function(e){ + e.preventDefault(); + var $div = $('.js-template-get-updates > div').clone(); + $div.find('input[name="id"]').val(id); + $div.find('input[disabled]').prop('disabled', false); + $div.hide().appendTo($li).slideDown(250, function(){ + $div.find('input[type="email"]').focus(); + }); + $li.find('.item-list__item--expandable__actions').slideUp(250); + $li.removeClass('js-expandable'); + $li.addClass('item-list__item--selected'); + }); + $li.find('.item-list__item--expandable__actions').append($button); + }); + } + } + + function render_duplicate_pins(api_response) { + var markers = fixmystreet.maps.markers_list( api_response.pins, true ); + fixmystreet.markers.removeFeatures( current_duplicate_markers ); + fixmystreet.markers.addFeatures( markers ); + current_duplicate_markers = markers; + } + + function remove_duplicate_list(cb) { + var animations = []; + + animations.push( $.Deferred() ); + $('#js-duplicate-reports').slideUp(function(){ + $(this).addClass('hidden'); + $(this).find('ul').empty(); + animations[0].resolve(); + }); + if ( $('#problem_form').length ) { + animations.push( $.Deferred() ); + $('.js-hide-if-invalid-category').slideDown(function(){ + animations[1].resolve(); + }); + } + + $.when.apply(this, animations).then(cb); + } + + function remove_duplicate_pins() { + fixmystreet.markers.removeFeatures( current_duplicate_markers ); + } + + function inspect_form_state_change() { + // The duplicate report list only makes sense when state is 'duplicate' + if ($(this).val() !== "duplicate") { + $("#js-duplicate-reports").addClass("hidden"); + return; + } else { + $("#js-duplicate-reports").removeClass("hidden"); + } + // If this report is already marked as a duplicate of another, then + // there's no need to refresh the list of duplicate reports + var duplicate_of = $("#report_inspect_form [name=duplicate_of]").val(); + if (!!duplicate_of) { + return; + } + refresh_duplicate_list(); + } + + var category_changing = false; + function problem_form_category_change() { + // Annoyingly this event seems to fire a few times in quick succession, + // so set a flag to avoid multiple overlapping refreshes. + if (category_changing) { return; } + category_changing = true; + + refresh_duplicate_list().always(function(){ + // Wait an extra second until we allow another reload. + setTimeout(function(){ + category_changing = false; + }, 1000); + }); + } + + // Want to show potential duplicates when a regular user starts a new + // report, or changes the category/location of a partial report. + $("#problem_form").on("change.category", "select#form_category", problem_form_category_change); + + // Want to show duplicates when an inspector sets a report’s state to "duplicate". + $("#report_inspect_form").on("change.state", "select#state", inspect_form_state_change); + + // Also want to give inspectors a way to select a *new* duplicate report. + $("#js-change-duplicate-report").click(refresh_duplicate_list); + + $('.js-hide-duplicate-suggestions').on('click', function(e){ + e.preventDefault(); + remove_duplicate_pins(); + remove_duplicate_list(function(){ + $('#form_title').focus(); + }); + }); + +}); |