Structure, Tasty pie API

Added tasty pie
Re-arranged app structure
Posts & comments test
This commit is contained in:
Alex Lewis
2012-10-04 22:33:23 +10:00
parent 450d09fd57
commit b17be39680
27 changed files with 3974 additions and 466 deletions

22
bodyrep/apps/api/auth.py Normal file
View File

@@ -0,0 +1,22 @@
from tastypie.authentication import Authentication
from tastypie.authorization import Authorization
class APIAuthentication(Authentication):
def is_authenticated(self, request, **kwargs):
return not request.user.is_anonymous()
# Optional but recommended
def get_identifier(self, request):
return request.user.username
class APIAuthorization(Authorization):
def is_authorized(self, request, object=None):
return not request.user.is_anonymous()
# Optional but useful for advanced limiting, such as per user.
#def apply_limits(self, request, object_list):
# if request and hasattr(request, 'user'):
# return object_list.filter(author__username=request.user.username)
# return object_list.none()

View File

@@ -0,0 +1,69 @@
# Django
from django.contrib.auth.models import User
from django.db import models
from django.forms.models import model_to_dict
# Tasty pie
from tastypie.resources import ModelResource
from tastypie.models import create_api_key
from tastypie import fields
# BR
from apps.core.models import *
from apps.api.auth import APIAuthentication, APIAuthorization
class AbstractResource(ModelResource):
def alter_list_data_to_serialize(self, request, data):
return data['objects']
def dehydrate_id(self, bundle):
return int(bundle.data['id'])
class Meta:
include_resource_uri = False
limit = 0
class PostResource(AbstractResource):
#member = fields.ForeignKey('apps.api.models.MemberResource', 'member', full = True)
class Meta:
queryset = Post.objects.all()
authorization = APIAuthorization()
authentication = APIAuthentication()
resource_name = 'post'
# Members
class MemberResource(AbstractResource):
class Meta:
queryset = Member.objects.all()
authorization = APIAuthorization()
#include_resource_uri = False
authentication = APIAuthentication()
resource_name = 'members'
fields = ['username', 'firstname', 'lastname']
def dehydrate(self, bundle):
bundle.data['fullname'] = bundle.data['firstname'].lower() + ' ' + bundle.data['lastname'].lower()
return bundle
# Comments
class CommentResource(AbstractResource):
post = fields.ForeignKey(PostResource, 'comment')
class Meta:
queryset = Comment.objects.all()
authorization = APIAuthorization()
authentication = APIAuthentication()
resource_name = 'comment'
# Workouts
class WorkoutResource(ModelResource):
user = User.objects.all()
class Meta:
queryset = Workout.objects.all()
authorization = APIAuthorization()
authentication = APIAuthentication()
resource_name = 'workouts'

View File

134
bodyrep/apps/auth/forms.py Normal file
View File

@@ -0,0 +1,134 @@
import datetime
# Django
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from django.db.models import Q
# Br
from apps.core.models import Member
class LoginForm(forms.Form):
username = forms.CharField(label=_("Username"), max_length=30,
widget=forms.TextInput(attrs={'tabindex': 1, 'class': 'NB-input'}),
error_messages={'required': 'Please enter a username.'})
password = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(attrs={'tabindex': 2, 'class': 'NB-input'}),
required=False)
def __init__(self, *args, **kwargs):
self.user_cache = None
super(LoginForm, self).__init__(*args, **kwargs)
def clean(self):
username = self.cleaned_data.get('username', '').lower()
password = self.cleaned_data.get('password', '')
user = User.objects.filter(Q(username__iexact=username) | Q(email=username))
if username and user:
self.user_cache = authenticate(username=user[0].username, password=password)
if self.user_cache is None:
self.user_cache = authenticate(username=user[0].username, password="")
if self.user_cache is None:
email_username = User.objects.filter(email=username)
if email_username:
self.user_cache = authenticate(username=email_username[0].username, password=password)
if self.user_cache is None:
self.user_cache = authenticate(username=email_username[0].username, password="")
if self.user_cache is None:
jkless_password = password.replace('j', '').replace('k', '')
self.user_cache = authenticate(username=username, password=jkless_password)
if self.user_cache is None:
raise forms.ValidationError(_("Login failed. Try again"))
# else:
# Supreme fuck-up. Accidentally removed the letters J and K from
# all user passwords. Re-save with correct password.
#logging.info(" ***> [%s] FIXING JK-LESS PASSWORD" % username)
# self.user_cache.set_password(password)
# self.user_cache.save()
if not self.user_cache.is_active:
raise forms.ValidationError(_("This account is inactive."))
elif username and not user:
raise forms.ValidationError(_("That username is not registered. Create an account with it instead."))
return self.cleaned_data
def get_user_id(self):
if self.user_cache:
return self.user_cache.id
return None
def get_user(self):
return self.user_cache
class SignupForm(forms.Form):
username = forms.RegexField(regex=r'^\w+$',
max_length=30,
widget=forms.TextInput(attrs={'class': ''}),
required=False,
label=_(u'username'),
error_messages={
'required': 'Please enter a username.',
'invalid': "Your username may only contain letters and numbers."
})
email = forms.EmailField(widget=forms.TextInput(attrs={'maxlength': 75, 'class': ''}),
label=_(u'email address'),
required=False)
# error_messages={'required': 'Please enter your email.'})
password = forms.CharField(widget=forms.PasswordInput(attrs={'class': 'NB-input'}),
label=_(u'password'),
required=False)
# error_messages={'required': 'Please enter a password.'})
def clean_username(self):
username = self.cleaned_data['username']
return username
def clean_password(self):
if not self.cleaned_data['password']:
return ""
return self.cleaned_data['password']
def clean_email(self):
if not self.cleaned_data['email']:
return ""
return self.cleaned_data['email']
def clean(self):
username = self.cleaned_data.get('username', '')
password = self.cleaned_data.get('password', '')
exists = User.objects.filter(username__iexact=username).count()
#if exists:
# user_auth = authenticate(username=username, password=password)
# if not user_auth:
# raise forms.ValidationError(_(u'Someone is already using that username.'))
return self.cleaned_data
def save(self, profile_callback=None):
username = self.cleaned_data['username']
password = self.cleaned_data['password']
exists = User.objects.filter(username__iexact=username).count()
# if exists:
# user_auth = authenticate(username=username, password=password)
# if not user_auth:
# raise forms.ValidationError(_(u'Someone is already using that username.'))
# else:
# return user_auth
new_user = User(username=username)
new_user.set_password(password)
new_user.is_active = True
new_user.email = self.cleaned_data['email']
new_user.save()
new_user = authenticate(username=username,
password=password)
# MActivity.new_signup(user_id=new_user.pk)
# if new_user.email:
# EmailNewUser.delay(user_id=new_user.pk)
return new_user

View File

