Browse Source

Fixed front page on mobile and improved city lookup

development
Godwin 8 years ago
parent
commit
e83c2fc464
  1. 80
      Gemfile
  2. 32
      Rakefile
  3. 520
      app/assets/javascripts/main.js
  4. 21
      app/assets/stylesheets/_application.scss
  5. 2
      app/assets/stylesheets/bumbleberry-settings.json
  6. 71
      app/models/city.rb
  7. 2
      app/views/layouts/application.html.haml
  8. 23
      config/initializers/geocoder.rb

80
Gemfile

@ -11,9 +11,9 @@ gem 'haml'
gem 'nokogiri', '~> 1.6.8.rc2'
if Dir.exists?('../lingua_franca')
gem 'lingua_franca', path: '../lingua_franca'
gem 'lingua_franca', :path => '../lingua_franca'
else
gem 'lingua_franca', git: 'git://github.com/lingua-franca/lingua_franca.git'
gem 'lingua_franca', :git => 'git://github.com/lingua-franca/lingua_franca.git'
end
gem 'tzinfo-data'
@ -21,15 +21,15 @@ gem 'sass'
gem 'sass-rails'
if Dir.exists?('../bumbleberry')
gem 'bumbleberry', path: "../bumbleberry"
gem 'bumbleberry', :path => "../bumbleberry"
else
gem 'bumbleberry', git: 'git://github.com/bumbleberry/bumbleberry.git'
gem 'bumbleberry', :git => 'git://github.com/bumbleberry/bumbleberry.git'
end
if Dir.exists?('../paypal-express')
gem 'paypal-express', path: "../paypal-express"
gem 'paypal-express', :path => "../paypal-express"
else
gem 'paypal-express', git: 'git://github.com/bikebike/paypal-express.git'
gem 'paypal-express', :git => 'git://github.com/bikebike/paypal-express.git'
end
gem 'uglifier', '>= 1.3.0'
@ -48,55 +48,55 @@ gem 'redcarpet'
gem 'sidekiq'
gem 'letter_opener'
gem 'launchy'
gem 'to_spreadsheet', git: 'git://github.com/glebm/to_spreadsheet.git'
gem 'to_spreadsheet', :git => 'git://github.com/glebm/to_spreadsheet.git'
group :test do
gem 'rspec'
gem 'rspec-rails'
gem 'rspec'
gem 'rspec-rails'
end
group :development do
gem 'better_errors'
gem 'binding_of_caller'
gem 'meta_request'
gem 'capistrano', '~> 3.1'
gem 'capistrano-rails', '~> 1.1'
gem 'capistrano-faster-assets', '~> 1.0'
gem 'eventmachine'#, :github => 'krzcho/eventmachine', :branch => 'master'
gem 'thin'#, :github => 'krzcho/thin', :branch => 'master'
gem 'better_errors'
gem 'binding_of_caller'
gem 'meta_request'
gem 'capistrano', '~> 3.1'
gem 'capistrano-rails', '~> 1.1'
gem 'capistrano-faster-assets', '~> 1.0'
gem 'eventmachine', :github => 'krzcho/eventmachine', :branch => 'master'
gem 'thin', :github => 'krzcho/thin', :branch => 'master'
end
group :test do
gem 'gherkin3', '>= 3.1.0'
gem 'cucumber'
gem 'cucumber-core'
gem 'cucumber-rails'
gem 'poltergeist'
gem 'guard-rspec'
gem 'factory_girl_rails'
gem 'coveralls', require: false
gem 'selenium-webdriver'
gem 'simplecov', require: false
gem 'webmock', require: false
gem 'database_cleaner'
gem 'mocha'
gem 'gherkin3', '>= 3.1.0'
gem 'cucumber'
gem 'cucumber-core'
gem 'cucumber-rails'
gem 'poltergeist'
gem 'guard-rspec'
gem 'factory_girl_rails'
gem 'coveralls', require: false
gem 'selenium-webdriver'
gem 'simplecov', require: false
gem 'webmock', require: false
gem 'database_cleaner'
gem 'mocha'
end
group :staging, :production, :preview do
gem 'rails_12factor'
gem 'rails_12factor'
end
group :production, :preview do
gem 'unicorn'
gem 'daemon-spawn'
gem 'daemons'
gem 'unicorn'
gem 'daemon-spawn'
gem 'daemons'
end
platforms 'mswin', 'mingw' do
group :test do
gem 'wdm', '>= 0.1.0'
end
group :test do
gem 'wdm', '>= 0.1.0'
end
end

