Fixed front page on mobile and improved city lookup
This commit is contained in:
parent
868f21a5f7
commit
e83c2fc464
76
Gemfile
76
Gemfile
@ -11,9 +11,9 @@ gem 'haml'
|
|||||||
gem 'nokogiri', '~> 1.6.8.rc2'
|
gem 'nokogiri', '~> 1.6.8.rc2'
|
||||||
|
|
||||||
if Dir.exists?('../lingua_franca')
|
if Dir.exists?('../lingua_franca')
|
||||||
gem 'lingua_franca', path: '../lingua_franca'
|
gem 'lingua_franca', :path => '../lingua_franca'
|
||||||
else
|
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
|
end
|
||||||
|
|
||||||
gem 'tzinfo-data'
|
gem 'tzinfo-data'
|
||||||
@ -21,15 +21,15 @@ gem 'sass'
|
|||||||
gem 'sass-rails'
|
gem 'sass-rails'
|
||||||
|
|
||||||
if Dir.exists?('../bumbleberry')
|
if Dir.exists?('../bumbleberry')
|
||||||
gem 'bumbleberry', path: "../bumbleberry"
|
gem 'bumbleberry', :path => "../bumbleberry"
|
||||||
else
|
else
|
||||||
gem 'bumbleberry', git: 'git://github.com/bumbleberry/bumbleberry.git'
|
gem 'bumbleberry', :git => 'git://github.com/bumbleberry/bumbleberry.git'
|
||||||
end
|
end
|
||||||
|
|
||||||
if Dir.exists?('../paypal-express')
|
if Dir.exists?('../paypal-express')
|
||||||
gem 'paypal-express', path: "../paypal-express"
|
gem 'paypal-express', :path => "../paypal-express"
|
||||||
else
|
else
|
||||||
gem 'paypal-express', git: 'git://github.com/bikebike/paypal-express.git'
|
gem 'paypal-express', :git => 'git://github.com/bikebike/paypal-express.git'
|
||||||
end
|
end
|
||||||
|
|
||||||
gem 'uglifier', '>= 1.3.0'
|
gem 'uglifier', '>= 1.3.0'
|
||||||
@ -48,55 +48,55 @@ gem 'redcarpet'
|
|||||||
gem 'sidekiq'
|
gem 'sidekiq'
|
||||||
gem 'letter_opener'
|
gem 'letter_opener'
|
||||||
gem 'launchy'
|
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
|
group :test do
|
||||||
gem 'rspec'
|
gem 'rspec'
|
||||||
gem 'rspec-rails'
|
gem 'rspec-rails'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :development do
|
group :development do
|
||||||
gem 'better_errors'
|
gem 'better_errors'
|
||||||
gem 'binding_of_caller'
|
gem 'binding_of_caller'
|
||||||
gem 'meta_request'
|
gem 'meta_request'
|
||||||
|
|
||||||
gem 'capistrano', '~> 3.1'
|
gem 'capistrano', '~> 3.1'
|
||||||
gem 'capistrano-rails', '~> 1.1'
|
gem 'capistrano-rails', '~> 1.1'
|
||||||
gem 'capistrano-faster-assets', '~> 1.0'
|
gem 'capistrano-faster-assets', '~> 1.0'
|
||||||
|
|
||||||
gem 'eventmachine'#, :github => 'krzcho/eventmachine', :branch => 'master'
|
gem 'eventmachine', :github => 'krzcho/eventmachine', :branch => 'master'
|
||||||
gem 'thin'#, :github => 'krzcho/thin', :branch => 'master'
|
gem 'thin', :github => 'krzcho/thin', :branch => 'master'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :test do
|
group :test do
|
||||||
gem 'gherkin3', '>= 3.1.0'
|
gem 'gherkin3', '>= 3.1.0'
|
||||||
gem 'cucumber'
|
gem 'cucumber'
|
||||||
gem 'cucumber-core'
|
gem 'cucumber-core'
|
||||||
gem 'cucumber-rails'
|
gem 'cucumber-rails'
|
||||||
|
|
||||||
gem 'poltergeist'
|
gem 'poltergeist'
|
||||||
gem 'guard-rspec'
|
gem 'guard-rspec'
|
||||||
gem 'factory_girl_rails'
|
gem 'factory_girl_rails'
|
||||||
gem 'coveralls', require: false
|
gem 'coveralls', require: false
|
||||||
gem 'selenium-webdriver'
|
gem 'selenium-webdriver'
|
||||||
gem 'simplecov', require: false
|
gem 'simplecov', require: false
|
||||||
gem 'webmock', require: false
|
gem 'webmock', require: false
|
||||||
gem 'database_cleaner'
|
gem 'database_cleaner'
|
||||||
gem 'mocha'
|
gem 'mocha'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :staging, :production, :preview do
|
group :staging, :production, :preview do
|
||||||
gem 'rails_12factor'
|
gem 'rails_12factor'
|
||||||
end
|
end
|
||||||
|
|
||||||
group :production, :preview do
|
group :production, :preview do
|
||||||
gem 'unicorn'
|
gem 'unicorn'
|
||||||
gem 'daemon-spawn'
|
gem 'daemon-spawn'
|
||||||
gem 'daemons'
|
gem 'daemons'
|
||||||
end
|
end
|
||||||
|
|
||||||
platforms 'mswin', 'mingw' do
|
platforms 'mswin', 'mingw' do
|
||||||
group :test do
|
group :test do
|
||||||
gem 'wdm', '>= 0.1.0'
|
gem 'wdm', '>= 0.1.0'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
32
Rakefile
32
Rakefile
@ -24,15 +24,25 @@ end
|
|||||||
|
|
||||||
task update_cities: :environment do
|
task update_cities: :environment do
|
||||||
Location.all.each do |l|
|
Location.all.each do |l|
|
||||||
city = City.search(([l.city, l.territory, l.country] - [nil, '']).join(', '))
|
s = ([l.city, l.territory, l.country] - [nil, '']).join(', ')
|
||||||
l.city_id = city.id
|
unless l.city_id.present?
|
||||||
l.save!
|
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
|
end
|
||||||
|
|
||||||
City.all.each do |c|
|
unless c.place_id.present?
|
||||||
location = Geocoder.search(c.address, language: 'en').first
|
City.all.each do |c|
|
||||||
c.place_id = location.data['place_id']
|
location = Geocoder.search(c.address, language: 'en').first
|
||||||
c.save!
|
c.place_id = location.data['place_id']
|
||||||
|
c.save!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -43,3 +53,11 @@ task update_cities_es: :environment do
|
|||||||
c.save!
|
c.save!
|
||||||
end
|
end
|
||||||
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
|
||||||
|
@ -1,244 +1,290 @@
|
|||||||
(function() {
|
(function() {
|
||||||
window.onerror = function(message, url, lineNumber) {
|
window.onerror = function(message, url, lineNumber) {
|
||||||
//save error and send to server for example.
|
//save error and send to server for example.
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
request.open('POST', '/js_error', true);
|
request.open('POST', '/js_error', true);
|
||||||
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
|
request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8');
|
||||||
request.send(
|
request.send(
|
||||||
'message=' + encodeURI(message) +
|
'message=' + encodeURI(message) +
|
||||||
'&url=' + encodeURI(url) +
|
'&url=' + encodeURI(url) +
|
||||||
'&lineNumber=' + encodeURI(lineNumber) +
|
'&lineNumber=' + encodeURI(lineNumber) +
|
||||||
'&location=' + encodeURI(window.location.href)
|
'&location=' + encodeURI(window.location.href)
|
||||||
);
|
);
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
window.forEach = function(a, f) { Array.prototype.forEach.call(a, f) };
|
window.forEach = function(a, f) { Array.prototype.forEach.call(a, f) };
|
||||||
window.forEachElement = function(s, f, p) { forEach((p || document).querySelectorAll(s), f) };
|
window.forEachElement = function(s, f, p) { forEach((p || document).querySelectorAll(s), f) };
|
||||||
|
|
||||||
var overlay = document.getElementById('content-overlay');
|
var overlay = document.getElementById('content-overlay');
|
||||||
if (overlay) {
|
if (overlay) {
|
||||||
var body = document.querySelector('body');
|
var body = document.querySelector('body');
|
||||||
var primaryContent = document.getElementById('primary-content');
|
var primaryContent = document.getElementById('primary-content');
|
||||||
primaryContent.addEventListener('keydown', function(event) {
|
primaryContent.addEventListener('keydown', function(event) {
|
||||||
if (body.classList.contains('has-overlay')) {
|
if (body.classList.contains('has-overlay')) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
document.addEventListener('focus', function(event) {
|
document.addEventListener('focus', function(event) {
|
||||||
if (overlay.querySelector('.dlg.open') && !overlay.querySelector('.dlg.open :focus')) {
|
if (overlay.querySelector('.dlg.open') && !overlay.querySelector('.dlg.open :focus')) {
|
||||||
overlay.querySelector('.dlg.open').focus();
|
overlay.querySelector('.dlg.open').focus();
|
||||||
}
|
}
|
||||||
}, true);
|
}, true);
|
||||||
window.openOverlay = function(dlg, primaryContent, body) {
|
window.openOverlay = function(dlg, primaryContent, body) {
|
||||||
primaryContent.setAttribute('aria-hidden', 'true');
|
primaryContent.setAttribute('aria-hidden', 'true');
|
||||||
body.classList.add('has-overlay');
|
body.classList.add('has-overlay');
|
||||||
var type = dlg.getAttribute('data-type');
|
var type = dlg.getAttribute('data-type');
|
||||||
if (type) {
|
if (type) {
|
||||||
body.classList.add('is-' + type + '-dlg');
|
body.classList.add('is-' + type + '-dlg');
|
||||||
}
|
}
|
||||||
dlg.removeAttribute('aria-hidden');
|
dlg.removeAttribute('aria-hidden');
|
||||||
dlg.setAttribute('role', 'alertdialog');
|
dlg.setAttribute('role', 'alertdialog');
|
||||||
dlg.setAttribute('tabindex', '0');
|
dlg.setAttribute('tabindex', '0');
|
||||||
dlg.focus();
|
dlg.focus();
|
||||||
setTimeout(function() { dlg.classList.add('open'); }, 100);
|
setTimeout(function() { dlg.classList.add('open'); }, 100);
|
||||||
}
|
}
|
||||||
window.closeOverlay = function(dlg, primaryContent, body) {
|
window.closeOverlay = function(dlg, primaryContent, body) {
|
||||||
setTimeout(function() {
|
setTimeout(function() {
|
||||||
body.classList.remove('has-overlay');
|
body.classList.remove('has-overlay');
|
||||||
body.removeAttribute('style');
|
body.removeAttribute('style');
|
||||||
}, 250);
|
}, 250);
|
||||||
var type = dlg.getAttribute('data-type');
|
var type = dlg.getAttribute('data-type');
|
||||||
if (type) {
|
if (type) {
|
||||||
body.classList.remove('is-' + type + '-dlg');
|
body.classList.remove('is-' + type + '-dlg');
|
||||||
}
|
}
|
||||||
primaryContent.removeAttribute('aria-hidden');
|
primaryContent.removeAttribute('aria-hidden');
|
||||||
dlg.setAttribute('aria-hidden', 'true');
|
dlg.setAttribute('aria-hidden', 'true');
|
||||||
dlg.removeAttribute('tabindex');
|
dlg.removeAttribute('tabindex');
|
||||||
dlg.classList.remove('open');
|
dlg.classList.remove('open');
|
||||||
dlg.removeAttribute('role');
|
dlg.removeAttribute('role');
|
||||||
}
|
}
|
||||||
|
|
||||||
function openDlg(dlg, link) {
|
function openDlg(dlg, link) {
|
||||||
document.getElementById('overlay').onclick =
|
document.getElementById('overlay').onclick =
|
||||||
dlg.querySelector('.close').onclick = function() { closeDlg(dlg); };
|
dlg.querySelector('.close').onclick = function() { closeDlg(dlg); };
|
||||||
body.setAttribute('style', 'width: ' + body.clientWidth + 'px');
|
body.setAttribute('style', 'width: ' + body.clientWidth + 'px');
|
||||||
var msg = link.querySelector('.message');
|
var msg = link.querySelector('.message');
|
||||||
if (msg) {
|
if (msg) {
|
||||||
dlg.querySelector('.message').innerHTML = msg.innerHTML
|
dlg.querySelector('.message').innerHTML = msg.innerHTML
|
||||||
}
|
}
|
||||||
if (link.dataset.infoTitle) {
|
if (link.dataset.infoTitle) {
|
||||||
dlg.querySelector('.title').innerHTML = decodeURI(link.dataset.infoTitle);
|
dlg.querySelector('.title').innerHTML = decodeURI(link.dataset.infoTitle);
|
||||||
}
|
}
|
||||||
confirmBtn = dlg.querySelector('.confirm');
|
confirmBtn = dlg.querySelector('.confirm');
|
||||||
if (confirmBtn) {
|
if (confirmBtn) {
|
||||||
confirmBtn.addEventListener('click', function(event) {
|
confirmBtn.addEventListener('click', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (link.tagName == 'BUTTON') {
|
if (link.tagName == 'BUTTON') {
|
||||||
var form = link.parentElement
|
var form = link.parentElement
|
||||||
while (form && form.tagName != 'FORM') {
|
while (form && form.tagName != 'FORM') {
|
||||||
var form = form.parentElement
|
var form = form.parentElement
|
||||||
}
|
}
|
||||||
if (form) {
|
if (form) {
|
||||||
var input = document.createElement('input');
|
var input = document.createElement('input');
|
||||||
input.type = 'hidden';
|
input.type = 'hidden';
|
||||||
input.name = 'button';
|
input.name = 'button';
|
||||||
input.value = link.value;
|
input.value = link.value;
|
||||||
form.appendChild(input);
|
form.appendChild(input);
|
||||||
form.submit();
|
form.submit();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
window.location.href = link.getAttribute('href');
|
window.location.href = link.getAttribute('href');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
window.openOverlay(dlg, primaryContent, body);
|
window.openOverlay(dlg, primaryContent, body);
|
||||||
}
|
}
|
||||||
function closeDlg(dlg) {
|
function closeDlg(dlg) {
|
||||||
window.closeOverlay(dlg, primaryContent, body);
|
window.closeOverlay(dlg, primaryContent, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
var confirmationDlg = document.getElementById('confirmation-dlg');
|
var confirmationDlg = document.getElementById('confirmation-dlg');
|
||||||
forEachElement('[data-confirmation]', function(link) {
|
forEachElement('[data-confirmation]', function(link) {
|
||||||
link.addEventListener('click', function(event) {
|
link.addEventListener('click', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
openDlg(confirmationDlg, link);
|
openDlg(confirmationDlg, link);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
var infoDlg = document.getElementById('info-dlg');
|
var infoDlg = document.getElementById('info-dlg');
|
||||||
forEachElement('[data-info-text]', function(link) {
|
forEachElement('[data-info-text]', function(link) {
|
||||||
link.addEventListener('click', function(event) {
|
link.addEventListener('click', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
openDlg(infoDlg, link);
|
openDlg(infoDlg, link);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
var loginDlg = document.getElementById('login-dlg');
|
var loginDlg = document.getElementById('login-dlg');
|
||||||
forEachElement('[data-sign-in]', function(link) {
|
forEachElement('[data-sign-in]', function(link) {
|
||||||
link.addEventListener('click', function(event) {
|
link.addEventListener('click', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
openDlg(loginDlg, link);
|
openDlg(loginDlg, link);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
var contactDlg = document.getElementById('contact-dlg');
|
var contactDlg = document.getElementById('contact-dlg');
|
||||||
var contactLink = document.getElementById('contact-link');
|
var contactLink = document.getElementById('contact-link');
|
||||||
contactLink.addEventListener('click', function(event) {
|
contactLink.addEventListener('click', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
openDlg(contactDlg, contactLink);
|
openDlg(contactDlg, contactLink);
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var htmlNode = document.documentElement;
|
var htmlNode = document.documentElement;
|
||||||
document.addEventListener('keydown', function(event) {
|
document.addEventListener('keydown', function(event) {
|
||||||
if (htmlNode.dataset.input != 'kb' &&
|
if (htmlNode.dataset.input != 'kb' &&
|
||||||
((["input", "textarea", "select", "option"].indexOf(event.target.nodeName.toLowerCase()) < 0 &&
|
((["input", "textarea", "select", "option"].indexOf(event.target.nodeName.toLowerCase()) < 0 &&
|
||||||
!event.target.attributes.contenteditable) || event.key == "Tab")) {
|
!event.target.attributes.contenteditable) || event.key == "Tab")) {
|
||||||
htmlNode.setAttribute('data-input', 'kb');
|
htmlNode.setAttribute('data-input', 'kb');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
document.addEventListener('mousemove', function(event) {
|
document.addEventListener('mousemove', function(event) {
|
||||||
if (htmlNode.dataset.input != 'mouse' && (event.movementX || event.movementY)) {
|
if (htmlNode.dataset.input != 'mouse' && (event.movementX || event.movementY)) {
|
||||||
htmlNode.setAttribute('data-input', 'mouse');
|
htmlNode.setAttribute('data-input', 'mouse');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
var errorField = document.querySelector('.input-field.has-error input, .input-field.has-error textarea');
|
var errorField = document.querySelector('.input-field.has-error input, .input-field.has-error textarea');
|
||||||
if (errorField) {
|
if (errorField) {
|
||||||
errorField.focus();
|
errorField.focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
window.initNodeFunctions = [ function(node) {
|
window.initNodeFunctions = [ function(node) {
|
||||||
forEachElement('.number-field,.email-field,.text-field,.password-field,.search-field', function(field) {
|
forEachElement('.number-field,.email-field,.text-field,.password-field,.search-field', function(field) {
|
||||||
var input = field.querySelector('input');
|
var input = field.querySelector('input');
|
||||||
var positionLabel = function(input) {
|
var positionLabel = function(input) {
|
||||||
field.classList[input.value ? 'remove' : 'add']('empty');
|
field.classList[input.value ? 'remove' : 'add']('empty');
|
||||||
}
|
}
|
||||||
positionLabel(input);
|
positionLabel(input);
|
||||||
input.addEventListener('keyup', function(event) {
|
input.addEventListener('keyup', function(event) {
|
||||||
positionLabel(event.target);
|
positionLabel(event.target);
|
||||||
});
|
});
|
||||||
input.addEventListener('blur', function(event) {
|
input.addEventListener('blur', function(event) {
|
||||||
positionLabel(event.target);
|
positionLabel(event.target);
|
||||||
field.classList.remove('focused');
|
field.classList.remove('focused');
|
||||||
});
|
});
|
||||||
input.addEventListener('focus', function(event) {
|
input.addEventListener('focus', function(event) {
|
||||||
field.classList.add('focused');
|
field.classList.add('focused');
|
||||||
});
|
});
|
||||||
}, node || document);
|
}, node || document);
|
||||||
forEachElement('form.js-xhr', function(form) {
|
forEachElement('form.js-xhr', function(form) {
|
||||||
if (form.addEventListener) {
|
if (form.addEventListener) {
|
||||||
form.addEventListener('submit', function(event) {
|
form.addEventListener('submit', function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
form.classList.add('requesting');
|
form.classList.add('requesting');
|
||||||
var data = new FormData(form);
|
var data = new FormData(form);
|
||||||
var request = new XMLHttpRequest();
|
var request = new XMLHttpRequest();
|
||||||
request.onreadystatechange = function() {
|
request.onreadystatechange = function() {
|
||||||
if (request.readyState == 4) {
|
if (request.readyState == 4) {
|
||||||
form.classList.remove('requesting');
|
form.classList.remove('requesting');
|
||||||
if (request.status == 200) {
|
if (request.status == 200) {
|
||||||
var response = JSON.parse(request.responseText);
|
var response = JSON.parse(request.responseText);
|
||||||
for (var i = 0; i < response.length; i++) {
|
for (var i = 0; i < response.length; i++) {
|
||||||
var element;
|
var element;
|
||||||
if (response[i].selector) {
|
if (response[i].selector) {
|
||||||
element = form.querySelector(response[i].selector);
|
element = form.querySelector(response[i].selector);
|
||||||
}
|
}
|
||||||
if (response[i].globalSelector) {
|
if (response[i].globalSelector) {
|
||||||
element = document.querySelector(response[i].globalSelector);
|
element = document.querySelector(response[i].globalSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response[i].html) {
|
if (response[i].html) {
|
||||||
element.innerHTML = response[i].html;
|
element.innerHTML = response[i].html;
|
||||||
window.initNode(element);
|
window.initNode(element);
|
||||||
}
|
}
|
||||||
if (response[i].className) {
|
if (response[i].className) {
|
||||||
element.className = response[i].className;
|
element.className = response[i].className;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
request.open('POST', form.getAttribute('action'), true);
|
request.open('POST', form.getAttribute('action'), true);
|
||||||
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||||
request.send(data);
|
request.send(data);
|
||||||
}, false);
|
}, false);
|
||||||
}
|
}
|
||||||
}, node || document);
|
}, node || document);
|
||||||
forEachElement('[data-opens]', function(control) {
|
forEachElement('[data-opens]', function(control) {
|
||||||
control.addEventListener('click', function(event) {
|
control.addEventListener('click', function(event) {
|
||||||
var opens = document.querySelector(control.getAttribute('data-opens'));
|
var opens = document.querySelector(control.getAttribute('data-opens'));
|
||||||
if (!opens.classList.contains('open')){
|
if (!opens.classList.contains('open')){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
opens.className += ' open';
|
opens.className += ' open';
|
||||||
if (control.getAttribute('data-focus')) {
|
if (control.getAttribute('data-focus')) {
|
||||||
var input = opens.querySelector(control.getAttribute('data-focus'));
|
var input = opens.querySelector(control.getAttribute('data-focus'));
|
||||||
if (input) {
|
if (input) {
|
||||||
input.focus();
|
input.focus();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
} ];
|
} ];
|
||||||
window.initNode = function(node) {
|
window.initNode = function(node) {
|
||||||
forEach(initNodeFunctions, function(fn) {
|
forEach(initNodeFunctions, function(fn) {
|
||||||
fn(node);
|
fn(node);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
initNode();
|
initNode();
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
var errors = document.getElementsByClassName('has-error');
|
var errors = document.getElementsByClassName('has-error');
|
||||||
if (errors.length <= 0) {
|
if (errors.length <= 0) {
|
||||||
errors = document.getElementsByClassName('info-message');
|
errors = document.getElementsByClassName('info-message');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errors.length > 0) {
|
if (errors.length > 0) {
|
||||||
errors[0].scrollIntoView();
|
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');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
@ -12,6 +12,7 @@ html, body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
background-color: $white;
|
||||||
padding-bottom: 20vw;
|
padding-bottom: 20vw;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1807,6 +1808,7 @@ ul.warnings {
|
|||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
padding: 0 0.333em;
|
padding: 0 0.333em;
|
||||||
|
display: inline-block;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
@include after {
|
@include after {
|
||||||
@ -2946,6 +2948,9 @@ a.logo {
|
|||||||
|
|
||||||
.conference-banner {
|
.conference-banner {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0 -1em 2em;
|
||||||
|
width: auto;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 5vw;
|
font-size: 5vw;
|
||||||
@ -2964,6 +2969,10 @@ a.logo {
|
|||||||
font-size: 0.85em;
|
font-size: 0.85em;
|
||||||
line-height: 2em;
|
line-height: 2em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
img {
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.conference-details {
|
.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 {
|
#banner {
|
||||||
@ -4674,6 +4674,9 @@ html[data-ontop] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.conference-banner {
|
.conference-banner {
|
||||||
|
margin: 0 auto;
|
||||||
|
width: 100%;
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 1.9em;
|
font-size: 1.9em;
|
||||||
margin: 0 0 1em;
|
margin: 0 0 1em;
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
"and_chr": ["54"],
|
"and_chr": ["54"],
|
||||||
"chrome": ["54"],
|
"chrome": ["54"],
|
||||||
"edge": ["13"],
|
"edge": ["13"],
|
||||||
"firefox": ["44"],
|
"firefox": ["48"],
|
||||||
"ie": ["11"],
|
"ie": ["11"],
|
||||||
"ios_saf": ["8", "9"]
|
"ios_saf": ["8", "9"]
|
||||||
}
|
}
|
||||||
|
@ -18,19 +18,30 @@ class City < ActiveRecord::Base
|
|||||||
def get_translation(locale)
|
def get_translation(locale)
|
||||||
location = Geocoder.search(address, language: locale.to_s).first
|
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 |
|
location.data['address_components'].each do | component |
|
||||||
# city is usually labelled a 'locality' but sometimes this is missing and only 'colloquial_area' is present
|
# city is usually labeled a 'locality' but sometimes this is missing and only 'colloquial_area' is present
|
||||||
if component['types'].first == 'locality' || component['types'].first == 'colloquial_area'
|
if component['types'].first == 'locality'
|
||||||
return component['short_name']
|
return component['short_name']
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if component['types'] == location.data['types']
|
||||||
|
searched_component = component['short_name']
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return nil
|
# return the type we searched for but it's still possible that it will be false
|
||||||
|
searched_component
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# this method will get called automatically if a translation is asked for but not found
|
||||||
def translate_city(locale)
|
def translate_city(locale)
|
||||||
translation = get_translation(locale)
|
translation = get_translation(locale)
|
||||||
|
|
||||||
|
# if we found it, set it
|
||||||
if translation.present?
|
if translation.present?
|
||||||
set_column_for_locale(:city, locale, translation)
|
set_column_for_locale(:city, locale, translation)
|
||||||
save!
|
save!
|
||||||
@ -48,16 +59,20 @@ class City < ActiveRecord::Base
|
|||||||
# look up the city in the geocoder
|
# look up the city in the geocoder
|
||||||
location = Geocoder.search(str, language: 'en').first
|
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
|
# see if the city is already present in our database
|
||||||
city = City.find_by_place_id(location.data['place_id'])
|
city = City.find_by_place_id(location.data['place_id'])
|
||||||
|
|
||||||
# return the city if we found it in the db already
|
# 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
|
# otherwise build a new city
|
||||||
component_alises = {
|
component_alises = {
|
||||||
'locality' => :city,
|
'locality' => :city,
|
||||||
'colloquial_area' => :city,
|
|
||||||
'administrative_area_level_1' => :territory,
|
'administrative_area_level_1' => :territory,
|
||||||
'country' => :country
|
'country' => :country
|
||||||
}
|
}
|
||||||
@ -67,15 +82,61 @@ class City < ActiveRecord::Base
|
|||||||
longitude: location.data['geometry']['location']['lng'],
|
longitude: location.data['geometry']['location']['lng'],
|
||||||
place_id: location.data['place_id']
|
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 |
|
location.data['address_components'].each do | component |
|
||||||
property = component_alises[component['types'].first]
|
property = component_alises[component['types'].first]
|
||||||
city_data[property] = component['short_name'] if property.present?
|
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
|
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
|
# save the new city
|
||||||
city = City.new(city_data)
|
city = City.new(city_data)
|
||||||
city.save!
|
city.save!
|
||||||
|
|
||||||
|
# save this to our cache
|
||||||
|
CityCache.create(city_id: city.id, search: str)
|
||||||
|
|
||||||
# and return it
|
# and return it
|
||||||
return city
|
return city
|
||||||
end
|
end
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
%meta{property: 'og:image', content: og_image}
|
%meta{property: 'og:image', content: og_image}
|
||||||
%meta{name: "theme-color", content: @theme_colour}
|
%meta{name: "theme-color", content: @theme_colour}
|
||||||
= yield :head
|
= 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 }
|
%body{ class: page_style }
|
||||||
#primary-content
|
#primary-content
|
||||||
|
@ -1,21 +1,24 @@
|
|||||||
# config/initializers/geocoder.rb
|
# config/initializers/geocoder.rb
|
||||||
Geocoder.configure(
|
config = {
|
||||||
# geocoding service (see below for supported options):
|
# geocoding service (see below for supported options):
|
||||||
:lookup => :google,
|
lookup: :google,
|
||||||
|
|
||||||
# IP address geocoding service (see below for supported options):
|
# IP address geocoding service (see below for supported options):
|
||||||
:ip_lookup => :freegeoip,
|
ip_lookup: :freegeoip,
|
||||||
|
|
||||||
# to use an API key:
|
# to use an API key:
|
||||||
# :api_key => "AIzaSyDitM1lyVWkrumteDvSkje6GiIKYyHlAXM",
|
|
||||||
|
|
||||||
# geocoding service request timeout, in seconds (default 3):
|
# geocoding service request timeout, in seconds (default 3):
|
||||||
:timeout => 5,
|
timeout: 5,
|
||||||
|
|
||||||
# set default units to kilometers:
|
# set default units to kilometers:
|
||||||
:units => :km,
|
units: :km
|
||||||
|
}
|
||||||
|
|
||||||
# caching (see below for details):
|
# use our api key on the server
|
||||||
#:cache => Redis.new,
|
if Rails.env.preview? || Rails.env.production?
|
||||||
#:cache_prefix => "..."
|
config[:api_key] = "AIzaSyDurfjX9f_NgYsJLyUuGqwdKuI745CE_OE"
|
||||||
)
|
config[:use_https] = true
|
||||||
|
end
|
||||||
|
|
||||||
|
Geocoder.configure(config)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user