diff options
author | Marius Halden <marius.h@lden.org> | 2017-12-20 01:06:27 +0100 |
---|---|---|
committer | Marius Halden <marius.h@lden.org> | 2017-12-20 01:06:27 +0100 |
commit | 8b10c8b8d787e680bb085e2a7543dac50fd39742 (patch) | |
tree | 391efde6de4944e350cc0dafbd4e1efb0613e9c3 /web/js | |
parent | eef35397ccf8242cdc65dc666db2958b1ee35440 (diff) | |
parent | 7e15bd3db202363db4bab8fa7c9f462eabe28fce (diff) |
Merge tag 'v2.3' into fiksgatami-dev
Diffstat (limited to 'web/js')
-rw-r--r-- | web/js/dashboard.js | 194 | ||||
-rw-r--r-- | web/js/front.js | 18 | ||||
-rw-r--r-- | web/js/geolocation.js | 43 | ||||
-rw-r--r-- | web/js/jquery.fixedthead.js | 81 | ||||
-rw-r--r-- | web/js/jquery.multi-select.js | 334 | ||||
-rw-r--r-- | web/js/map-OpenLayers.js | 149 | ||||
-rw-r--r-- | web/js/map-bing-ol.js | 8 | ||||
-rw-r--r-- | web/js/map-fms.js | 8 | ||||
-rw-r--r-- | web/js/map-google.js | 47 | ||||
-rw-r--r-- | web/js/map-wmts-bristol.js | 9 | ||||
-rw-r--r-- | web/js/map-wmts-zurich.js | 8 |
11 files changed, 322 insertions, 577 deletions
diff --git a/web/js/dashboard.js b/web/js/dashboard.js index f436b8d18..a6e06e048 100644 --- a/web/js/dashboard.js +++ b/web/js/dashboard.js @@ -1,6 +1,26 @@ $(function(){ Chart.defaults.global.defaultFontSize = 16; + Chart.defaults.global.defaultFontFamily = $('body').css('font-family'); + + var colours = [ + '#FF4343', // red + '#F4A140', // orange + '#FFD000', // yellow + '#62B356', // green + '#4D96E5', // blue + '#B446CA', // purple + '#7B8B98', // gunmetal + '#BCB590', // taupe + '#9C0101', // dark red + '#CA6D00', // dark orange + '#C2A526', // dark yellow + '#1D7710', // dark green + '#1D64B1', // dark blue + '#7A108F', // dark purple + '#3B576E', // dark gunmetal + '#655F3A' // dark taupe + ]; var setUpLabelsForChart = function(chart){ var $parent = $(chart.chart.canvas).parent(); @@ -89,54 +109,142 @@ $(function(){ ); }); - var $allReports = $('#chart-all-reports'), - labels = $allReports.data('labels'), - data0 = $allReports.data('values-reports'), - data1 = $allReports.data('values-fixed'); - window.chartAllReports = new Chart($allReports, { - type: 'line', - data: { - labels: labels, - datasets: [{ - data: data0, - pointRadius: pointRadiusFinalDot(data0.length, 4), - pointBackgroundColor: '#F4A140', - borderColor: '#F4A140' - }, { - data: data1, - pointRadius: pointRadiusFinalDot(data1.length, 4), - pointBackgroundColor: '#62B356', - borderColor: '#62B356' - }] - }, - options: { - animation: { - onComplete: function(){ - setUpLabelsForChart(this); - } - }, - layout: { - padding: { - top: 4 - } + $('#chart-all-reports').each(function(){ + var $allReports = $(this), + labels = $allReports.data('labels'), + data0 = $allReports.data('values-reports'), + data1 = $allReports.data('values-fixed'); + + window.chartAllReports = new Chart($allReports, { + type: 'line', + data: { + labels: labels, + datasets: [{ + data: data0, + pointRadius: pointRadiusFinalDot(data0.length, 4), + pointBackgroundColor: colours[1], + borderColor: colours[1] + }, { + data: data1, + pointRadius: pointRadiusFinalDot(data1.length, 4), + pointBackgroundColor: colours[3], + borderColor: colours[3] + }] }, - scales: { - xAxes: [{ - type: 'category', - gridLines: { - display: false + options: { + animation: { + onComplete: function(){ + setUpLabelsForChart(this); } - }], - yAxes: [{ - type: "linear", - ticks: { - display: false + }, + layout: { + padding: { + top: 4 } + }, + scales: { + xAxes: [{ + type: 'category', + gridLines: { + display: false + } + }], + yAxes: [{ + type: "linear", + ticks: { + display: false + } + }] + }, + onResize: function(chart, size){ + setUpLabelsForChart(chart); + } + } + }); + }); + + $('.js-make-bar-chart').each(function(){ + var $table = $(this); + var $trs = $table.find('tr'); + var $wrapper = $('<div>').addClass('responsive-bar-chart').insertBefore($table); + var $canvas = $('<canvas>').attr({ + 'width': 600, + 'height': 30 * $trs.length + }).appendTo($wrapper); + var rowLabels = []; + var rowValues = []; + + $trs.each(function(){ + rowLabels.push( $(this).find('th').text() ); + rowValues.push( parseInt($(this).find('td').text(), 10) ); + }); + + for (var i=colours.length; i<rowLabels.length; i++) { + colours[i] = colours[i % colours.length]; + } + + var barChart = new Chart($canvas, { + type: 'horizontalBar', + data: { + labels: rowLabels, + datasets: [{ + label: "", + data: rowValues, + backgroundColor: colours }] }, - onResize: function(chart, size){ - setUpLabelsForChart(chart); + options: { + animation: { + onComplete: function(){ + // Label each bar with the numerical value. + var chartInstance = this.chart, + ctx = chartInstance.ctx; + + ctx.font = Chart.helpers.fontString( Chart.defaults.global.defaultFontSize * 0.8, 'bold', Chart.defaults.global.defaultFontFamily); + ctx.textAlign = 'right'; + ctx.textBaseline = 'middle'; + + this.data.datasets.forEach(function (dataset, i) { + var meta = chartInstance.controller.getDatasetMeta(i); + meta.data.forEach(function (bar, index) { + var dataValue = dataset.data[index]; + var width_text = ctx.measureText(dataValue).width; + var width_bar = bar._model.x - bar._model.base; + var gutter = (bar._model.height - (Chart.defaults.global.defaultFontSize * 0.8)) / 2; + var textX; + if (width_text + 2 * gutter > width_bar) { + textX = bar._model.x + 2 * gutter; + ctx.fillStyle = bar._model.backgroundColor; + } else { + textX = bar._model.x - gutter; + ctx.fillStyle = '#fff'; + } + ctx.fillText( dataValue, textX, bar._model.y ); + }); + }); + } + }, + scales: { + xAxes: [{ + gridLines: { + drawBorder: false, + drawTicks: false + }, + ticks: { + beginAtZero: true, + maxTicksLimit: 11, + display: false + } + }], + yAxes: [{ + gridLines: { + display: false + } + }] + } } - } + }); + + $table.hide(); }); }); diff --git a/web/js/front.js b/web/js/front.js new file mode 100644 index 000000000..8471972d4 --- /dev/null +++ b/web/js/front.js @@ -0,0 +1,18 @@ +document.getElementById('pc').focus(); + +(function(){ + var around_forms = document.querySelectorAll('form[action*="around"]'); + for (var i=0; i<around_forms.length; i++) { + var form = around_forms[i]; + var el = document.createElement('input'); + el.type = 'hidden'; + el.name = 'js'; + el.value = 1; + form.insertBefore(el, form.firstChild); + } + var around_links = document.querySelectorAll('a[href*="around"]'); + for (i=0; i<around_links.length; i++) { + var link = around_links[i]; + link.href = link.href + (link.href.indexOf('?') > -1 ? '&js=1' : '?js=1'); + } +})(); diff --git a/web/js/geolocation.js b/web/js/geolocation.js new file mode 100644 index 000000000..3c2cf04df --- /dev/null +++ b/web/js/geolocation.js @@ -0,0 +1,43 @@ +var fixmystreet = fixmystreet || {}; + +fixmystreet.geolocate = function(element, success_callback) { + element.addEventListener('click', function(e) { + var link = this; + e.preventDefault(); + link.className += ' loading'; + navigator.geolocation.getCurrentPosition(function(pos) { + link.className = link.className.replace(/loading/, ' '); + success_callback(pos); + }, function(err) { + link.className = link.className.replace(/loading/, ' '); + if (err.code === 1) { // User said no + link.innerHTML = translation_strings.geolocation_declined; + } else if (err.code === 2) { // No position + link.innerHTML = translation_strings.geolocation_no_position; + } else if (err.code === 3) { // Too long + link.innerHTML = translation_strings.geolocation_no_result; + } else { // Unknown + link.innerHTML = translation_strings.geolocation_unknown; + } + }, { + enableHighAccuracy: true, + timeout: 10000 + }); + }); +}; + +(function(){ + var link = document.getElementById('geolocate_link'); + if (!link) { return; } + var https = window.location.protocol.toLowerCase() === 'https:'; + if ('geolocation' in navigator && https) { + fixmystreet.geolocate(link, function(pos) { + var latitude = pos.coords.latitude.toFixed(6); + var longitude = pos.coords.longitude.toFixed(6); + var coords = 'latitude=' + latitude + ';longitude=' + longitude; + location.href = link.href + (link.href.indexOf('?') > -1 ? ';' : '?') + coords; + }); + } else { + link.style.display = 'none'; + } +})(); diff --git a/web/js/jquery.fixedthead.js b/web/js/jquery.fixedthead.js deleted file mode 100644 index 33e60f721..000000000 --- a/web/js/jquery.fixedthead.js +++ /dev/null @@ -1,81 +0,0 @@ -/* - * jQuery.fixedThead.js - * By Zarino at mySociety - */ - -(function ($) { - - // Call this on a <thead> element and it'll be given a class - // of '.js-fixed-thead__clone' when you scroll down. eg: - // $('#my-table thead').fixedThead() - // - // You'll probably want to specify some CSS styles like: - // .js-fixed-thead__clone { position: fixed; background: #fff; } - - $.fn.fixedThead = function() { - - var calculateCloneDimensions = function calculateCloneDimensions($originalThead, $cloneThead){ - $cloneThead.css({ - width: $originalThead.width() - }); - - $('tr', $originalThead).each(function(tr_index, tr){ - $('th', tr).each(function(th_index, th){ - $cloneThead.find('tr:eq(' + tr_index + ') th:eq(' + th_index + ')').css({ - width: $(th).width() - }); - }); - }); - } - - var showOrHideClone = function showOrHideClone($table, $originalThead, $cloneThead){ - var bounds = $table[0].getBoundingClientRect(); - - // First we detect whether *any* of the table is visible, - // then, if it is, we position the fixed thead so that it - // never extends outside of the table bounds even when the - // visible portion of the table is shorter than the thead. - - if(bounds.top <= 0 && bounds.bottom >= 0){ - $cloneThead.css('display', $originalThead.css('display')); - - var rowHeight = $cloneThead.outerHeight(); - if(bounds.bottom < rowHeight){ - $cloneThead.css({ - top: (rowHeight - bounds.bottom) * -1 - }); - } else { - $cloneThead.css({ - top: 0 - }); - } - - } else { - $cloneThead.css('display', 'none'); - } - } - - return this.each(function() { - var $originalThead = $(this); - var $table = $originalThead.parent('table'); - var $cloneThead = $originalThead.clone().addClass('js-fixed-thead__clone'); - - $cloneThead.insertAfter($originalThead); - $cloneThead.css('display', 'none'); - - calculateCloneDimensions($originalThead, $cloneThead); - showOrHideClone($table, $originalThead, $cloneThead); - - $(window).resize(function(){ - calculateCloneDimensions($originalThead, $cloneThead); - showOrHideClone($table, $originalThead, $cloneThead); - }); - - $(window).scroll(function(){ - showOrHideClone($table, $originalThead, $cloneThead); - }); - }); - - }; - -}(jQuery)); diff --git a/web/js/jquery.multi-select.js b/web/js/jquery.multi-select.js deleted file mode 100644 index 38921b147..000000000 --- a/web/js/jquery.multi-select.js +++ /dev/null @@ -1,334 +0,0 @@ -// jquery.multi-select.js -// by mySociety -// https://github.com/mysociety/jquery-multi-select - -(function($) { - - var pluginName = "multiSelect", - defaults = { - containerHTML: '<div class="multi-select-container">', - menuHTML: '<div class="multi-select-menu">', - buttonHTML: '<span class="multi-select-button">', - menuItemsHTML: '<div class="multi-select-menuitems">', - menuItemHTML: '<label class="multi-select-menuitem">', - presetsHTML: '<div class="multi-select-presets">', - activeClass: 'multi-select-container--open', - noneText: '-- Select --', - allText: undefined, - presets: undefined, - positionedMenuClass: 'multi-select-container--positioned', - positionMenuWithin: undefined - }; - - function Plugin(element, options) { - this.element = element; - this.$element = $(element); - this.settings = $.extend( {}, defaults, options ); - this._defaults = defaults; - this._name = pluginName; - this.init(); - } - - function arraysAreEqual(array1, array2) { - if ( array1.length != array2.length ){ - return false; - } - - array1.sort(); - array2.sort(); - - for ( var i = 0; i < array1.length; i++ ){ - if ( array1[i] !== array2[i] ){ - return false; - } - } - - return true; - } - - $.extend(Plugin.prototype, { - - init: function() { - this.checkSuitableInput(); - this.findLabels(); - this.constructContainer(); - this.constructButton(); - this.constructMenu(); - - this.setUpBodyClickListener(); - this.setUpLabelsClickListener(); - - this.$element.hide(); - }, - - checkSuitableInput: function(text) { - if ( this.$element.is('select[multiple]') === false ) { - throw new Error('$.multiSelect only works on <select multiple> elements'); - } - }, - - findLabels: function() { - this.$labels = $('label[for="' + this.$element.attr('id') + '"]'); - }, - - constructContainer: function() { - this.$container = $(this.settings.containerHTML); - this.$element.data('multi-select-container', this.$container); - this.$container.insertAfter(this.$element); - }, - - constructButton: function() { - var _this = this; - this.$button = $(this.settings.buttonHTML); - this.$button.attr({ - 'role': 'button', - 'aria-haspopup': 'true', - 'tabindex': 0, - 'aria-label': this.$labels.eq(0).text() - }) - .on('keydown.multiselect', function(e) { - var key = e.which; - var returnKey = 13; - var spaceKey = 32; - if ((key === returnKey) || (key === spaceKey)) { - _this.$button.click(); - } - }).on('click.multiselect', function(e) { - _this.menuToggle(); - }) - .appendTo(this.$container); - - this.$element.on('change.multiselect', function() { - _this.updateButtonContents(); - }); - - this.updateButtonContents(); - }, - - updateButtonContents: function() { - var _this = this; - var options = []; - var selected = []; - - this.$element.children('option').each(function() { - var text = $(this).text(); - options.push(text); - if ($(this).is(':selected')) { - selected.push( $.trim(text) ); - } - }); - - this.$button.empty(); - - if (selected.length === 0) { - this.$button.text( this.settings.noneText ); - } else if ( (selected.length === options.length) && this.settings.allText) { - this.$button.text( this.settings.allText ); - } else { - this.$button.text( selected.join(', ') ); - } - }, - - constructMenu: function() { - var _this = this; - - this.$menu = $(this.settings.menuHTML); - this.$menu.attr({ - 'role': 'menu' - }).on('keyup.multiselect', function(e){ - var key = e.which; - var escapeKey = 27; - if (key === escapeKey) { - _this.menuHide(); - } - }) - .appendTo(this.$container); - - this.constructMenuItems(); - - if ( this.settings.presets ) { - this.constructPresets(); - } - }, - - constructMenuItems: function() { - var _this = this; - - this.$menuItems = $(this.settings.menuItemsHTML); - this.$menu.append(this.$menuItems); - - this.$element.on('change.multiselect', function(e, internal) { - // Don't need to update the menu items if this - // change event was fired by our tickbox handler. - if(internal !== true){ - _this.updateMenuItems(); - } - }); - - this.updateMenuItems(); - }, - - updateMenuItems: function() { - var _this = this; - this.$menuItems.empty(); - - this.$element.children('option').each(function(option_index, option) { - var $item = _this.constructMenuItem($(option), option_index); - _this.$menuItems.append($item); - }); - }, - - constructPresets: function() { - var _this = this; - this.$presets = $(this.settings.presetsHTML); - this.$menu.prepend(this.$presets); - - $.each(this.settings.presets, function(i, preset){ - var unique_id = _this.$element.attr('name') + '_preset_' + i; - var $item = $(_this.settings.menuItemHTML) - .attr({ - 'for': unique_id, - 'role': 'menuitem' - }) - .text(' ' + preset.name) - .appendTo(_this.$presets); - - var $input = $('<input>') - .attr({ - 'type': 'radio', - 'name': _this.$element.attr('name') + '_presets', - 'id': unique_id - }) - .prependTo($item); - - $input.on('change.multiselect', function(){ - _this.$element.val(preset.options); - _this.$element.trigger('change'); - }); - }); - - this.$element.on('change.multiselect', function() { - _this.updatePresets(); - }); - - this.updatePresets(); - }, - - updatePresets: function() { - var _this = this; - - $.each(this.settings.presets, function(i, preset){ - var unique_id = _this.$element.attr('name') + '_preset_' + i; - var $input = _this.$presets.find('#' + unique_id); - - if ( arraysAreEqual(preset.options || [], _this.$element.val() || []) ){ - $input.prop('checked', true); - } else { - $input.prop('checked', false); - } - }); - }, - - constructMenuItem: function($option, option_index) { - var unique_id = this.$element.attr('name') + '_' + option_index; - var $item = $(this.settings.menuItemHTML) - .attr({ - 'for': unique_id, - 'role': 'menuitem' - }) - .text(' ' + $option.text()); - - var $input = $('<input>') - .attr({ - 'type': 'checkbox', - 'id': unique_id, - 'value': $option.val() - }) - .prependTo($item); - - if ( $option.is(':disabled') ) { - $input.attr('disabled', 'disabled'); - } - if ( $option.is(':selected') ) { - $input.prop('checked', 'checked'); - } - - $input.on('change.multiselect', function() { - if ($(this).prop('checked')) { - $option.prop('selected', true); - } else { - $option.prop('selected', false); - } - - // .prop() on its own doesn't generate a change event. - // Other plugins might want to do stuff onChange. - $option.trigger('change', [true]); - }); - - return $item; - }, - - setUpBodyClickListener: function() { - var _this = this; - - // Hide the $menu when you click outside of it. - $('html').on('click.multiselect', function(){ - _this.menuHide(); - }); - - // Stop click events from inside the $button or $menu from - // bubbling up to the body and closing the menu! - this.$container.on('click.multiselect', function(e){ - e.stopPropagation(); - }); - }, - - setUpLabelsClickListener: function() { - var _this = this; - this.$labels.on('click.multiselect', function(e) { - e.preventDefault(); - e.stopPropagation(); - _this.menuToggle(); - }); - }, - - menuShow: function() { - this.$container.addClass(this.settings.activeClass); - if (this.settings.positionMenuWithin && this.settings.positionMenuWithin instanceof $) { - var menuLeftEdge = this.$menu.offset().left + this.$menu.outerWidth(); - var withinLeftEdge = this.settings.positionMenuWithin.offset().left + - this.settings.positionMenuWithin.outerWidth(); - - if( menuLeftEdge > withinLeftEdge ) { - this.$menu.css( 'width', (withinLeftEdge - this.$menu.offset().left) ); - this.$container.addClass(this.settings.positionedMenuClass); - } - } - }, - - menuHide: function() { - this.$container.removeClass(this.settings.activeClass); - this.$container.removeClass(this.settings.positionedMenuClass); - this.$menu.css('width', 'auto'); - }, - - menuToggle: function() { - if ( this.$container.hasClass(this.settings.activeClass) ) { - this.menuHide(); - } else { - this.menuShow(); - } - } - - }); - - $.fn[ pluginName ] = function(options) { - return this.each(function() { - if ( !$.data(this, "plugin_" + pluginName) ) { - $.data(this, "plugin_" + pluginName, - new Plugin(this, options) ); - } - }); - }; - -})(jQuery); diff --git a/web/js/map-OpenLayers.js b/web/js/map-OpenLayers.js index 8cc2e8e2c..31f5f49d8 100644 --- a/web/js/map-OpenLayers.js +++ b/web/js/map-OpenLayers.js @@ -1,5 +1,23 @@ var fixmystreet = fixmystreet || {}; +fixmystreet.utils = fixmystreet.utils || {}; + +$.extend(fixmystreet.utils, { + parse_query_string: function() { + var qs = {}; + if (!location.search) { + return qs; + } + location.search.substring(1).split(/[;&]/).forEach(function(i) { + var s = i.split('='), + k = s[0], + v = s[1] && decodeURIComponent(s[1].replace(/\+/g, ' ')); + qs[k] = v; + }); + return qs; + } +}); + (function() { fixmystreet.maps = fixmystreet.maps || {}; @@ -282,7 +300,7 @@ var fixmystreet = fixmystreet || {}; if (!location.search) { return qs; } - location.search.substring(1).split('&').forEach(function(i) { + location.search.substring(1).split(/[&;]/).forEach(function(i) { var s = i.split('='), k = s[0], v = s[1] && decodeURIComponent(s[1].replace(/\+/g, ' ')); @@ -301,15 +319,7 @@ var fixmystreet = fixmystreet || {}; return value; } - function categories_or_status_changed_history() { - if (!('pushState' in history)) { - return; - } - var qs = parse_query_string(); - var filter_categories = replace_query_parameter(qs, 'filter_categories', 'filter_category'); - var filter_statuses = replace_query_parameter(qs, 'statuses', 'status'); - var sort_key = replace_query_parameter(qs, 'sort', 'sort'); - delete qs.p; + function update_url(qs) { var new_url; if ($.isEmptyObject(qs)) { new_url = location.href.replace(location.search, ""); @@ -318,6 +328,37 @@ var fixmystreet = fixmystreet || {}; } else { new_url = location.href + '?' + $.param(qs); } + return new_url; + } + + function page_changed_history() { + if (!('pushState' in history)) { + return; + } + var qs = fixmystreet.utils.parse_query_string(); + + var page = $('.pagination').data('page'); + if (page > 1) { + qs.p = page; + } else { + delete qs.p; + } + var new_url = update_url(qs); + history.pushState({ + page_change: { 'page': page } + }, null, new_url); + } + + function categories_or_status_changed_history() { + if (!('pushState' in history)) { + return; + } + var qs = fixmystreet.utils.parse_query_string(); + var filter_categories = replace_query_parameter(qs, 'filter_categories', 'filter_category'); + var filter_statuses = replace_query_parameter(qs, 'statuses', 'status'); + var sort_key = replace_query_parameter(qs, 'sort', 'sort'); + delete qs.p; + var new_url = update_url(qs); history.pushState({ filter_change: { 'filter_categories': filter_categories, 'statuses': filter_statuses, 'sort': sort_key } }, null, new_url); @@ -387,7 +428,7 @@ var fixmystreet = fixmystreet || {}; f.geometry = new_geometry; this.removeAllFeatures(); this.addFeatures([f]); - var qs = parse_query_string(); + var qs = fixmystreet.utils.parse_query_string(); if (!qs.bbox) { zoomToBounds(extent); } @@ -482,19 +523,14 @@ var fixmystreet = fixmystreet || {}; if (fixmystreet.page == 'around') { fixmystreet.bbox_strategy = fixmystreet.bbox_strategy || new OpenLayers.Strategy.FixMyStreet(); pin_layer_options.strategies = [ fixmystreet.bbox_strategy ]; - pin_layer_options.protocol = new OpenLayers.Protocol.FixMyStreet({ - url: '/ajax', - params: fixmystreet.all_pins ? { all_pins: 1 } : { }, - format: new OpenLayers.Format.FixMyStreet() - }); } if (fixmystreet.page == 'reports') { - pin_layer_options.strategies = [ new OpenLayers.Strategy.FixMyStreetRefreshOnZoom() ]; + pin_layer_options.strategies = [ new OpenLayers.Strategy.FixMyStreetNoLoad() ]; } if (fixmystreet.page == 'my') { pin_layer_options.strategies = [ new OpenLayers.Strategy.FixMyStreetFixed() ]; } - if (fixmystreet.page == 'reports' || fixmystreet.page == 'my') { + if (fixmystreet.page == 'around' || fixmystreet.page == 'reports' || fixmystreet.page == 'my') { pin_layer_options.protocol = new OpenLayers.Protocol.FixMyStreet({ url: fixmystreet.original.href.split('?')[0] + '?ajax=1', format: new OpenLayers.Format.FixMyStreet() @@ -549,9 +585,22 @@ var fixmystreet = fixmystreet || {}; $("#filter_categories").on("change.filters", categories_or_status_changed); $("#statuses").on("change.filters", categories_or_status_changed); $("#sort").on("change.filters", categories_or_status_changed); + $('.js-pagination').on('change.filters', categories_or_status_changed); + $('.js-pagination').on('click', 'a', function(e) { + e.preventDefault(); + var page = $('.pagination').data('page'); + if ($(this).hasClass('next')) { + $('.pagination').data('page', page + 1); + } else { + $('.pagination').data('page', page - 1); + } + fixmystreet.markers.protocol.use_page = true; + $(this).trigger('change'); + }); $("#filter_categories").on("change.user", categories_or_status_changed_history); $("#statuses").on("change.user", categories_or_status_changed_history); $("#sort").on("change.user", categories_or_status_changed_history); + $('.js-pagination').on('click', 'a', page_changed_history); } else if (fixmystreet.page == 'new') { drag.activate(); } @@ -565,49 +614,21 @@ var fixmystreet = fixmystreet || {}; zoomToBounds( fixmystreet.markers.getDataExtent() ); } - $('#hide_pins_link').click(function(e) { + $('#hide_pins_link, .big-hide-pins-link').click(function(e) { e.preventDefault(); if (this.innerHTML == translation_strings.show_pins) { fixmystreet.markers.setVisibility(true); fixmystreet.select_feature.activate(); - this.innerHTML = translation_strings.hide_pins; + $('#hide_pins_link, .big-hide-pins-link').html(translation_strings.hide_pins); } else if (this.innerHTML == translation_strings.hide_pins) { fixmystreet.markers.setVisibility(false); fixmystreet.select_feature.deactivate(); - this.innerHTML = translation_strings.show_pins; + $('#hide_pins_link, .big-hide-pins-link').html(translation_strings.show_pins); } - }); - - $('#all_pins_link').click(function(e) { - e.preventDefault(); - fixmystreet.markers.setVisibility(true); - var texts = [ - 'en', 'Show old', 'Hide old', - 'nb', 'Vis gamle', 'Skjul gamle', - 'cy', 'Cynnwys hen adroddiadau', 'Cuddio hen adroddiadau' - ]; - for (var i=0; i<texts.length; i+=3) { - if (this.innerHTML == texts[i+1]) { - this.innerHTML = texts[i+2]; - fixmystreet.markers.protocol.options.params = { all_pins: 1 }; - fixmystreet.markers.refresh( { force: true } ); - lang = texts[i]; - } else if (this.innerHTML == texts[i+2]) { - this.innerHTML = texts[i+1]; - fixmystreet.markers.protocol.options.params = { }; - fixmystreet.markers.refresh( { force: true } ); - lang = texts[i]; - } - } - if (lang == 'cy') { - document.getElementById('hide_pins_link').innerHTML = 'Cuddio pinnau'; - } else if (lang == 'nb') { - document.getElementById('hide_pins_link').innerHTML = 'Skjul nåler'; - } else { - document.getElementById('hide_pins_link').innerHTML = 'Hide pins'; + if (typeof ga !== 'undefined') { + ga('send', 'event', 'toggle-pins-on-map', 'click'); } }); - } $(function(){ @@ -761,6 +782,8 @@ OpenLayers.Control.PermalinkFMSz = OpenLayers.Class(OpenLayers.Control.Permalink }); OpenLayers.Strategy.FixMyStreet = OpenLayers.Class(OpenLayers.Strategy.BBOX, { + // Update when the zoom changes, pagination means there might be new things + resFactor: 1.5, ratio: 1, // The transform in Strategy.BBOX's getMapBounds could mean you end up with // co-ordinates too precise, which could then cause the Strategy to think @@ -787,11 +810,8 @@ OpenLayers.Strategy.FixMyStreet = OpenLayers.Class(OpenLayers.Strategy.BBOX, { } }); -/* This strategy will call for updates whenever the zoom changes, - * unlike the parent which only will if new area is included. It - * also does not update on load, as we already have the data. */ -OpenLayers.Strategy.FixMyStreetRefreshOnZoom = OpenLayers.Class(OpenLayers.Strategy.FixMyStreet, { - resFactor: 1.5, +/* This strategy additionally does not update on load, as we already have the data. */ +OpenLayers.Strategy.FixMyStreetNoLoad = OpenLayers.Class(OpenLayers.Strategy.FixMyStreet, { activate: function() { var activated = OpenLayers.Strategy.prototype.activate.call(this); if (activated) { @@ -821,12 +841,15 @@ OpenLayers.Strategy.FixMyStreetFixed = OpenLayers.Class(OpenLayers.Strategy.Fixe }); /* Pan data request handler */ -// This class is used to get a JSON object from /ajax that contains +// This class is used to get a JSON object from /around?ajax that contains // pins for the map and HTML for the sidebar. It does a fetch whenever the map // is dragged (modulo a buffer extending outside the viewport). // This subclass is required so we can pass the 'filter_category' and 'status' query -// params to /ajax if the user has filtered the map. +// params to /around?ajax if the user has filtered the map. OpenLayers.Protocol.FixMyStreet = OpenLayers.Class(OpenLayers.Protocol.HTTP, { + initial_page: null, + use_page: false, + read: function(options) { // Show the loading indicator over the map $('#loading-indicator').removeClass('hidden'); @@ -839,6 +862,16 @@ OpenLayers.Protocol.FixMyStreet = OpenLayers.Class(OpenLayers.Protocol.HTTP, { options.params[key] = val; } }); + if (this.use_page) { + var page = $('.pagination').data('page'); + this.use_page = false; + } else if (this.initial_page) { + page = 1; + } else { + var qs = fixmystreet.utils.parse_query_string(); + this.initial_page = page = qs.p || 1; + } + options.params.p = page; return OpenLayers.Protocol.HTTP.prototype.read.apply(this, [options]); }, CLASS_NAME: "OpenLayers.Protocol.FixMyStreet" diff --git a/web/js/map-bing-ol.js b/web/js/map-bing-ol.js index 3ad92b27e..6662bf91a 100644 --- a/web/js/map-bing-ol.js +++ b/web/js/map-bing-ol.js @@ -95,10 +95,10 @@ OpenLayers.Layer.Bing = OpenLayers.Class(OpenLayers.Layer.XYZ, { get_urls: function(bounds, z) { return [ - "//ecn.t0.tiles.virtualearth.net/tiles/r${id}.png?g=3467", - "//ecn.t1.tiles.virtualearth.net/tiles/r${id}.png?g=3467", - "//ecn.t2.tiles.virtualearth.net/tiles/r${id}.png?g=3467", - "//ecn.t3.tiles.virtualearth.net/tiles/r${id}.png?g=3467" + "//ecn.t0.tiles.virtualearth.net/tiles/r${id}.png?g=5941", + "//ecn.t1.tiles.virtualearth.net/tiles/r${id}.png?g=5941", + "//ecn.t2.tiles.virtualearth.net/tiles/r${id}.png?g=5941", + "//ecn.t3.tiles.virtualearth.net/tiles/r${id}.png?g=5941" ]; }, diff --git a/web/js/map-fms.js b/web/js/map-fms.js index 61206a90a..014bd58bb 100644 --- a/web/js/map-fms.js +++ b/web/js/map-fms.js @@ -61,10 +61,10 @@ OpenLayers.Layer.BingUK = OpenLayers.Class(OpenLayers.Layer.Bing, { type = '&productSet=mmOS&key=' + fixmystreet.key; } urls = [ - "//ecn.t0.tiles.virtualearth.net/tiles/r${id}.png?g=3467" + type, - "//ecn.t1.tiles.virtualearth.net/tiles/r${id}.png?g=3467" + type, - "//ecn.t2.tiles.virtualearth.net/tiles/r${id}.png?g=3467" + type, - "//ecn.t3.tiles.virtualearth.net/tiles/r${id}.png?g=3467" + type + "//ecn.t0.tiles.virtualearth.net/tiles/r${id}.png?g=5941" + type, + "//ecn.t1.tiles.virtualearth.net/tiles/r${id}.png?g=5941" + type, + "//ecn.t2.tiles.virtualearth.net/tiles/r${id}.png?g=5941" + type, + "//ecn.t3.tiles.virtualearth.net/tiles/r${id}.png?g=5941" + type ]; } return urls; diff --git a/web/js/map-google.js b/web/js/map-google.js index 596e4f8ee..75a1b25a1 100644 --- a/web/js/map-google.js +++ b/web/js/map-google.js @@ -127,12 +127,10 @@ fixmystreet.maps = {}; b_ne = b.getNorthEast(), bbox = b_sw.lng() + ',' + b_sw.lat() + ',' + b_ne.lng() + ',' + b_ne.lat(), params = { + ajax: 1, bbox: bbox }; - if (fixmystreet.all_pins) { - params.all_pins = 1; - } - $.getJSON('/ajax', params, read_pin_json); + $.getJSON('/around', params, read_pin_json); } function map_initialize() { @@ -208,55 +206,24 @@ fixmystreet.maps = {}; } */ - $('#hide_pins_link').click(function(e) { + $('#hide_pins_link, .big-hide-pins-link').click(function(e) { var i, m; e.preventDefault(); if (this.innerHTML == translation_strings.show_pins) { for (m=0; m<fixmystreet.markers.length; m++) { fixmystreet.markers[m].setMap(fixmystreet.map); } - this.innerHTML = translation_strings.hide_pins; + $('#hide_pins_link, .big-hide-pins-link').html(translation_strings.hide_pins); } else if (this.innerHTML == translation_strings.hide_pins) { for (m=0; m<fixmystreet.markers.length; m++) { fixmystreet.markers[m].setMap(null); } - this.innerHTML = translation_strings.show_pins; - } - }); - - $('#all_pins_link').click(function(e) { - var i; - e.preventDefault(); - for (i=0; i<fixmystreet.markers.length; i++) { - fixmystreet.markers[i].setMap(fixmystreet.map); - } - var texts = [ - 'en', 'Show old', 'Hide old', - 'nb', 'Inkluder utdaterte problemer', 'Skjul utdaterte rapporter', - 'cy', 'Cynnwys hen adroddiadau', 'Cuddio hen adroddiadau' - ]; - for (i=0; i<texts.length; i+=3) { - if (this.innerHTML == texts[i+1]) { - this.innerHTML = texts[i+2]; - fixmystreet.markers.protocol.options.params = { all_pins: 1 }; - fixmystreet.markers.refresh( { force: true } ); - lang = texts[i]; - } else if (this.innerHTML == texts[i+2]) { - this.innerHTML = texts[i+1]; - fixmystreet.markers.protocol.options.params = { }; - fixmystreet.markers.refresh( { force: true } ); - lang = texts[i]; - } + $('#hide_pins_link, .big-hide-pins-link').html(translation_strings.show_pins); } - if (lang == 'cy') { - document.getElementById('hide_pins_link').innerHTML = 'Cuddio pinnau'; - } else if (lang == 'nb') { - document.getElementById('hide_pins_link').innerHTML = 'Gjem nåler'; - } else { - document.getElementById('hide_pins_link').innerHTML = 'Hide pins'; + if (typeof ga !== 'undefined') { + ga('send', 'event', 'toggle-pins-on-map', 'click'); } }); - } google.maps.visualRefresh = true; diff --git a/web/js/map-wmts-bristol.js b/web/js/map-wmts-bristol.js index 4a48da27f..35f5ed0d6 100644 --- a/web/js/map-wmts-bristol.js +++ b/web/js/map-wmts-bristol.js @@ -14,7 +14,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "0", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 181428.9342864172, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 432, @@ -24,7 +23,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "1", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 90714.4671432086, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 863, @@ -34,7 +32,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "2", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 45357.2335716043, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 1725, @@ -44,7 +41,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "3", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 22678.61678580215, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 3449, @@ -54,7 +50,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "4", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 11339.308392901075, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 6898, @@ -64,7 +59,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "5", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 5669.654196450538, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 13795, @@ -74,7 +68,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "6", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 2834.827098225269, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 27590, @@ -84,7 +77,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "7", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 1181.177957593862, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 66215, @@ -94,7 +86,6 @@ fixmystreet.maps.matrix_ids = [ "identifier": "8", "supportedCRS": "urn:ogc:def:crs:EPSG::27700", "scaleDenominator": 708.7067745563172, - "topLeftCorner": { "lat": 4470200, "lon": -5220400 }, "tileWidth": 256, "tileHeight": 256, "matrixWidth": 110359, diff --git a/web/js/map-wmts-zurich.js b/web/js/map-wmts-zurich.js index 6bc1c5e14..0a753e831 100644 --- a/web/js/map-wmts-zurich.js +++ b/web/js/map-wmts-zurich.js @@ -4,10 +4,10 @@ // From 'fullExtent' from http://www.gis.stadt-zuerich.ch/maps/rest/services/tiled95/LuftbildHybrid/MapServer?f=pjson fixmystreet.maps.layer_bounds = new OpenLayers.Bounds( - 2676000.9069999997, // W - 1241399.842, // S - 2689900.9069999997, // E - 1254599.842); // N + 2674687.5, // W + 1240500, // S + 2690000, // E + 1255500); // N fixmystreet.maps.matrix_ids = [ // The two highest zoom levels are pretty much useless so they're disabled. |