32
Rakefile

@ -24,15 +24,25 @@ end
task update_cities: :environment do
Location.all.each do |l|
city = City.search(([l.city, l.territory, l.country] - [nil, '']).join(', '))
l.city_id = city.id
l.save!
s = ([l.city, l.territory, l.country] - [nil, '']).join(', ')
unless l.city_id.present?
begin
puts "Searching for #{s}"
city = City.search(s)
l.city_id = city.id
l.save!
rescue
puts "Error searching for #{s}"
end
end
end
City.all.each do |c|
location = Geocoder.search(c.address, language: 'en').first
c.place_id = location.data['place_id']
c.save!
unless c.place_id.present?
City.all.each do |c|
location = Geocoder.search(c.address, language: 'en').first
c.place_id = location.data['place_id']
c.save!
end
end
end
@ -43,3 +53,11 @@ task update_cities_es: :environment do
c.save!
end
end
task update_cities_fr: :environment do
City.all.each do |c|
city = c.get_translation(:fr)
c.set_column_for_locale(:city, :fr, city, 0) unless city.blank? || city == c.get_column_for_locale(:city, :fr)
c.save!
end
end

520
app/assets/javascripts/main.js

@ -1,244 +1,290 @@
(function() {
window.onerror = function(message, url, lineNumber) {
//save error and send to server for example.
var request = new XMLHttpRequest();
request.open('POST', '/js_error', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send(
'message=' + encodeURI(message) +
'&url=' + encodeURI(url) +
'&lineNumber=' + encodeURI(lineNumber) +
'&location=' + encodeURI(window.location.href)
);
return false;
};
window.forEach = function(a, f) { Array.prototype.forEach.call(a, f) };
window.forEachElement = function(s, f, p) { forEach((p || document).querySelectorAll(s), f) };
var overlay = document.getElementById('content-overlay');
if (overlay) {
var body = document.querySelector('body');
var primaryContent = document.getElementById('primary-content');
primaryContent.addEventListener('keydown', function(event) {
if (body.classList.contains('has-overlay')) {
event.stopPropagation();
return false;
}
});
document.addEventListener('focus', function(event) {
if (overlay.querySelector('.dlg.open') && !overlay.querySelector('.dlg.open :focus')) {
overlay.querySelector('.dlg.open').focus();
}
}, true);
window.openOverlay = function(dlg, primaryContent, body) {
primaryContent.setAttribute('aria-hidden', 'true');
body.classList.add('has-overlay');
var type = dlg.getAttribute('data-type');
if (type) {
body.classList.add('is-' + type + '-dlg');
}
dlg.removeAttribute('aria-hidden');
dlg.setAttribute('role', 'alertdialog');
dlg.setAttribute('tabindex', '0');
dlg.focus();
setTimeout(function() { dlg.classList.add('open'); }, 100);
}
window.closeOverlay = function(dlg, primaryContent, body) {
setTimeout(function() {
body.classList.remove('has-overlay');
body.removeAttribute('style');
}, 250);
var type = dlg.getAttribute('data-type');
if (type) {
body.classList.remove('is-' + type + '-dlg');
}
primaryContent.removeAttribute('aria-hidden');
dlg.setAttribute('aria-hidden', 'true');
dlg.removeAttribute('tabindex');
dlg.classList.remove('open');
dlg.removeAttribute('role');
}
window.onerror = function(message, url, lineNumber) {
//save error and send to server for example.
var request = new XMLHttpRequest();
request.open('POST', '/js_error', true);
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
request.send(
'message=' + encodeURI(message) +
'&url=' + encodeURI(url) +
'&lineNumber=' + encodeURI(lineNumber) +
'&location=' + encodeURI(window.location.href)
);
return false;
};
window.forEach = function(a, f) { Array.prototype.forEach.call(a, f) };
window.forEachElement = function(s, f, p) { forEach((p || document).querySelectorAll(s), f) };
var overlay = document.getElementById('content-overlay');
if (overlay) {
var body = document.querySelector('body');
var primaryContent = document.getElementById('primary-content');
primaryContent.addEventListener('keydown', function(event) {
if (body.classList.contains('has-overlay')) {
event.stopPropagation();
return false;
}
});
document.addEventListener('focus', function(event) {
if (overlay.querySelector('.dlg.open') && !overlay.querySelector('.dlg.open :focus')) {
overlay.querySelector('.dlg.open').focus();
}
}, true);
window.openOverlay = function(dlg, primaryContent, body) {
primaryContent.setAttribute('aria-hidden', 'true');
body.classList.add('has-overlay');
var type = dlg.getAttribute('data-type');
if (type) {
body.classList.add('is-' + type + '-dlg');
}
dlg.removeAttribute('aria-hidden');
dlg.setAttribute('role', 'alertdialog');
dlg.setAttribute('tabindex', '0');
dlg.focus();
setTimeout(function() { dlg.classList.add('open'); }, 100);
}
window.closeOverlay = function(dlg, primaryContent, body) {
setTimeout(function() {
body.classList.remove('has-overlay');
body.removeAttribute('style');
}, 250);
var type = dlg.getAttribute('data-type');
if (type) {
body.classList.remove('is-' + type + '-dlg');
}
primaryContent.removeAttribute('aria-hidden');
dlg.setAttribute('aria-hidden', 'true');
dlg.removeAttribute('tabindex');
dlg.classList.remove('open');
dlg.removeAttribute('role');
}
function openDlg(dlg, link) {
document.getElementById('overlay').onclick =
dlg.querySelector('.close').onclick = function() { closeDlg(dlg); };
body.setAttribute('style', 'width: ' + body.clientWidth + 'px');
var msg = link.querySelector('.message');
if (msg) {
dlg.querySelector('.message').innerHTML = msg.innerHTML
}
if (link.dataset.infoTitle) {
dlg.querySelector('.title').innerHTML = decodeURI(link.dataset.infoTitle);
}
confirmBtn = dlg.querySelector('.confirm');
if (confirmBtn) {
confirmBtn.addEventListener('click', function(event) {
event.preventDefault();
if (link.tagName == 'BUTTON') {
var form = link.parentElement
while (form && form.tagName != 'FORM') {
var form = form.parentElement
}
if (form) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = 'button';
input.value = link.value;
form.appendChild(input);
form.submit();
}
} else {
window.location.href = link.getAttribute('href');
}
});
}
window.openOverlay(dlg, primaryContent, body);
}
function closeDlg(dlg) {
window.closeOverlay(dlg, primaryContent, body);
}
function openDlg(dlg, link) {
document.getElementById('overlay').onclick =
dlg.querySelector('.close').onclick = function() { closeDlg(dlg); };
body.setAttribute('style', 'width: ' + body.clientWidth + 'px');
var msg = link.querySelector('.message');
if (msg) {
dlg.querySelector('.message').innerHTML = msg.innerHTML
}
if (link.dataset.infoTitle) {
dlg.querySelector('.title').innerHTML = decodeURI(link.dataset.infoTitle);
}
confirmBtn = dlg.querySelector('.confirm');
if (confirmBtn) {
confirmBtn.addEventListener('click', function(event) {
event.preventDefault();
if (link.tagName == 'BUTTON') {
var form = link.parentElement
while (form && form.tagName != 'FORM') {
var form = form.parentElement
}
if (form) {
var input = document.createElement('input');
input.type = 'hidden';
input.name = 'button';
input.value = link.value;
form.appendChild(input);
form.submit();
}
} else {
window.location.href = link.getAttribute('href');
}
});
}
window.openOverlay(dlg, primaryContent, body);
}
function closeDlg(dlg) {
window.closeOverlay(dlg, primaryContent, body);
}
var confirmationDlg = document.getElementById('confirmation-dlg');
forEachElement('[data-confirmation]', function(link) {
link.addEventListener('click', function(event) {
event.preventDefault();
openDlg(confirmationDlg, link);
return false;
});
});
var infoDlg = document.getElementById('info-dlg');
forEachElement('[data-info-text]', function(link) {
link.addEventListener('click', function(event) {
event.preventDefault();
openDlg(infoDlg, link);
return false;
});
});
var loginDlg = document.getElementById('login-dlg');
forEachElement('[data-sign-in]', function(link) {
link.addEventListener('click', function(event) {
event.preventDefault();
openDlg(loginDlg, link);
return false;
});
});
var contactDlg = document.getElementById('contact-dlg');
var contactLink = document.getElementById('contact-link');
contactLink.addEventListener('click', function(event) {
event.preventDefault();
openDlg(contactDlg, contactLink);
return false;
});
}
var htmlNode = document.documentElement;
document.addEventListener('keydown', function(event) {
if (htmlNode.dataset.input != 'kb' &&
((["input", "textarea", "select", "option"].indexOf(event.target.nodeName.toLowerCase()) < 0 &&
!event.target.attributes.contenteditable) || event.key == "Tab")) {
htmlNode.setAttribute('data-input', 'kb');
}
});
document.addEventListener('mousemove', function(event) {
if (htmlNode.dataset.input != 'mouse' && (event.movementX || event.movementY)) {
htmlNode.setAttribute('data-input', 'mouse');
}
});
var confirmationDlg = document.getElementById('confirmation-dlg');
forEachElement('[data-confirmation]', function(link) {
link.addEventListener('click', function(event) {
event.preventDefault();
openDlg(confirmationDlg, link);
return false;
});
});
var infoDlg = document.getElementById('info-dlg');
forEachElement('[data-info-text]', function(link) {
link.addEventListener('click', function(event) {
event.preventDefault();
openDlg(infoDlg, link);
return false;
});
});
var loginDlg = document.getElementById('login-dlg');
forEachElement('[data-sign-in]', function(link) {
link.addEventListener('click', function(event) {
event.preventDefault();
openDlg(loginDlg, link);
return false;
});
});
var contactDlg = document.getElementById('contact-dlg');
var contactLink = document.getElementById('contact-link');
contactLink.addEventListener('click', function(event) {
event.preventDefault();
openDlg(contactDlg, contactLink);
return false;
});
}
var htmlNode = document.documentElement;
document.addEventListener('keydown', function(event) {
if (htmlNode.dataset.input != 'kb' &&
((["input", "textarea", "select", "option"].indexOf(event.target.nodeName.toLowerCase()) < 0 &&
!event.target.attributes.contenteditable) || event.key == "Tab")) {
htmlNode.setAttribute('data-input', 'kb');
}
});
document.addEventListener('mousemove', function(event) {
if (htmlNode.dataset.input != 'mouse' && (event.movementX || event.movementY)) {
htmlNode.setAttribute('data-input', 'mouse');
}
});
var errorField = document.querySelector('.input-field.has-error input, .input-field.has-error textarea');
if (errorField) {
errorField.focus();
}
window.initNodeFunctions = [ function(node) {
forEachElement('.number-field,.email-field,.text-field,.password-field,.search-field', function(field) {
var input = field.querySelector('input');
var positionLabel = function(input) {
field.classList[input.value ? 'remove' : 'add']('empty');
}
positionLabel(input);
input.addEventListener('keyup', function(event) {
positionLabel(event.target);
});
input.addEventListener('blur', function(event) {
positionLabel(event.target);
field.classList.remove('focused');
});
input.addEventListener('focus', function(event) {
field.classList.add('focused');
});
}, node || document);
forEachElement('form.js-xhr', function(form) {
if (form.addEventListener) {
form.addEventListener('submit', function(event) {
event.preventDefault();
form.classList.add('requesting');
var data = new FormData(form);
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4) {
form.classList.remove('requesting');
if (request.status == 200) {
var response = JSON.parse(request.responseText);
for (var i = 0; i < response.length; i++) {
var element;
if (response[i].selector) {
element = form.querySelector(response[i].selector);
}
if (response[i].globalSelector) {
element = document.querySelector(response[i].globalSelector);
}
var errorField = document.querySelector('.input-field.has-error input, .input-field.has-error textarea');
if (errorField) {
errorField.focus();
}
window.initNodeFunctions = [ function(node) {
forEachElement('.number-field,.email-field,.text-field,.password-field,.search-field', function(field) {
var input = field.querySelector('input');
var positionLabel = function(input) {
field.classList[input.value ? 'remove' : 'add']('empty');
}
positionLabel(input);
input.addEventListener('keyup', function(event) {
positionLabel(event.target);
});
input.addEventListener('blur', function(event) {
positionLabel(event.target);
field.classList.remove('focused');
});
input.addEventListener('focus', function(event) {
field.classList.add('focused');
});
}, node || document);
forEachElement('form.js-xhr', function(form) {
if (form.addEventListener) {
form.addEventListener('submit', function(event) {
event.preventDefault();
form.classList.add('requesting');
var data = new FormData(form);
var request = new XMLHttpRequest();
request.onreadystatechange = function() {
if (request.readyState == 4) {
form.classList.remove('requesting');
if (request.status == 200) {
var response = JSON.parse(request.responseText);
for (var i = 0; i < response.length; i++) {
var element;
if (response[i].selector) {
element = form.querySelector(response[i].selector);
}
if (response[i].globalSelector) {
element = document.querySelector(response[i].globalSelector);
}
if (response[i].html) {
element.innerHTML = response[i].html;
window.initNode(element);
}
if (response[i].className) {
element.className = response[i].className;
}
}
}
}
}
request.open('POST', form.getAttribute('action'), true);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.send(data);
}, false);
}
}, node || document);
forEachElement('[data-opens]', function(control) {
control.addEventListener('click', function(event) {
var opens = document.querySelector(control.getAttribute('data-opens'));
if (!opens.classList.contains('open')){
event.preventDefault();
opens.className += ' open';
if (control.getAttribute('data-focus')) {
var input = opens.querySelector(control.getAttribute('data-focus'));
if (input) {
input.focus();
}
}
return false;
}
});
});
} ];
window.initNode = function(node) {
forEach(initNodeFunctions, function(fn) {
fn(node);
});
};
initNode();
document.addEventListener('DOMContentLoaded', function() {
var errors = document.getElementsByClassName('has-error');
if (errors.length <= 0) {
errors = document.getElementsByClassName('info-message');
}
if (errors.length > 0) {
errors[0].scrollIntoView();
}
});
if (response[i].html) {
element.innerHTML = response[i].html;
window.initNode(element);
}
if (response[i].className) {
element.className = response[i].className;
}
}
}
}
}
request.open('POST', form.getAttribute('action'), true);
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
request.send(data);
}, false);
}
}, node || document);
forEachElement('[data-opens]', function(control) {
control.addEventListener('click', function(event) {
var opens = document.querySelector(control.getAttribute('data-opens'));
if (!opens.classList.contains('open')){
event.preventDefault();
opens.className += ' open';
if (control.getAttribute('data-focus')) {
var input = opens.querySelector(control.getAttribute('data-focus'));
if (input) {
input.focus();
}
}
return false;
}
});
});
} ];
window.initNode = function(node) {
forEach(initNodeFunctions, function(fn) {
fn(node);
});
};
initNode();
document.addEventListener('DOMContentLoaded', function() {
var errors = document.getElementsByClassName('has-error');
if (errors.length <= 0) {
errors = document.getElementsByClassName('info-message');
}
if (errors.length > 0) {
errors[0].scrollIntoView();
}
});
})();
function generateScreenshot() {
var css = '';
var svgs = document.getElementsByTagName('svg');
for (var i = 0; i < document.styleSheets.length; i++) {
if (document.styleSheets[i].href && !document.styleSheets[i].href.match(/web\-fonts/)) {
var rules = document.styleSheets[i].rules || document.styleSheets[i].cssRules;
for (var j = 0; j < rules.length; j++) {
cssText = rules[j].cssText;
if (rules[j].selectorText) {
if (rules[j].selectorText.match(/(^|\s)svg[^\w]/) || cssText.match(/\s(fill|stroke(\-width)?):/)) {
css += cssText;
}
}
}
}
}
for (var i = 0; i < svgs.length; i++) {
var svg = svgs[i];
// svg.innerHTML = '<style type="text/css"><![CDATA[' + css + ']]></style>' + svg.innerHTML;
svg.innerHTML = '<style type="text/css"><![CDATA[' + css + ']]></style>' + svg.innerHTML;
svg.setAttribute('height', svg.clientHeight);
svg.setAttribute('width', svg.clientWidth);
var canvas = document.createElement('canvas');
canvg(canvas, svg.outerHTML);
console.log(svg.outerHTML);
svg.style.backgroundImage = 'url(' + encodeURI(canvas.toDataURL('image/png')) + ')';
}
html2canvas(document.body, {
logging: true,
profile: true,
useCORS: true}).then(function(canvas) {
var data = canvas.toDataURL('image/jpeg', 0.9);
var src = encodeURI(data);
window.open(src, '_blank');
// reset the svg height and width
for (var i = 0; i < svgs.length; i++) {
var svg = svgs[i];
svg.removeAttribute('height');
svg.removeAttribute('width');
svg.removeAttribute('style');
}
});
}

