Initial code for Boost your Spark on desktop

This commit is contained in:
sork 2011-04-11 23:15:33 +02:00
Родитель ab7e20b6a8
Коммит 432d8f31c5
15 изменённых файлов: 227 добавлений и 228 удалений

Просмотреть файл

@ -1,7 +1,7 @@
{% extends "desktop/base.html" %}
{% set title = _('Your Spark dashboard') %}
{% set body_id = 'dashboard' %}
{% set scripts = ('desktop', 'raphael', 'dashboard') %}
{% set scripts = ('desktop', 'raphael', 'dashboard', 'geolocation') %}
{% block content %}
<div id="container">
@ -47,6 +47,9 @@ $(document).ready(function() {
{% include 'desktop/includes/dashboard-script.html' %}
initPlaceholders();
initYourAccountPopups();
initBoostPopups();
});
</script>
{% endblock %}

Просмотреть файл

@ -1,5 +1,5 @@
<div id="popup">
<!-- <div id="boost0">
<div id="boost">
<h3>{{ _('Boost your Spark') }}</h3>
<p class="legend">
{{ _('Wanna share a few more details?') }}<br>
@ -11,7 +11,8 @@
<a class="button left-button close">{{ _('Maybe later') }}</a>
<button tabindex="2" class="right-button" type="submit">{{ _("Let's boost") }}</button>
</div>
</div> -->
</div>
<div id="boost1">
<h3>{{ _('Boost your Spark') }}</h3>
<h4>{{ _('Step 1 of 2') }}</h4>
@ -21,73 +22,93 @@
<!-- Initial state -->
<div class="disclaimer">
<a href="http://www.mozilla.com/m/privacy.html">{{ _('Learn how Mozilla protects your geolocation data') }} ></a>
<a href="http://www.mozilla.com/en-US/privacy-policy.html" target="_blank">{{ _('Learn how Mozilla protects your geolocation data') }} ></a>
</div>
<hr>
<div class="buttons-wrapper">
{# L10n: Space is limited here, the translation should be no longer than ~15 latin characters #}
<a class="button left-button close">{{ _('Maybe later') }}</a>
<a class="button right-button" id="geolocate">{{ _('Locate me') }}<img src="{{ MEDIA_URL }}img/mobile/spinner.gif" alt="" class="preload spinner"></a>
<div id="geolocate"><a class="button right-button">{{ _('Locate me') }}</a><img src="{{ MEDIA_URL }}img/mobile/spinner.gif" alt="" class="preload spinner"></div>
</div>
<!-- Should be displayed when geolocation works -->
<!-- <div id="location-result">
</div>
<form id="boost1-form" action="{{ url('mobile.boost1')|secure_url }}" method="post" accept-charset="utf-8">
{{ csrf() }}
<input type="hidden" id="lat" name="lat" value="">
<input type="hidden" id="long" name="long" value="">
<input type="hidden" id="city" name="city" value="">
<input type="hidden" id="country-code" name="country_code" value="">
<input type="hidden" id="country" name="country" value="">
<input type="hidden" id="us-state" name="us_state" value="">
</form>
<div id="boost1-confirm">
<h3>{{ _('Boost your Spark') }}</h3>
<h4>{{ _('Step 1 of 2') }}</h4>
<div id="location-result">
<div id="checkmark"></div>
<div id="your-location">
{# L10n: Placed before the location where the user has been geolocated. #}
{{ _('Your location') }}
<span>{{ geo_result }}Paris, France</span>
<span></span>
</div>
<div class="buttons-wrapper">
{# L10n: Space is limited here, the translation should be no longer than ~15 latin characters #}
<a class="button left-button close">{{ _('Cancel') }}</a>
<a class="button right-button">{{ _('Next step') }}</a>
</div>
</div>
<div class="buttons-wrapper">
{# L10n: Space is limited here, the translation should be no longer than ~15 latin characters #}
<a class="button left-button">{{ _('Cancel') }}</a>
<a class="button right-button">{{ _('Next step') }}</a>
</div> -->
<!-- If geolocation fails -->
<!-- <span class="error">{{ _("Sorry, we couldn't determine your location.") }}</span>
<hr>
<div class="cta"><a href="{{ url('mobile.yourlocation') }}">{{ _('Select your location manually') }}</a></div>
<hr>
<div class="buttons-wrapper">
{# L10n: Space is limited here, the translation should be no longer than ~15 latin characters #}
<a class="button left-button">{{ _('Cancel') }}</a>
<a class="button right-button" id="geolocate">{{ _('Try again') }}</a>
</div> -->
<div id="location-error">
<span class="error">{{ _("Sorry, we couldn't determine your location.") }}</span>
<hr>
<div class="cta"><a href="{{ url('desktop.cities') }}">{{ _('Select your location manually') }}</a></div>
<hr>
<div class="buttons-wrapper">
{# L10n: Space is limited here, the translation should be no longer than ~15 latin characters #}
<a class="button left-button close">{{ _('Cancel') }}</a>
<div id="geolocate"><a class="button right-button">{{ _('Try again') }}</a><img src="{{ MEDIA_URL }}img/mobile/spinner.gif" alt="" class="preload spinner"></div>
</div>
</div>
</div>
<div id="select-location">
<h3>{{ _('Boost your Spark') }}</h3>
<h4>{{ _('Step 1 of 2') }}</h4>
<!-- Choose your location manually -->
<!-- <p class="legend">
<p class="legend">
{{ _("Select your location manually") }}
</p>
<form method="post" id="choose-location">
<form id="select-location-form" method="post">
{{ csrf() }}
<fieldset>
<select name="citylist" id="citylist">
<select tabindex="1" name="chosen_city" id="citylist">
<option value="">{{ _("Your location") }}</option>
{% for (id, city) in cities %}
<option value="{{ id }}">{{ city }}</option>
{% endfor %}
</select>
</fieldset>
<div class="buttons-wrapper">
{# L10n: Space is limited here, the translation should be no longer than ~15 latin characters #}
<a class="button left-button">{{ _('Cancel') }}</a>
<a class="button right-button">{{ _('OK') }}</a>
<a class="button left-button close">{{ _('Cancel') }}</a>
<button tabindex="2" class="right-button" type="submit">{{ _('OK') }}</button>
</div>
</form> -->
</form>
</div>
<div id="boost2">
<h3>{{ _('Boost your Spark') }}</h3>
<h4>{{ _('Step 2 of 2') }}</h4>
<!-- Step 2 -->
<!-- <h4>{{ _('Step 2 of 2') }}</h4>
<p class="legend">
{% trans %}
Did someone send you a spark? Enter their username or email address
below so you guys can be connected, help visualize where your Spark
has travelled and make cool stuff happen.
{% endtrans %}
</p> -->
</p>
<!-- Step 2 start state -->
<!-- <form method="post" accept-charset="utf-8">
<form method="post" accept-charset="utf-8">
{{ csrf() }}
<fieldset id="identifier" class="section">
<div class="input-wrapper">
@ -109,41 +130,45 @@
<hr>
<div class="buttons-wrapper">
{# L10n: Space is limited here. The translation should be no longer than the English version, leave only "Later" if needed #}
<a class="button left-button" href="">{{ _('Maybe later') }}</a>
<a class="button left-button close">{{ _('Maybe later') }}</a>
<a tabindex="3" class="button right-button" type="submit">{{ _('Find') }}</a>
</div>
</form> -->
<!-- Step 2 success -->
<!-- {% if no_parent %}
</form>
</div>
<form id="boost2-form" action="{{ url('mobile.boost2_confirm')|secure_url }}" method="post" accept-charset="utf-8">
{{ csrf() }}
<input type="hidden" name="no_parent" value="">
<input type="hidden" name="parent" value="">
</form>
<div id="boost2-confirm">
<div id="boost2-result">
<div id="checkmark"></div>
<span>
{{ _('Congrats! You started a new Spark.') }}
</span>
</span>
</div>
{% else %}
<div id="boost2-result">
<div id="checkmark"></div>
<span>
{{ _('Your Spark was started by: {parent}')|f(parent=parent) }}
{{ _('Your Spark was started by:') }}
<span></span>
</span>
</div>
{% endif %}
<form action="{{ url('mobile.boost2_confirm') }}" method="POST">
{{ csrf() }}
{% if no_parent %}
<input type="hidden" name="no_parent" value="1">
{% else %}
<input type="hidden" name="parent" value="{{ parent }}">
{% endif %}
<input id="no-parent" type="hidden" name="no_parent" value="1">
<input id="has-parent" type="hidden" name="parent" value="">
<div class="buttons-wrapper">
<a class="button left-button" href="{{ url('mobile.home') }}">{{ _('Cancel') }}</a>
<a class="button left-button close">{{ _('Cancel') }}</a>
{# L10n: Action verb on a form submit button. #}
<a class="button right-button" type="submit">{{ _('Complete') }}</a>
</div>
</form> -->
</form>
</div>
{% include 'desktop/popups/your-account.html' %}
</div>

Просмотреть файл

@ -9,4 +9,5 @@ urlpatterns = patterns('',
url(r'^user/(?P<username>[\w.+-]+)$', views.user, name='desktop.user'),
url(r'^global$', views.visualization, name='desktop.visualization'),
url(r'^close$', views.close, name='desktop.close_popup'),
url(r'^cities$', views.cities, name='desktop.cities')
)

Просмотреть файл

@ -9,10 +9,11 @@ from django.utils.http import urlquote
from geo.countries import countries
from spark.decorators import ssl_required, login_required, mobile_view
from spark.decorators import ssl_required, login_required, mobile_view, json_view, ajax_required
from spark.helpers import secure_url
from spark.urlresolvers import reverse, absolute_url
from spark.utils import get_city_fullname
from spark.models import City
from sharing.utils import set_sharing_cookies
from sharing.messages import (TWITTER_SHARE_MSG, TWITTER_SPARK_MSG, FACEBOOK_SPARK_TITLE,
@ -119,8 +120,17 @@ def visualization(request):
def close(request):
return jingo.render(request, 'desktop/close.html')
@json_view
def cities(request):
cities = City.objects.order_by('city_name')
citylist = [(city.id, get_city_fullname(city.city_name, city.country_code, request.locale)) for city in cities]
print 'hop'
return citylist
def _total_seconds(td):
"""Returns the total number of seconds in a given timedelta."""
return (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

Просмотреть файл

@ -65,3 +65,19 @@
</div>
</form>
{% endblock %}
{% block script %}
<script>
$(document).ready(function() {
var callback = function() {
$('form').submit();
};
var onLocateMe = function() {
$('#geolocate a').hide();
$('#geolocate img').show();
$('ul.errorlist').hide();
};
initGeolocation(onLocateMe, callback, callback);
});
</script>
{% endblock %}

Просмотреть файл

@ -7,7 +7,7 @@ import jingo
from spark.models import City
from spark.urlresolvers import reverse, absolute_url
from spark.decorators import post_required
from spark.decorators import post_required, json_view
from spark.utils import (get_city_fullname, is_supported_non_firefox, is_iphone,
is_firefox_mobile, is_android, get_ua, approximate_major_city)
@ -64,6 +64,7 @@ def boost(request):
@login_required
@json_view
def boost1(request):
""" Boost your Spark step 1/2 :
Allows a Spark user to be geolocated by the application."""

Просмотреть файл

@ -745,7 +745,8 @@ span.error {
font-size:1.231em;
}
#sign-in, #your-account, #password-recovery, #success, #change-email, #change-password, #delete-account, #register {
#sign-in, #your-account, #password-recovery, #success, #change-email, #change-password, #delete-account, #register,
#boost, #boost1, #boost1-confirm, #boost2, #boost2-confirm, #select-location {
display:none;
}

Просмотреть файл

@ -91,6 +91,12 @@ $(document).ready(function() {
$('#your-account').show();
showPopup();
});
// displays the boost popups
$('#user-details .popup-trigger').click(function() {
$('#boost').show();
showPopup();
});
// hides the sign-in modal popup (and resets it to sign-in state)
$mask.click(function() {

Просмотреть файл

@ -0,0 +1,80 @@
var initBoost = function() {
// Let's boost
$('#boost .right-button').click(function() {
swap('#boost', '#boost1');
});
// Try again (boost 1)
$('#location-error .right-button').click(function() {
swap('#boost1-confirm', '#boost1');
});
popupForm('#select-location-form', null, function($form, data) {
refreshYourLocation(data.cityName, data.countryName);
swap('#select-location', '#boost1-confirm');
});
// Select your location manually
$('#location-error .cta a').click(function(e) {
$.get($(this).attr('href'), function(cities) {
var citylist = $("#citylist");
//¨Populate city drop-down
$.each(cities, function(index, city) {
citylist.append($("<option />").val(city[0]).text(city[1]));
});
swap('#boost1-confirm', '#select-location');
});
e.preventDefault();
return false;
});
// Next step (boost 1 confirm)
$('#boost1-confirm .right-button').click(function() {
swap('#boost1-confirm', '#boost2');
});
/*
var boost1Error = function() {
alert('error');
};
var boost1Success = function() {
alert('success');
};
popupForm('#boost1-form', boost1Error, boost1Success);*/
};
var geoSuccess = function() {
swap('#boost1', '#boost1-confirm');
refreshYourLocation($('#city').val(), $('#country').val());
$('#location-error').hide();
$('#location-result').show();
};
var geoError = function() {
swap('#boost1', '#boost1-confirm');
$('#location-error').show();
$('#location-result').hide();
};
var onLocateClick = function() {
$('#geolocate a').hide();
$('#geolocate img').show();
$('ul.errorlist').hide();
};
var initBoostPopups = function() {
initBoost();
initGeolocation(onLocateClick, geoSuccess, geoError);
};
// Helper functions
var refreshYourLocation = function(city, country) {
$('#your-location').find('span').html(city+', '+country);
};

Просмотреть файл

Просмотреть файл

@ -44,9 +44,8 @@ function initDeleteAccountForm() {
});
}
$(document).ready(function() {
initPlaceholders();
function initYourAccountPopups() {
initChangePasswordForm();
initChangeEmailForm();
initDeleteAccountForm();
});
}

Просмотреть файл

Просмотреть файл

@ -1,6 +1,4 @@
$(document).ready(function() {
var timer = null;
function initGeolocation(clickCallback, successCallback, errorCallback) {
var process = function(info) {
if(info.coords) {
$('#lat').attr('value', info.coords.latitude);
@ -14,23 +12,25 @@ $(document).ready(function() {
$('#us-state').attr('value', zipToState(info.address.postalCode));
}
}
$('form').submit();
}
if(successCallback) {
successCallback();
}
};
var error = function() {
$('form').submit();
}
var geolocateMe = function() {
if(errorCallback) {
errorCallback();
}
};
$('#geolocate').click(function() {
navigator.geolocation.getCurrentPosition(process, error, {timeout: 8000});
$('#geolocate a').hide();
$('#geolocate img').show();
$('ul.errorlist').hide();
};
$('#geolocate').click(geolocateMe);
});
if(clickCallback) {
clickCallback();
}
});
}
// Borrowed from http://zacharyburt.com/2010/02/javascript-zip-code-to-state-conversion/
function zipToState(zip) {

Просмотреть файл

@ -1,144 +0,0 @@
/*
CUSTOM FORM ELEMENTS
Created by Ryan Fait
www.ryanfait.com
The only things you may need to change in this file are the following
variables: checkboxHeight, radioHeight and selectWidth (lines 24, 25, 26)
The numbers you set for checkboxHeight and radioHeight should be one quarter
of the total height of the image want to use for checkboxes and radio
buttons. Both images should contain the four stages of both inputs stacked
on top of each other in this order: unchecked, unchecked-clicked, checked,
checked-clicked.
You may need to adjust your images a bit if there is a slight vertical
movement during the different stages of the button activation.
The value of selectWidth should be the width of your select list image.
Visit http://ryanfait.com/ for more information.
*/
var checkboxHeight = "24";
var radioHeight = "24";
var selectWidth = "190";
/* No need to change anything after this */
document.write('<style type="text/css">input.styled { display: none; } select.styled { position: relative; width: ' + selectWidth + 'px; opacity: 0; filter: alpha(opacity=0); z-index: 5; } .disabled { opacity: 0.5; filter: alpha(opacity=50); }</style>');
var Custom = {
init: function() {
var inputs = document.getElementsByTagName("input"), span = Array(), textnode, option, active;
for(a = 0; a < inputs.length; a++) {
if((inputs[a].type == "checkbox" || inputs[a].type == "radio") && inputs[a].className == "styled") {
span[a] = document.createElement("span");
span[a].className = inputs[a].type;
if(inputs[a].checked == true) {
if(inputs[a].type == "checkbox") {
position = "0 -" + (checkboxHeight*2) + "px";
span[a].style.backgroundPosition = position;
} else {
position = "0 -" + (radioHeight*2) + "px";
span[a].style.backgroundPosition = position;
}
}
inputs[a].parentNode.insertBefore(span[a], inputs[a]);
inputs[a].onchange = Custom.clear;
if(!inputs[a].getAttribute("disabled")) {
span[a].onmousedown = Custom.pushed;
span[a].onmouseup = Custom.check;
} else {
span[a].className = span[a].className += " disabled";
}
}
}
inputs = document.getElementsByTagName("select");
for(a = 0; a < inputs.length; a++) {
if(inputs[a].className == "styled") {
option = inputs[a].getElementsByTagName("option");
active = option[0].childNodes[0].nodeValue;
textnode = document.createTextNode(active);
for(b = 0; b < option.length; b++) {
if(option[b].selected == true) {
textnode = document.createTextNode(option[b].childNodes[0].nodeValue);
}
}
span[a] = document.createElement("span");
span[a].className = "select";
span[a].id = "select" + inputs[a].name;
span[a].appendChild(textnode);
inputs[a].parentNode.insertBefore(span[a], inputs[a]);
if(!inputs[a].getAttribute("disabled")) {
inputs[a].onchange = Custom.choose;
} else {
inputs[a].previousSibling.className = inputs[a].previousSibling.className += " disabled";
}
}
}
document.onmouseup = Custom.clear;
},
pushed: function() {
element = this.nextSibling;
if(element.checked == true && element.type == "checkbox") {
this.style.backgroundPosition = "0 -" + checkboxHeight + "px";
} else if(element.checked == true && element.type == "radio") {
this.style.backgroundPosition = "0 -" + radioHeight + "px";
} else if(element.checked != true && element.type == "checkbox") {
this.style.backgroundPosition = "0 -" + checkboxHeight + "px";
} else {
this.style.backgroundPosition = "0 -" + radioHeight + "px";
}
},
check: function() {
element = this.nextSibling;
if(element.checked == true && element.type == "checkbox") {
this.style.backgroundPosition = "0 0";
element.checked = false;
} else {
if(element.type == "checkbox") {
this.style.backgroundPosition = "0 -" + checkboxHeight + "px";
} else {
this.style.backgroundPosition = "0 -" + radioHeight + "px";
group = this.nextSibling.name;
inputs = document.getElementsByTagName("input");
for(a = 0; a < inputs.length; a++) {
if(inputs[a].name == group && inputs[a] != this.nextSibling) {
inputs[a].previousSibling.style.backgroundPosition = "0 0";
}
}
}
element.checked = true;
}
},
clear: function() {
inputs = document.getElementsByTagName("input");
for(var b = 0; b < inputs.length; b++) {
if(inputs[b].type == "checkbox" && inputs[b].checked == true && inputs[b].className == "styled") {
inputs[b].previousSibling.style.backgroundPosition = "0 -" + checkboxHeight + "px";
} else if(inputs[b].type == "checkbox" && inputs[b].className == "styled") {
inputs[b].previousSibling.style.backgroundPosition = "0 0";
} else if(inputs[b].type == "radio" && inputs[b].checked == true && inputs[b].className == "styled") {
inputs[b].previousSibling.style.backgroundPosition = "0 -" + radioHeight + "px";
} else if(inputs[b].type == "radio" && inputs[b].className == "styled") {
inputs[b].previousSibling.style.backgroundPosition = "0 0";
}
}
},
choose: function() {
option = this.getElementsByTagName("option");
for(d = 0; d < option.length; d++) {
if(option[d].selected == true) {
document.getElementById("select" + this.name).childNodes[0].nodeValue = option[d].childNodes[0].nodeValue;
}
}
}
}
window.onload = Custom.init;

Просмотреть файл

@ -184,14 +184,15 @@ MINIFY_BUNDLES = {
),
'home': (
'js/desktop/popups-loggedout.js',
'js/desktop/customforms.js',
'js/libs/customforms.js',
),
'dashboard': (
'js/desktop/minimap.js',
'js/desktop/dashboard.js',
'js/desktop/sharehistory.js',
'js/desktop/popups-youraccount.js',
'js/desktop/customforms.js',
'js/desktop/popups-boost.js',
'js/libs/customforms.js',
'js/desktop/myspark.js',
),
'user-logged-in': (
@ -227,10 +228,10 @@ MINIFY_BUNDLES = {
'js/mobile/badges.js',
),
'geolocation': (
'js/mobile/geolocation.js',
'js/libs/geolocation.js',
),
'customforms': (
'js/mobile/customforms.js',
'js/libs/customforms.js',
),
'myspark': (
'js/mobile/myspark.js',