@@ -0,0 +1,74 @@
import urllib
import urlparse
# Django
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404
from django.conf import settings
from django.views.decorators.cache import never_cache
from django.contrib.auth import login as login_user
from django.contrib.auth import logout as logout_user
# Libs
from annoying.decorators import render_to, ajax_request
# BR
from apps.auth.forms import LoginForm, SignupForm
from utils.functions import get_user, render_to
# Vendors
#from vendor import facebook
@never_cache
@render_to('auth/signup.html')
def signup(request):
form = SignupForm(prefix='signup', data=request.POST)
if request.method == "POST":
if form.is_valid():
new_user = form.save()
login_user(request, new_user)
return HttpResponseRedirect(reverse('showUserProfile'))
return {'signup_form':form}
@never_cache
@render_to('auth/login.html')
def login(request):
if not request.user.is_anonymous():
return HttpResponseRedirect(reverse('showUserProfile'))
if request.method == "POST":
if request.POST.get('submit', '').startswith('log'):
login_form = LoginForm(request.POST, prefix='login')
else:
login_form = LoginForm(prefix='login')
else:
login_form = LoginForm(prefix='login')
return {'login_form':login_form}
@never_cache
def dologin(request):
code = -1
message = ""
if request.method == "POST":
form = LoginForm(request.POST, prefix='login')
if form.is_valid():
login_user(request, form.get_user())
return HttpResponseRedirect(reverse('showUserProfile'))
else:
message = form.errors.items()[0][1][0]
@never_cache
def logout(request):
logout_user(request)
if request.GET.get('api'):
return HttpResponse(json.encode(dict(code=1)), mimetype='application/json')
else:
return HttpResponseRedirect(reverse('index'))

View File

@@ -1,73 +0,0 @@
import urllib
import urlparse
from django.contrib.auth.decorators import login_required
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User
from django.contrib.sites.models import Site
from django.http import HttpResponseForbidden, HttpResponseRedirect
from django.conf import settings
from utils.functions import ajax_login_required, render_to
from vendor import facebook
@render_to('core/auth/facebook.html')
def facebook_connect(request):
facebook_app_id = settings.FACEBOOK_APP_ID
facebook_secret = settings.FACEBOOK_SECRET
args = {
"client_id": facebook_app_id,
"redirect_uri": "http://" + Site.objects.get_current().domain + reverse('facebook-connect'),
"scope": "offline_access,user_website,publish_actions",
"display": "popup",
}
verification_code = request.REQUEST.get('code')
if verification_code:
args["client_secret"] = facebook_secret
args["code"] = verification_code
uri = "https://graph.facebook.com/oauth/access_token?" + \
urllib.urlencode(args)
response_text = urllib.urlopen(uri).read()
response = urlparse.parse_qs(response_text)
if "access_token" not in response:
logging.user(request, "~BB~FRFailed Facebook connect")
return dict(error="Facebook has returned an error. Try connecting again.")
access_token = response["access_token"][-1]
# Get the user's profile.
graph = facebook.GraphAPI(access_token)
profile = graph.get_object("me")
uid = profile["id"]
# Be sure that two people aren't using the same Facebook account.
existing_user = MSocialServices.objects.filter(facebook_uid=uid)
if existing_user and existing_user[0].user_id != request.user.pk:
user = User.objects.get(pk=existing_user[0].user_id)
#logging.user(request, "~BB~FRFailed FB connect, another user: %s" % user.username)
return dict(error=("Another user (%s, %s) has "
"already connected with those Facebook credentials."
% (user.username, user.email or "no email")))
social_services, _ = MSocialServices.objects.get_or_create(user_id=request.user.pk)
social_services.facebook_uid = uid
social_services.facebook_access_token = access_token
social_services.syncing_facebook = True
social_services.save()
SyncFacebookFriends.delay(user_id=request.user.pk)
#srequest, "~BB~FRFinishing Facebook connect")
return {}
elif request.REQUEST.get('error'):
#logging.user(request, "~BB~FRFailed Facebook connect")
return {'error': '%s... Try connecting again.' % request.REQUEST.get('error')}
else:
# Start the OAuth process
#logging.user(request, "~BB~FRStarting Facebook connect")
url = "https://www.facebook.com/dialog/oauth?" + urllib.urlencode(args)
return {'next': url}

View File

@@ -1,92 +1,39 @@
import datetime
# Django
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from django.db.models import Q
# Br
from apps.core.models import Members
class LoginForm(forms.Form):
username = forms.CharField(label=_("Username"), max_length=30,
widget=forms.TextInput(attrs={'tabindex': 1, 'class': 'NB-input'}),
error_messages={'required': 'Please enter a username.'})
password = forms.CharField(label=_("Password"),
widget=forms.PasswordInput(attrs={'tabindex': 2, 'class': 'NB-input'}),
required=False)
def __init__(self, *args, **kwargs):
self.user_cache = None
super(LoginForm, self).__init__(*args, **kwargs)
def clean(self):
username = self.cleaned_data.get('username', '').lower()
password = self.cleaned_data.get('password', '')
user = User.objects.filter(Q(username__iexact=username) | Q(email=username))
if username and user:
self.user_cache = authenticate(username=user[0].username, password=password)
if self.user_cache is None:
self.user_cache = authenticate(username=user[0].username, password="")
if self.user_cache is None:
email_username = User.objects.filter(email=username)
if email_username:
self.user_cache = authenticate(username=email_username[0].username, password=password)
if self.user_cache is None:
self.user_cache = authenticate(username=email_username[0].username, password="")
if self.user_cache is None:
jkless_password = password.replace('j', '').replace('k', '')
self.user_cache = authenticate(username=username, password=jkless_password)
if self.user_cache is None:
raise forms.ValidationError(_("Login failed. Try again"))
# else:
# Supreme fuck-up. Accidentally removed the letters J and K from
# all user passwords. Re-save with correct password.
#logging.info(" ***> [%s] FIXING JK-LESS PASSWORD" % username)
# self.user_cache.set_password(password)
# self.user_cache.save()
if not self.user_cache.is_active:
raise forms.ValidationError(_("This account is inactive."))
elif username and not user:
raise forms.ValidationError(_("That username is not registered. Create an account with it instead."))
return self.cleaned_data
def get_user_id(self):
if self.user_cache:
return self.user_cache.id
return None
def get_user(self):
return self.user_cache
class EditProfileForm(forms.Form):
firstname = forms.CharField(label=_("First Name"), max_length=30,
widget=forms.TextInput(attrs={'tabindex': 1, 'class': 'NB-input'}),
error_messages={'required': 'Please enter a first name'})
lastname = forms.CharField(label=_("LastName"),
widget=forms.TextInput(attrs={'tabindex': 2, 'class': 'NB-input'}),
error_messages={'required': 'Please enter a last name.'})
def __init__(self, *args, **kwargs):
super(EditProfileForm, self).__init__(*args, **kwargs)
def clean(self):
firstname = self.cleaned_data.get('firstname', '')
lastname = self.cleaned_data.get('lastname', '')
return self.cleaned_data
def save(self, username):
firstname = self.cleaned_data['firstname']
lastname = self.cleaned_data['lastname']
member = Members.objects.get(username=username)
member.firstname = firstname
member.lastname = lastname
member.save()
import datetime
# Django
from django import forms
from django.utils.translation import ugettext_lazy as _
from django.contrib.auth.models import User
from django.contrib.auth import authenticate
from django.db.models import Q
#BR
from apps.core.models import Member
class EditProfileForm(forms.Form):
firstname = forms.CharField(label=_("First Name"), max_length=30,
widget=forms.TextInput(attrs={'tabindex': 1, 'class': 'NB-input'}),
error_messages={'required': 'Please enter a first name'})
lastname = forms.CharField(label=_("LastName"),
widget=forms.TextInput(attrs={'tabindex': 2, 'class': 'NB-input'}),
error_messages={'required': 'Please enter a last name.'})
def __init__(self, *args, **kwargs):
super(EditProfileForm, self).__init__(*args, **kwargs)
def clean(self):
firstname = self.cleaned_data.get('firstname', '')
lastname = self.cleaned_data.get('lastname', '')
return self.cleaned_data
def save(self, username):
firstname = self.cleaned_data['firstname']
lastname = self.cleaned_data['lastname']
member = Member.objects.get(username=username)
member.firstname = firstname
member.lastname = lastname
member.save()
return member

