aboutsummaryrefslogtreecommitdiffstats
path: root/web/js
diff options
context:
space:
mode:
Diffstat (limited to 'web/js')
-rw-r--r--web/js/dashboard.js194
-rw-r--r--web/js/front.js18
-rw-r--r--web/js/geolocation.js43
-rw-r--r--web/js/jquery.fixedthead.js81
-rw-r--r--web/js/jquery.multi-select.js334
-rw-r--r--web/js/map-OpenLayers.js149
-rw-r--r--web/js/map-bing-ol.js8
-rw-r--r--web/js/map-fms.js8
-rw-r--r--web/js/map-google.js47
-rw-r--r--web/js/map-wmts-bristol.js9
-rw-r--r--web/js/map-wmts-zurich.js8
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.