21
app/assets/stylesheets/_application.scss

@ -12,6 +12,7 @@ html, body {
}
body {
background-color: $white;
padding-bottom: 20vw;
}
@ -1807,6 +1808,7 @@ ul.warnings {
a {
color: inherit;
padding: 0 0.333em;
display: inline-block;
&:hover {
@include after {
@ -2946,6 +2948,9 @@ a.logo {
.conference-banner {
text-align: center;
padding: 0;
margin: 0 -1em 2em;
width: auto;
.title {
font-size: 5vw;
@ -2964,6 +2969,10 @@ a.logo {
font-size: 0.85em;
line-height: 2em;
}
img {
max-width: 100%;
}
}
.conference-details {
@ -4653,15 +4662,6 @@ html[data-ontop] {
}
}
}
// .nav a.register, .nav button {
// @include before-and-after {
// background-color: $colour-2;
// }
// &:focus, &:active {
// @include _(transform, none);
// }
// }
}
#banner {
@ -4674,6 +4674,9 @@ html[data-ontop] {
}
.conference-banner {
margin: 0 auto;
width: 100%;
.title {
font-size: 1.9em;
margin: 0 0 1em;

2
app/assets/stylesheets/bumbleberry-settings.json

@ -8,7 +8,7 @@
"and_chr": ["54"],
"chrome": ["54"],
"edge": ["13"],
"firefox": ["44"],
"firefox": ["48"],
"ie": ["11"],
"ios_saf": ["8", "9"]
}

71
app/models/city.rb

@ -18,19 +18,30 @@ class City < ActiveRecord::Base
def get_translation(locale)
location = Geocoder.search(address, language: locale.to_s).first
# if the service lets us down, return nil
return nil unless location.present?
searched_component = false
location.data['address_components'].each do | component |
# city is usually labelled a 'locality' but sometimes this is missing and only 'colloquial_area' is present
if component['types'].first == 'locality' || component['types'].first == 'colloquial_area'
# city is usually labeled a 'locality' but sometimes this is missing and only 'colloquial_area' is present
if component['types'].first == 'locality'
return component['short_name']
end
if component['types'] == location.data['types']
searched_component = component['short_name']
end
end
return nil
# return the type we searched for but it's still possible that it will be false
searched_component
end
# this method will get called automatically if a translation is asked for but not found
def translate_city(locale)
translation = get_translation(locale)
# if we found it, set it
if translation.present?
set_column_for_locale(:city, locale, translation)
save!
@ -48,16 +59,20 @@ class City < ActiveRecord::Base
# look up the city in the geocoder
location = Geocoder.search(str, language: 'en').first
# return nil to indicate that the service is down
return nil unless location.present?
# see if the city is already present in our database
city = City.find_by_place_id(location.data['place_id'])
# return the city if we found it in the db already
return city if city.present?
if city.present?
CityCache.create(city_id: city.id, search: str)
return city
end
# otherwise build a new city
component_alises = {
'locality' => :city,
'colloquial_area' => :city,
'administrative_area_level_1' => :territory,
'country' => :country
}
@ -67,15 +82,61 @@ class City < ActiveRecord::Base
longitude: location.data['geometry']['location']['lng'],
place_id: location.data['place_id']
}
# these things are definitely not cities, make sure we don't think they're one
not_a_city = [
'administrative_area_level_1',
'country',
'street_address',
'street_number',
'postal_code',
'postal_code_prefix',
'route',
'intersection',
'premise',
'subpremise',
'natural_feature',
'airport',
'park',
'point_of_interest',
'bus_station',
'train_station',
'transit_station',
'room',
'post_box',
'parking',
'establishment',
'floor'
]
searched_component = nil
location.data['address_components'].each do | component |
property = component_alises[component['types'].first]
city_data[property] = component['short_name'] if property.present?
# ideally we will find the component that is labeled a locality but
# if that fails we will select what was searched for, hopefully they searched for a city
# and not an address or country
# some places are not labeled 'locality', search for 'Halifax NS' for example and you will
# get 'administrative_area_level_2' since Halifax is a municipality
if component['types'] == location.data['types'] && not_a_city.include?(component['types'].first)
searched_component = component['short_name']
end
end
# fall back to the searched component
city_data[:city] ||= searched_component
# we need to have the city and country at least
return false unless city_data[:city].present? && city_data[:country].present?
# save the new city
city = City.new(city_data)
city.save!
# save this to our cache
CityCache.create(city_id: city.id, search: str)
# and return it
return city
end

2
app/views/layouts/application.html.haml

@ -20,6 +20,8 @@
%meta{property: 'og:image', content: og_image}
%meta{name: "theme-color", content: @theme_colour}
= yield :head
= javascript_include_tag 'https://rawgit.com/niklasvh/html2canvas/master/dist/html2canvas.js'
= javascript_include_tag 'https://cdnjs.cloudflare.com/ajax/libs/amcharts/3.13.0/exporting/canvg.js'
%body{ class: page_style }
#primary-content

23
config/initializers/geocoder.rb

@ -1,21 +1,24 @@
# config/initializers/geocoder.rb
Geocoder.configure(
config = {
# geocoding service (see below for supported options):
:lookup => :google,
lookup: :google,
# IP address geocoding service (see below for supported options):
:ip_lookup => :freegeoip,
ip_lookup: :freegeoip,
# to use an API key:
# :api_key => "AIzaSyDitM1lyVWkrumteDvSkje6GiIKYyHlAXM",
# geocoding service request timeout, in seconds (default 3):
:timeout => 5,
timeout: 5,
# set default units to kilometers:
:units => :km,
units: :km
}
# caching (see below for details):
#:cache => Redis.new,
#:cache_prefix => "..."
)
# use our api key on the server
if Rails.env.preview? || Rails.env.production?
config[:api_key] = "AIzaSyDurfjX9f_NgYsJLyUuGqwdKuI745CE_OE"
config[:use_https] = true
end
Geocoder.configure(config)

Loading…
Cancel
Save