View File

@@ -1,8 +1,26 @@
from django.db import models
from django.contrib import admin
from django.contrib.auth.models import User, UserManager
class Members(models.Model):
username = models.CharField(max_length = 30)
firstname = models.CharField(max_length=30)
lastname = models.CharField(max_length=30)
from django.db import models
from django.contrib import admin
from django.contrib.auth.models import User, UserManager
class Member(models.Model):
username = models.CharField(max_length = 30)
firstname = models.CharField(max_length=30)
lastname = models.CharField(max_length=30)
class Post(models.Model):
username = models.CharField(max_length = 30)
text = models.CharField(max_length=100)
created = models.DateTimeField()
member = models.ForeignKey(Member)
class Comment(models.Model):
username = models.CharField(max_length = 30)
text = models.CharField(max_length=100)
created = models.DateTimeField()
post = models.ForeignKey('Post')
class Workout(models.Model):
username = models.CharField(max_length = 30)
timeSpent = models.CharField(max_length=30)
exercise = models.CharField(max_length=30)
member = models.ForeignKey(Member)

View File

@@ -9,8 +9,6 @@ from django.template.loader import render_to_string
from django.db import IntegrityError
from django.views.decorators.cache import never_cache
from django.core.urlresolvers import reverse
from django.contrib.auth import login as login_user
from django.contrib.auth import logout as logout_user
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect, HttpResponseForbidden, Http404
from django.conf import settings
@@ -18,14 +16,16 @@ from django.contrib.sites.models import Site
from django.core.context_processors import csrf
from django.template import RequestContext
from django.db.models import Q
from django.views.decorators.cache import never_cache
# Libs
from annoying.decorators import render_to, ajax_request
# BR
from apps.core.forms import LoginForm, EditProfileForm
from apps.core.models import Members
from apps.core.models import *
from apps.core.forms import EditProfileForm
from utils.functions import get_user, render_to
from apps.auth.views import login
@render_to('core/landing.html')
def index(request):
@@ -36,71 +36,39 @@ def showUserProfile(request):
if request.user.is_anonymous():
return login(request)
else:
member = Members.objects.get(username=request.user.username)
try:
member = Member.objects.get(username=request.user.username)
except Member.DoesNotExist:
return render_to_response('core/errors/memberNotFound.html')
return {'member': member}
@login_required
@render_to('core/member/profile.html')
def showMemberProfile(request, username):
try:
member = Members.objects.get(username=username)
except Members.DoesNotExist:
member = Member.objects.get(username=username)
except Member.DoesNotExist:
return render_to_response('core/errors/memberNotFound.html')
if request.user.is_anonymous():
return login(request)
else:
return { 'user': request.user, 'member': member }
post = Post.objects.filter(username=request.user.username).prefetch_related('comment_set').all().order_by('created')
@never_cache
@render_to('core/auth/login.html')
def login(request):
if not request.user.is_anonymous():
return HttpResponseRedirect(reverse('showUserProfile'))
if request.method == "POST":
if request.POST.get('submit', '').startswith('log'):
login_form = LoginForm(request.POST, prefix='login')
else:
login_form = LoginForm(prefix='login')
else:
login_form = LoginForm(prefix='login')
return {'login_form':login_form}
return { 'user': request.user, 'member': member, 'post': post }
@never_cache
def search(request, kw):
try:
members = Members.objects.filter(Q(firstname__icontains=kw) | Q(lastname__icontains=kw))
members = Member.objects.filter(Q(firstname__icontains=kw) | Q(lastname__icontains=kw))
except Members.DoesNotExist:
except Member.DoesNotExist:
x=1
return render_to_response ('core/user/searchResults.html', { 'user': request.user, 'members': members} )
@never_cache
def dologin(request):
code = -1
message = ""
if request.method == "POST":
form = LoginForm(request.POST, prefix='login')
if form.is_valid():
login_user(request, form.get_user())
return HttpResponseRedirect(reverse('showUserProfile'))
else:
message = form.errors.items()[0][1][0]
@never_cache
def logout(request):
logout_user(request)
if request.GET.get('api'):
return HttpResponse(json.encode(dict(code=1)), mimetype='application/json')
else:
return HttpResponseRedirect(reverse('index'))
@ajax_request
@render_to('core/user/editProfile.html')
def editUserProfile(request):
@@ -108,7 +76,7 @@ def editUserProfile(request):
return login(request)
else:
member = Members.objects.get(username=request.user.username)
member = Member.objects.get(username=request.user.username)
mdata = {'firstname': member.firstname, 'lastname': member.lastname }
@@ -123,3 +91,12 @@ def saveUserProfile(request):
return { 'result': 1 }
else:
return { 'result': 0 }
@render_to('core/member/comment.html')
def comment(request):
try:
comment = Comment.objects.filter(username=request.user.username)
except Comment.DoesNotExist:
render_to_response('core/member/memberNotFound.html')
return {'comment': comment}

563
bodyrep/media/css/jquery-ui.css vendored Normal file
View File

@@ -0,0 +1,563 @@
/*!
* jQuery UI CSS Framework 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*/
/* Layout helpers
----------------------------------*/
.ui-helper-hidden { display: none; }
.ui-helper-hidden-accessible { position: absolute !important; clip: rect(1px 1px 1px 1px); clip: rect(1px,1px,1px,1px); }
.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; }
.ui-helper-clearfix:before, .ui-helper-clearfix:after { content: ""; display: table; }
.ui-helper-clearfix:after { clear: both; }
.ui-helper-clearfix { zoom: 1; }
.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); }
/* Interaction Cues
----------------------------------*/
.ui-state-disabled { cursor: default !important; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; }
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; }
/*!
* jQuery UI CSS Framework 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Theming/API
*
* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Verdana,Arial,sans-serif&fwDefault=normal&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=cccccc&bgTextureHeader=03_highlight_soft.png&bgImgOpacityHeader=75&borderColorHeader=aaaaaa&fcHeader=222222&iconColorHeader=222222&bgColorContent=ffffff&bgTextureContent=01_flat.png&bgImgOpacityContent=75&borderColorContent=aaaaaa&fcContent=222222&iconColorContent=222222&bgColorDefault=e6e6e6&bgTextureDefault=02_glass.png&bgImgOpacityDefault=75&borderColorDefault=d3d3d3&fcDefault=555555&iconColorDefault=888888&bgColorHover=dadada&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=999999&fcHover=212121&iconColorHover=454545&bgColorActive=ffffff&bgTextureActive=02_glass.png&bgImgOpacityActive=65&borderColorActive=aaaaaa&fcActive=212121&iconColorActive=454545&bgColorHighlight=fbf9ee&bgTextureHighlight=02_glass.png&bgImgOpacityHighlight=55&borderColorHighlight=fcefa1&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px
*/
/* Component containers
----------------------------------*/
.ui-widget { font-family: Verdana,Arial,sans-serif; font-size: 1.1em; }
.ui-widget .ui-widget { font-size: 1em; }
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Verdana,Arial,sans-serif; font-size: 1em; }
.ui-widget-content { border: 1px solid #aaaaaa; background: #ffffff url(/s/img/ui-bg_flat_75_ffffff_40x100.png) 50% 50% repeat-x; color: #222222; }
.ui-widget-content a { color: #222222; }
.ui-widget-header { border: 1px solid #aaaaaa; background: #cccccc url(/s/img/ui-bg_highlight-soft_75_cccccc_1x100.png) 50% 50% repeat-x; color: #222222; font-weight: bold; }
.ui-widget-header a { color: #222222; }
/* Interaction states
----------------------------------*/
.ui-state-default, .ui-widget-content .ui-state-default, .ui-widget-header .ui-state-default { border: 1px solid #d3d3d3; background: #e6e6e6 url(/s/img/ui-bg_glass_75_e6e6e6_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #555555; }
.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #555555; text-decoration: none; }
.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-widget-header .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus, .ui-widget-header .ui-state-focus { border: 1px solid #999999; background: #dadada url(/s/img/ui-bg_glass_75_dadada_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-hover a, .ui-state-hover a:hover { color: #212121; text-decoration: none; }
.ui-state-active, .ui-widget-content .ui-state-active, .ui-widget-header .ui-state-active { border: 1px solid #aaaaaa; background: #ffffff url(/s/img/ui-bg_glass_65_ffffff_1x400.png) 50% 50% repeat-x; font-weight: normal; color: #212121; }
.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #212121; text-decoration: none; }
.ui-widget :active { outline: none; }
/* Interaction Cues
----------------------------------*/
.ui-state-highlight, .ui-widget-content .ui-state-highlight, .ui-widget-header .ui-state-highlight {border: 1px solid #fcefa1; background: #fbf9ee url(/s/img/ui-bg_glass_55_fbf9ee_1x400.png) 50% 50% repeat-x; color: #363636; }
.ui-state-highlight a, .ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a { color: #363636; }
.ui-state-error, .ui-widget-content .ui-state-error, .ui-widget-header .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(/s/img/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; }
.ui-state-error a, .ui-widget-content .ui-state-error a, .ui-widget-header .ui-state-error a { color: #cd0a0a; }
.ui-state-error-text, .ui-widget-content .ui-state-error-text, .ui-widget-header .ui-state-error-text { color: #cd0a0a; }
.ui-priority-primary, .ui-widget-content .ui-priority-primary, .ui-widget-header .ui-priority-primary { font-weight: bold; }
.ui-priority-secondary, .ui-widget-content .ui-priority-secondary, .ui-widget-header .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; }
.ui-state-disabled, .ui-widget-content .ui-state-disabled, .ui-widget-header .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; }
/* Icons
----------------------------------*/
/* states and images */
.ui-icon { width: 16px; height: 16px; background-image: url(/s/img/ui-icons_222222_256x240.png); }
.ui-widget-content .ui-icon {background-image: url(/s/img/ui-icons_222222_256x240.png); }
.ui-widget-header .ui-icon {background-image: url(/s/img/ui-icons_222222_256x240.png); }
.ui-state-default .ui-icon { background-image: url(/s/img/ui-icons_888888_256x240.png); }
.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(/s/img/ui-icons_454545_256x240.png); }
.ui-state-active .ui-icon {background-image: url(/s/img/ui-icons_454545_256x240.png); }
.ui-state-highlight .ui-icon {background-image: url(/s/img/ui-icons_2e83ff_256x240.png); }
.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(/s/img/ui-icons_cd0a0a_256x240.png); }
/* positioning */
.ui-icon-carat-1-n { background-position: 0 0; }
.ui-icon-carat-1-ne { background-position: -16px 0; }
.ui-icon-carat-1-e { background-position: -32px 0; }
.ui-icon-carat-1-se { background-position: -48px 0; }
.ui-icon-carat-1-s { background-position: -64px 0; }
.ui-icon-carat-1-sw { background-position: -80px 0; }
.ui-icon-carat-1-w { background-position: -96px 0; }
.ui-icon-carat-1-nw { background-position: -112px 0; }
.ui-icon-carat-2-n-s { background-position: -128px 0; }
.ui-icon-carat-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -64px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -64px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 0 -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-off { background-position: -96px -144px; }
.ui-icon-radio-on { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all, .ui-corner-top, .ui-corner-left, .ui-corner-tl { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; -khtml-border-top-left-radius: 4px; border-top-left-radius: 4px; }
.ui-corner-all, .ui-corner-top, .ui-corner-right, .ui-corner-tr { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; -khtml-border-top-right-radius: 4px; border-top-right-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-left, .ui-corner-bl { -moz-border-radius-bottomleft: 4px; -webkit-border-bottom-left-radius: 4px; -khtml-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; }
.ui-corner-all, .ui-corner-bottom, .ui-corner-right, .ui-corner-br { -moz-border-radius-bottomright: 4px; -webkit-border-bottom-right-radius: 4px; -khtml-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; }
/* Overlays */
.ui-widget-overlay { background: #aaaaaa url(/s/img/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); }
.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(/s/img/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -khtml-border-radius: 8px; -webkit-border-radius: 8px; border-radius: 8px; }/*!
* jQuery UI Resizable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Resizable#theming
*/
.ui-resizable { position: relative;}
.ui-resizable-handle { position: absolute;font-size: 0.1px; display: block; }
.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; }
.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0; }
.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0; }
.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0; height: 100%; }
.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0; height: 100%; }
.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; }
.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; }
.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; }
.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/*!
* jQuery UI Selectable 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Selectable#theming
*/
.ui-selectable-helper { position: absolute; z-index: 100; border:1px dotted black; }
/*!
* jQuery UI Accordion 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Accordion#theming
*/
/* IE/Win - Fix animation bug - #4615 */
.ui-accordion { width: 100%; }
.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; }
.ui-accordion .ui-accordion-li-fix { display: inline; }
.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; }
.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em .7em; }
.ui-accordion-icons .ui-accordion-header a { padding-left: 2.2em; }
.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; }
.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; zoom: 1; }
.ui-accordion .ui-accordion-content-active { display: block; }
/*!
* jQuery UI Autocomplete 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Autocomplete#theming
*/
.ui-autocomplete { position: absolute; cursor: default; }
/* workarounds */
* html .ui-autocomplete { width:1px; } /* without this, the menu expands to 100% in IE6 */
/*
* jQuery UI Menu 1.8.23
*
* Copyright 2010, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Menu#theming
*/
.ui-menu {
list-style:none;
padding: 2px;
margin: 0;
display:block;
float: left;
}
.ui-menu .ui-menu {
margin-top: -3px;
}
.ui-menu .ui-menu-item {
margin:0;
padding: 0;
zoom: 1;
float: left;
clear: left;
width: 100%;
}
.ui-menu .ui-menu-item a {
text-decoration:none;
display:block;
padding:.2em .4em;
line-height:1.5;
zoom:1;
}
.ui-menu .ui-menu-item a.ui-state-hover,
.ui-menu .ui-menu-item a.ui-state-active {
font-weight: normal;
margin: -1px;
}
/*!
* jQuery UI Button 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Button#theming
*/
.ui-button { display: inline-block; position: relative; padding: 0; margin-right: .1em; text-decoration: none !important; cursor: pointer; text-align: center; zoom: 1; overflow: visible; } /* the overflow property removes extra width in IE */
.ui-button-icon-only { width: 2.2em; } /* to make room for the icon, a width needs to be set here */
button.ui-button-icon-only { width: 2.4em; } /* button elements seem to need a little more width */
.ui-button-icons-only { width: 3.4em; }
button.ui-button-icons-only { width: 3.7em; }
/*button text element */
.ui-button .ui-button-text { display: block; line-height: 1.4; }
.ui-button-text-only .ui-button-text { padding: .4em 1em; }
.ui-button-icon-only .ui-button-text, .ui-button-icons-only .ui-button-text { padding: .4em; text-indent: -9999999px; }
.ui-button-text-icon-primary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 1em .4em 2.1em; }
.ui-button-text-icon-secondary .ui-button-text, .ui-button-text-icons .ui-button-text { padding: .4em 2.1em .4em 1em; }
.ui-button-text-icons .ui-button-text { padding-left: 2.1em; padding-right: 2.1em; }
/* no icon support for input elements, provide padding by default */
input.ui-button { padding: .4em 1em; }
/*button icon element(s) */
.ui-button-icon-only .ui-icon, .ui-button-text-icon-primary .ui-icon, .ui-button-text-icon-secondary .ui-icon, .ui-button-text-icons .ui-icon, .ui-button-icons-only .ui-icon { position: absolute; top: 50%; margin-top: -8px; }
.ui-button-icon-only .ui-icon { left: 50%; margin-left: -8px; }
.ui-button-text-icon-primary .ui-button-icon-primary, .ui-button-text-icons .ui-button-icon-primary, .ui-button-icons-only .ui-button-icon-primary { left: .5em; }
.ui-button-text-icon-secondary .ui-button-icon-secondary, .ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
.ui-button-text-icons .ui-button-icon-secondary, .ui-button-icons-only .ui-button-icon-secondary { right: .5em; }
/*button sets*/
.ui-buttonset { margin-right: 7px; }
.ui-buttonset .ui-button { margin-left: 0; margin-right: -.3em; }
/* workarounds */
button.ui-button::-moz-focus-inner { border: 0; padding: 0; } /* reset extra padding in Firefox */
/*!
* jQuery UI Dialog 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Dialog#theming
*/
.ui-dialog { position: absolute; padding: .2em; width: 300px; overflow: hidden; }
.ui-dialog .ui-dialog-titlebar { padding: .4em 1em; position: relative; }
.ui-dialog .ui-dialog-title { float: left; margin: .1em 16px .1em 0; }
.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; }
.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; }
.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; }
.ui-dialog .ui-dialog-content { position: relative; border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; }
.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; }
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset { float: right; }
.ui-dialog .ui-dialog-buttonpane button { margin: .5em .4em .5em 0; cursor: pointer; }
.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; }
.ui-draggable .ui-dialog-titlebar { cursor: move; }
/*!
* jQuery UI Slider 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Slider#theming
*/
.ui-slider { position: relative; text-align: left; }
.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; }
.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; background-position: 0 0; }
.ui-slider-horizontal { height: .8em; }
.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; }
.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; }
.ui-slider-horizontal .ui-slider-range-min { left: 0; }
.ui-slider-horizontal .ui-slider-range-max { right: 0; }
.ui-slider-vertical { width: .8em; height: 100px; }
.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; }
.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; }
.ui-slider-vertical .ui-slider-range-min { bottom: 0; }
.ui-slider-vertical .ui-slider-range-max { top: 0; }/*!
* jQuery UI Tabs 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Tabs#theming
*/
.ui-tabs { position: relative; padding: .2em; zoom: 1; } /* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
.ui-tabs .ui-tabs-nav { margin: 0; padding: .2em .2em 0; }
.ui-tabs .ui-tabs-nav li { list-style: none; float: left; position: relative; top: 1px; margin: 0 .2em 1px 0; border-bottom: 0 !important; padding: 0; white-space: nowrap; }
.ui-tabs .ui-tabs-nav li a { float: left; padding: .5em 1em; text-decoration: none; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected { margin-bottom: 0; padding-bottom: 1px; }
.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; }
.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */
.ui-tabs .ui-tabs-panel { display: block; border-width: 0; padding: 1em 1.4em; background: none; }
.ui-tabs .ui-tabs-hide { display: none !important; }
/*!
* jQuery UI Datepicker 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Datepicker#theming
*/
.ui-datepicker { width: 17em; padding: .2em .2em 0; display: none; }
.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; }
.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; }
.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; }
.ui-datepicker .ui-datepicker-prev { left:2px; }
.ui-datepicker .ui-datepicker-next { right:2px; }
.ui-datepicker .ui-datepicker-prev-hover { left:1px; }
.ui-datepicker .ui-datepicker-next-hover { right:1px; }
.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; }
.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; }
.ui-datepicker .ui-datepicker-title select { font-size:1em; margin:1px 0; }
.ui-datepicker select.ui-datepicker-month-year {width: 100%;}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year { width: 49%;}
.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; }
.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; }
.ui-datepicker td { border: 0; padding: 1px; }
.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; }
.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; }
.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; }
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; }
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi { width:auto; }
.ui-datepicker-multi .ui-datepicker-group { float:left; }
.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; }
.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; }
.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; }
.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; }
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; }
.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; }
.ui-datepicker-row-break { clear:both; width:100%; font-size:0em; }
/* RTL support */
.ui-datepicker-rtl { direction: rtl; }
.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; }
.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; }
.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; }
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; }
.ui-datepicker-rtl .ui-datepicker-group { float:right; }
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; }
/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */
.ui-datepicker-cover {
position: absolute; /*must have*/
z-index: -1; /*must have*/
filter: mask(); /*must have*/
top: -4px; /*must have*/
left: -4px; /*must have*/
width: 200px; /*must have*/
height: 200px; /*must have*/
}/*!
* jQuery UI Progressbar 1.8.23
*
* Copyright 2012, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI/Progressbar#theming
*/
.ui-progressbar { height:2em; text-align: left; overflow: hidden; }
.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }

View File

@@ -5,9 +5,11 @@
height : 1000px;
}
.hidden {
display: none;
.comment[placeholder] {
width: 400px;
color: #ccc;
}
.mc-main-nav {
width : 170px;
border-right : 1px solid #e6e6e6;
@@ -19,6 +21,10 @@ display: none;
color: navy;
}
.hidden {
display: none;
}
.mc-profile-pic {
width : 140px;
height : 125px;

View File

@@ -1,5 +1,6 @@
$(function() {
$(document).ready(function() {
$('#edprf').unbind().live('click', function() {
$.get('/m/profile/edit', {}, function(data) {
$('#mcnt').html(data);
@@ -31,5 +32,69 @@ $(function() {
}, function(){
$(this).animate({height:'0px'},{queue:false,duration:200});
});
$('.comment').keyup(function(e) {
var code = (e.keyCode ? e.keyCode : e.which);
ctx = $(this);
if(code == 13)
{
ctx.parent().parent().find('.hidden').removeClass('hidden').find('span').html('Just now');
var text = ctx.val();
ctx.replaceWith(text)
}
});
$('.comment').live('focus', function() {
ctx = $(this);
if (ctx.val() == '')
{
ctx.attr('placeholder', '')
ctx.css('color', '#000')
}
});
$('.comment').live('blur', function(e) {
ctx = $(this);
if (ctx.val() == '')
{
ctx.attr('placeholder', 'Type something')
ctx.css('color', '#ccc')
}
});
var Member = Backbone.Model.extend({});
var MemberList = Backbone.Collection.extend({
model: Member,
url: '/api/members/?format=json',
parse: function(response) {
return response;
}
});
var SelectionView = Backbone.View.extend({
el : $('#user-selection'),
render: function() {
window.location = '/' + this.model.get('username')
return this;
},
});
var members = new MemberList();
members.fetch({async: false});
var fns = members.pluck("fullname");
$("#topsearch").autocomplete({
source : fns,
minLength : 2,
select: function(event, ui){
var selectedModel = members.where({fullname: ui.item.value})[0];
var view = new SelectionView({model: selectedModel});
view.render();
}
});
});

View File

@@ -0,0 +1,104 @@
(function($, _, Backbone) {
Backbone.Tastypie = {
defaultLimit: 20
};
Backbone.Tastypie.Model = Backbone.Model.extend({
idAttribute: 'resource_uri',
url: function() {
var url = getValue(this, 'urlRoot') || getValue(this.collection, 'urlRoot') || urlError();
if (this.isNew())
return url;
return this.get('resource_uri');
},
_getId: function() {
if (this.has('id'))
return this.get('id');
return _.chain(this.get('resource_uri').split('/')).compact().last().value();
}
});
Backbone.Tastypie.Collection = Backbone.Collection.extend({
constructor: function(models, options) {
Backbone.Collection.prototype.constructor.apply(this, arguments);
this.meta = {};
this.filters = {
limit: Backbone.Tastypie.defaultLimit,
offset: 0
};
if (options && options.filters)
_.extend(this.filters, options.filters);
},
url: function(models) {
var url = this.urlRoot;
if (models) {
var ids = _.map(models, function(model) {
return model._getId();
});
url += 'set/' + ids.join(';') + '/';
}
return url + this._getQueryString();
},
parse: function(response) {
if (response && response.meta)
this.meta = response.meta;
return response && response.objects;
},
fetchNext: function(options) {
options = options || {};
options.add = true;
this.filters.limit = this.meta.limit;
this.filters.offset = this.meta.offset + this.meta.limit;
if (this.filters.offset > this.meta.total_count)
this.filters.offset = this.meta.total_count;
return this.fetch.call(this, options);
},
fetchPrevious: function(options) {
options = options || {};
options.add = true;
options.at = 0;
this.filters.limit = this.meta.limit;
this.filters.offset = this.meta.offset - this.meta.limit;
if (this.filters.offset < 0){
this.filters.limit += this.filters.offset;
this.filters.offset = 0;
}
return this.fetch.call(this, options);
},
_getQueryString: function() {
if (!this.filters)
return '';
return '?' + $.param(this.filters);
}
});
// Helper function from Backbone to get a value from a Backbone
// object as a property or as a function.
var getValue = function(object, prop) {
if ((object && object[prop]))
return _.isFunction(object[prop]) ? object[prop]() : object[prop];
};
// Helper function from Backbone that raises error when a model's
// url cannot be determined.
var urlError = function() {
throw new Error('A "url" property or function must be specified');
};
})(window.$, window._, window.Backbone);

1431
bodyrep/media/js/backbone.js Normal file

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -58,12 +58,17 @@ STATIC_URL = '/static/'
PASSWORD_HASHERS = (
'django.contrib.auth.hashers.BCryptPasswordHasher',
'django.contrib.auth.hashers.SHA1PasswordHasher',
)
LOGIN_URL = '/login'
LOGOUT_URL = '/logout'
FACEBOOK_APP_ID = ''
FACEBOOK_SECRET = ''
ADMIN_MEDIA_PREFIX = '/static/admin/'
STATIC_URL = '/static/admin/'
# Additional locations of static files
STATICFILES_DIRS = (
@@ -117,6 +122,7 @@ INSTALLED_APPS = (
'django_extensions',
'django.contrib.admin',
'django.contrib.admindocs',
'tastypie',
'annoying',
'utils',
'apps',

View File

@@ -0,0 +1,30 @@
{% extends 'base.html' %}
{% block content %}
{% include 'navbar.html' %}
<h1>Signup</h1>
{% if signup_form.errors %}
{% for field, error in signup_form.errors.items %}
{{ error|safe }}
{% endfor %}
{% endif %}
<form name='signup' action="{% url signup %}" method="post" id="signup">
<div>
{{ signup_form.username.label_tag }}
{{ signup_form.username }}
</div>
<div>
{{ signup_form.password.label_tag }}
{{ signup_form.password }}
</div>
<input type="submit" class="btn btn-primary btn-mini" id='signupbtn' value="LOGIN" />
<input type="hidden" name="next" value="/m/profile" />
{% csrf_token %}
</form>
{% endblock %}

View File

@@ -1,13 +1,16 @@
<!doctype html>
<html lang="en">
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<title>test</title>
<link rel="stylesheet" href="/s/css/bootstrap.css" media="all" />
<title>BodyRep</title>
<link rel="stylesheet" href="/s/css/bootstrap.css" media="all" />
<style type="text/css">
body {
padding-top: 60px;
@@ -17,22 +20,29 @@
padding: 9px 0;
}
</style>
<link rel="stylesheet" href="/s/css/bootstrap-responsive.css" />
<link rel="stylesheet" href="/s/css/site.css" />
<link rel="stylesheet" href="/s/css/chosen.css" />
<script type="text/javascript" src="/s/js/LAB.js"></script>
<link rel="stylesheet" href="/s/css/bootstrap-responsive.css" />
<link rel="stylesheet" href="/s/css/jquery-ui.css" />
<link rel="stylesheet" href="/s/css/site.css" />
<link rel="stylesheet" href="/s/css/chosen.css" />
<script type="text/javascript" src="/s/js/LAB.js"></script>
<script type="text/javascript">
var loadb;
$LAB.script('/s/js/jquery.min.js')
.script('/s/js/jquery-ui.min.js')
.script("/s/js/application.js")
.script("/s/js/jquery.chosen.min.js")
.script("/s/js/bootstrap.js").wait(function() {
clearTimeout(loadb);
$('#loadmast').hide();
$('#mast').removeClass('hidden');
});
</script>
var loadb;
$LAB.script('/s/js/jquery.min.js')
.script('/s/js/jquery-ui.min.js')
.script("/s/js/application.js")
.script("/s/js/underscore.js")
.script("/s/js/backbone.js")
.script("/s/js/backbone-tastypie.js")
.script("/s/js/jquery.chosen.min.js")
.script("/s/js/bootstrap.js").wait(function() {
clearTimeout(loadb);
$('#loadmast').hide();
$('#mast').removeClass('hidden');
});
</script>
</head>
<body>

View File

@@ -4,5 +4,11 @@
{% block content %}
{% include "navbar.html" %}
Landing Page
<p>Landing Page</p>
<p>
<input id='test' type='button' value="Test" />
</p>
<p>
</p>
{% endblock %}

View File

@@ -0,0 +1,50 @@
{% for p in post %}
<div class="stats">
<div class="comment_block">
<div class="block_types">
<div class="block_type greenbd">
<i class="gicon-search"></i>
</div>
<div class="block_type orangebd">
<i class="gicon-screen"></i>
</div>
</div>
</div>
<div class="tnc-blurb">
<i class="icon-time"></i>
45
<i class="icon-signal"></i>
900
</div>
<div class="basic-comment">
{{ p.text }}
</div>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>{{ p.created }}</span>
</div>
{% for c in p.comment_set.all %}
<div class="user-sub-comment">
<div class="sub-avatar user2"></div>
<a>{{p.member.firstname}} {{p.member.lastname}}</a>
<p id='ctx'>{{c.text}}</p>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>{{c.created}}</span>
</div>
</div>
{% endfor %}
<div class="user-sub-comment">
<div class="sub-avatar user2"></div>
<p id='ctx'><input type='text' class='comment' placeholder='Type something' /></p>
<div class="like-comment-time hidden">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>{{c.created}}</span>
</div>
</div>
</div>
{% endfor %}

View File

@@ -64,212 +64,13 @@
</div>
</div>
</div>
<div class="stats">
<div class="comment_block">
<div class="block_types">
<div class="block_type redbd">
<i class="gicon-magnet"></i>
</div>
</div>
</div>
<div class="tnc-blurb">
<i class="icon-signal"></i>
565
</div>
<div class="basic-comment">
<b>Breakfast:</b><span> 30g Oats, 1x Banana, 5x Egg Whites</span>
</div>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>14 minutes ago</span>
</div>
<div class="user-sub-comment">
<div class='sub-avatar user1'></div>
<a>Brian Goff</a>
<p>Good to see you're keeping up the good work mate. Keep us posted ;)</p>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 3 at 2:05pm</span>
</div>
</div>
<div class="user-sub-comment">
<div class='sub-avatar user2'></div>
<a>Alex Zborowski</a>
<p>Well it's not easy but you do your best every day and you judge every action.</p>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 3 at 2:05pm</span>
</div>
</div>
</div>
<div class="stats">
<div class="comment_block">
<div class="block_types">
<div class="block_type greenbd">
<i class="gicon-search"></i>
</div>
<div class="block_type orangebd">
<i class="gicon-screen"></i>
</div>
</div>
</div>
<div class="tnc-blurb">
<i class="icon-time"></i>
45
<i class="icon-signal"></i>
900
</div>
<div class="basic-comment">
Workout at <a>Talisman Center</a> with <a>Brian Goff</a>
</div>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>37 minutes ago</span>
</div>
</div>
<div class="stats">
<div class="comment_block">
<div class="block_types">
<div class="block_type greenbd">
<i class="gicon-search"></i>
</div>
</div>
</div>
<div class="tnc-blurb">
<i class="icon-time"></i>
90
<i class="icon-signal"></i>
720
</div>
<div class="basic-comment">
Workout at <a>Talisman Center</a>
</div>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 4 at 7:00pm</span>
</div>
</div>
<div class="stats">
<div class="comment_block">
<div class="block_types">
<div class="block_type bluebd">
<i class="gicon-profile"></i>
</div>
</div>
</div>
<div class="tnc-blurb">
</div>
<div class="basic-comment">
You commented on <a>Brian Goff's workout</a>
</div>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 4 at 6:30pm</span>
</div>
</div>
<div class="stats">
<div class="comment_block">
<div class="block_types">
<div class="block_type purplebd">
<i class="gicon-profile"></i>
</div>
</div>
</div>
<div class="tnc-blurb">
</div>
<div class="basic-comment">
Your read <a>"Fatigue Recovery & Supercompensation Theory"</a>
</div>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 2 at 8:00am</span>
</div>
</div>
<div class="stats">
<div class="comment_block">
<div class="block_types">
<div class="block_type greenbd">
<i class="gicon-search"></i>
</div>
<div class="block_type orangebd">
<i class="gicon-screen"></i>
</div>
<div class="block_type tealbd">
<i class="gicon-line"></i>
</div>
</div>
</div>
<div class="tnc-blurb">
<i class="icon-time"></i>
30
<i class="icon-signal"></i>
450
</div>
<div class="basic-comment">
<a>Workout</a> using <a>Runtracker</a> with <a>Brian Goff</a>
</div>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 2 at 6:00am</span>
</div>
</div>
<div class="stats">
<div class="comment_block">
<div class="block_types">
<div class="block_type orangebd">
<i class="gicon-screen"></i>
</div>
</div>
</div>
<div class="user-comment">
<div class='avatar user1'></div>
<a>Brian Goff</a>
<p>Hey "mate"! Want to train at the <a>Talisman</a> again tonight?</p>
</div>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 3 at 2:00pm</span>
</div>
<div class="user-sub-comment">
<div class='sub-avatar user2'></div>
<a>Alex Zborowski</a>
<p>Sorry Brian, working on the BodyREP pitch tonight.</p>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 3 at 2:05pm</span>
</div>
</div>
<div class="user-sub-comment">
<div class='sub-avatar user1'></div>
<a>Brian Goff</a>
<p>No worries "mate", maybe next time.</p>
<div class="like-comment-time">
<i class="icon-thumbs-up"></i>
<i class="icon-comment"></i>
<span>April 3 at 2:07pm</span>
</div>
</div>
</div>
{% include 'core/member/post.html' %}
</div>
<div class="span4">
<div class="hero-unit">
<h1>Hello, world!</h1>
<p>This is a template for a simple marketing or informational website. It includes a large callout called the hero unit and three supporting pieces of content. Use it as a starting point to create something more unique.</p>
<p><a class="btn btn-primary btn-large">Learn more &raquo;</a></p>
<p><a id='test' class="btn btn-primary btn-large">Learn more &raquo;</a></p>
</div>
<div class="row-fluid">
<div class="span4">

View File

@@ -5,7 +5,7 @@
<div id='banner'></div>
{% if members %}
{% for m in members %}
<p><a href='/{{m.username}}'>{{ m.firstname }} {{ m.lastname }}</a></p>
<p><a href='/p/{{m.username}}'>{{ m.firstname }} {{ m.lastname }}</a></p>
{% endfor %}
{% else %}
No members found with that keyword

View File

@@ -27,7 +27,7 @@
</ul>
</div>
<div class='offset2'>
<form class="navbar-search pull-left" id='topsearch' action="/m/search">
<form class="navbar-search pull-left" id='topsearchf' action="/m/search">
<input type="text" class="search-query span4" id="topsearch" style='height : 28px;' placeholder="Search"><span id='msg_topsearch'></span>
</form>
</div>

View File

@@ -1,40 +1,51 @@
# Django libs
from django.conf.urls.defaults import patterns, include, url
# Django
from django.conf.urls.defaults import *
from django.conf import settings
from django.contrib import admin
# Libs
from tastypie.api import Api
from apps.api.models import MemberResource, PostResource
# BR libs
from apps.core import views as coreviews
from apps.core.auth import views as authviews
from apps.core import views as core
from apps.auth import views as auth
admin.autodiscover()
tasty = Api(api_name='api')
tasty.register(MemberResource())
tasty.register(PostResource())
urlpatterns = patterns('',
# Index
url(r'^$', coreviews.index, name='index'),
url(r'^$', core.index, name='index'),
# Static
(r'^s/(?P<path>.*)$', 'django.views.static.serve',
{'document_root': settings.STATIC_ROOT}),
# User tasks
url(r'^m/profile/?$', coreviews.showUserProfile, name='showUserProfile'),
url(r'^m/profile/save/?$', coreviews.saveUserProfile, name='saveUserProfile'),
url(r'^m/profile/edit/?$', coreviews.editUserProfile, name='editUser'),
url(r'^m/profile/?$', core.showUserProfile, name='showUserProfile'),
url(r'^m/profile/save/?$', core.saveUserProfile, name='saveUserProfile'),
url(r'^m/profile/edit/?$', core.editUserProfile, name='editUser'),
url(r'^m/profile/comments/?$', core.comment, name='comment'),
url(r'^m/search/(.+)$', coreviews.search, name='search'),
url(r'^m/search/(.+)$', core.search, name='search'),
# Auth
url(r'^logout$', coreviews.logout, name='logout'),
url(r'^login$', coreviews.login, name='login'),
url(r'^dologin$', coreviews.dologin, name='dologin'),
url(r'^facebook_connect/?$', authviews.facebook_connect, name='facebook-connect'),
url(r'^logout$', auth.logout, name='logout'),
url(r'^login$', auth.login, name='login'),
url(r'^dologin$', auth.dologin, name='dologin'),
url(r'^signup$', auth.signup, name='signup'),
# Django
url(r'^admin/doc/', include('django.contrib.admindocs.urls')),
url(r'^admin/', include(admin.site.urls)),
# Member profile
url(r'^([a-zA-Z0-9]+)', coreviews.showMemberProfile, name='showMemberProfile'),
# Tasty API
url(r'^', include(tasty.urls)),
# Member profile - PUT AT BOTTOM!
url(r'^p/([a-zA-Z0-9]+)', core.showMemberProfile, name='showMemberProfile'),
url(r'^([a-zA-Z0-9]+)', core.showMemberProfile, name='showMemberProfile'),
)

View File

@@ -128,4 +128,72 @@ def render_to(template):
def is_true(value):
if value == 1:
return True
return bool(value) and isinstance(value, basestring) and value.lower() not in ('false', '0')
return bool(value) and isinstance(value, basestring) and value.lower() not in ('false', '0')
# Samuel Clay
# https://github.com/samuelclay/NewsBlur
def json_encode(data, *args, **kwargs):
"""
The main issues with django's default json serializer is that properties that
had been added to an object dynamically are being ignored (and it also has
problems with some models).
"""
def _any(data):
ret = None
# Opps, we used to check if it is of type list, but that fails
# i.e. in the case of django.newforms.utils.ErrorList, which extends
# the type "list". Oh man, that was a dumb mistake!
if hasattr(data, 'to_json'):
ret = data.to_json()
elif isinstance(data, list):
ret = _list(data)
# Same as for lists above.
elif isinstance(data, dict):
ret = _dict(data)
elif isinstance(data, Decimal):
# json.dumps() cant handle Decimal
ret = str(data)
elif isinstance(data, models.query.QuerySet):
# Actually its the same as a list ...
ret = _list(data)
elif isinstance(data, models.Model):
ret = _model(data)
# here we need to encode the string as unicode (otherwise we get utf-16 in the json-response)
elif isinstance(data, basestring):
ret = unicode(data)
# see http://code.djangoproject.com/ticket/5868
elif isinstance(data, Promise):
ret = force_unicode(data)
elif isinstance(data, datetime.datetime) or isinstance(data, datetime.date):
ret = str(data)
else:
ret = data
return ret
def _model(data):
ret = {}
# If we only have a model, we only want to encode the fields.
for f in data._meta.fields:
ret[f.attname] = _any(getattr(data, f.attname))
# And additionally encode arbitrary properties that had been added.
fields = dir(data.__class__) + ret.keys()
add_ons = [k for k in dir(data) if k not in fields]
for k in add_ons:
ret[k] = _any(getattr(data, k))
return ret
def _list(data):
ret = []
for v in data:
ret.append(_any(v))
return ret
def _dict(data):
ret = {}
for k,v in data.items():
ret[str(k)] = _any(v)
return ret
ret = _any(data)
return json.dumps(ret)