Working on home view

master
Nick Sergeant 2011-10-10 23:30:56 -04:00
parent 2ac5706f75
commit 49e67bbc59
20 changed files with 546 additions and 17 deletions

View File

@ -3,7 +3,7 @@
// Focus
*:focus {
.box-shadow(0, 0, 10px, #47B7F2);
.box-shadow(0, 0, 10px, #46CD46);
}
// Mixins
@ -73,16 +73,29 @@ header {
background: #12343D url('/media/images/header-bg.gif') top left repeat-x;
border-bottom: 1px solid #DDDDDD;
height: 66px;
position: relative;
z-index: 50;
div.inner {
background: transparent url('/media/images/header-inner-bg.png') top left no-repeat;
border-left: 1px solid rgba(229, 229, 229, .25);
height: 65px;
margin: 0 auto;
position: relative;
width: 939px;
div.shadey {
background: transparent url('/media/images/header-inner-bg.png') top left no-repeat;
height: 65px;
left: -157px;
position: absolute;
top: 0;
width: 432px;
z-index: 49;
}
h1 {
float: left;
position: relative;
z-index: 50;
a {
background: transparent url('/media/images/logo.png') top left no-repeat;
@ -94,13 +107,185 @@ header {
width: 87px;
}
}
form.search {
float: left;
padding: 17px 0 0 20px;
position: relative;
z-index: 50;
div.infield {
position: relative;
label {
color: #72979C;
cursor: text;
font: normal 12px @Helvetica;
left: 30px;
position: absolute;
top: 8px;
}
input {
background: #17484F url('/media/images/search-icon.png') top left no-repeat;
background: rgba(43, 82, 93, .5) url('/media/images/search-icon.png') 8px center no-repeat;
border: 1px solid #3A5E67;
color: #FFF;
font: normal 12px @Helvetica;
margin: 0;
padding: 7px;
padding-left: 28px;
width: 175px;
.border-radius(3px);
.inset-box-shadow(0, 1px, 0px, #1D4249);
}
}
}
nav.public {
float: left;
ul {
margin: 0;
padding: 17px 0 0 20px;
li {
display: block;
float: left;
a {
border-bottom: 2px solid transparent;
color: #FFF;
display: block;
float: left;
font: normal 14px @Helvetica;
padding: 7px;
padding-bottom: 5px;
margin-right: 20px;
text-decoration: none;
-webkit-transition: border .08s linear;
-moz-transition: border .08s linear;
-o-transition: border .08s linear;
transition: border .08s linear;
&:hover {
border-bottom: 2px solid #3A5E67;
}
&.active {
border-bottom: 2px solid #85D2DD;
}
}
}
}
}
aside.nav {
border-left: 1px solid rgba(229, 229, 229, .25);
float: right;
height: 65px;
width: 189px;
}
}
}
section.main {
border-left: 1px solid #DDDDDD;
height: 100%;
margin: 0 auto;
width: 939px;
padding-top: 30px;
position: relative;
width: 940px;
div.ruler {
background: #DDDDDD;
height: 100%;
position: fixed;
top: 0;
width: 1px;
z-index: 48;
}
div.right-y {
margin-left: 750px;
}
div.inner {
float: left;
width: 750px;
}
aside.main {
float: right;
width: 190px;
section.ad {
div.asset {
background: #FFF url('/media/images/ad.jpg') center center no-repeat;
border: 1px solid #DDDDDD;
height: 130px;
margin: 15px 15px 6px;
width: 158px;
.border-radius(3px);
}
div.meta {
color: #CCC;
font: normal 12px @Helvetica;
margin-right: 15px;
text-align: right;
text-transform: uppercase;
}
}
section.tags {
margin: 45px 15px;
h1 {
background: transparent url('/media/images/tags-icon.png') 0 0 no-repeat;
color: #3BAAF3;
font: bold 12px @Helvetica;
padding-bottom: 5px;
padding-left: 22px;
}
ul {
margin: 0 0 15px 0;
li {
margin: 6px 0 6px 22px;
}
}
a {
border-bottom: 1px solid #5AB6F4;
color: #5AB6F4;
font: normal 12px @Helvetica;
text-decoration: none;
&:hover {
border-bottom: 1px solid #2B6E9B;
color: #2B6E9B;
}
&.view-all {
font-weight: bold;
margin: 0 0 0 22px;
}
}
}
nav.footer {
margin: 45px 15px 32px;
ul {
margin: 0;
li {
background: transparent url('/media/images/api-icon.png') center left no-repeat;
margin: 6px 0 6px 0;
padding-left: 22px;
a {
border-bottom: 1px solid #C5C5C6;
color: #999;
font: bold 12px @Helvetica;
text-decoration: none;
}
&.twitter {
background: transparent url('/media/images/twitter-icon.png') 4px center no-repeat;
}
&.pro {
background: transparent url('/media/images/upgrade-icon.png') 2px center no-repeat;
}
}
}
}
}
}
// Utils

BIN
media/images/ad.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

BIN
media/images/api-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
media/images/grey-bit.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

BIN
media/images/tags-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,99 @@
/*
* jQuery Hotkeys Plugin
* Copyright 2010, John Resig
* Dual licensed under the MIT or GPL Version 2 licenses.
*
* Based upon the plugin by Tzury Bar Yochay:
* http://github.com/tzuryby/hotkeys
*
* Original idea by:
* Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
*/
(function(jQuery){
jQuery.hotkeys = {
version: "0.8",
specialKeys: {
8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del",
96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/",
112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8",
120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta"
},
shiftNums: {
"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&",
"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<",
".": ">", "/": "?", "\\": "|"
}
};
function keyHandler( handleObj ) {
// Only care when a possible input has been specified
if ( typeof handleObj.data !== "string" ) {
return;
}
var origHandler = handleObj.handler,
keys = handleObj.data.toLowerCase().split(" ");
handleObj.handler = function( event ) {
// Don't fire in text-accepting inputs that we didn't directly bind to
if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
event.target.type === "text") ) {
return;
}
// Keypress represents characters, not special keys
var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ],
character = String.fromCharCode( event.which ).toLowerCase(),
key, modif = "", possible = {};
// check combinations (alt|ctrl|shift+anything)
if ( event.altKey && special !== "alt" ) {
modif += "alt+";
}
if ( event.ctrlKey && special !== "ctrl" ) {
modif += "ctrl+";
}
// TODO: Need to make sure this works consistently across platforms
if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
modif += "meta+";
}
if ( event.shiftKey && special !== "shift" ) {
modif += "shift+";
}
if ( special ) {
possible[ modif + special ] = true;
} else {
possible[ modif + character ] = true;
possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;
// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
if ( modif === "shift+" ) {
possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
}
}
for ( var i = 0, l = keys.length; i < l; i++ ) {
if ( possible[ keys[i] ] ) {
return origHandler.apply( this, arguments );
}
}
};
}
jQuery.each([ "keydown", "keyup", "keypress" ], function() {
jQuery.event.special[ this ] = { add: keyHandler };
});
})( jQuery );

View File

@ -0,0 +1,154 @@
/**
* @license In-Field Label jQuery Plugin
* http://fuelyourcoding.com/scripts/infield.html
*
* Copyright (c) 2009-2010 Doug Neiner
* Dual licensed under the MIT and GPL licenses.
* Uses the same license as jQuery, see:
* http://docs.jquery.com/License
*
* @version 0.1.2
*/
(function ($) {
$.InFieldLabels = function (label, field, options) {
// To avoid scope issues, use 'base' instead of 'this'
// to reference this class from internal events and functions.
var base = this;
// Access to jQuery and DOM versions of each element
base.$label = $(label);
base.label = label;
base.$field = $(field);
base.field = field;
base.$label.data("InFieldLabels", base);
base.showing = true;
base.init = function () {
// Merge supplied options with default options
base.options = $.extend({}, $.InFieldLabels.defaultOptions, options);
// Check if the field is already filled in
if (base.$field.val() !== "") {
base.$label.hide();
base.showing = false;
}
base.$field.focus(function () {
base.fadeOnFocus();
}).blur(function () {
base.checkForEmpty(true);
}).bind('keydown.infieldlabel', function (e) {
// Use of a namespace (.infieldlabel) allows us to
// unbind just this method later
base.hideOnChange(e);
}).bind('paste', function (e) {
// Since you can not paste an empty string we can assume
// that the fieldis not empty and the label can be cleared.
base.setOpacity(0.0);
}).change(function (e) {
base.checkForEmpty();
}).bind('onPropertyChange', function () {
base.checkForEmpty();
});
};
// If the label is currently showing
// then fade it down to the amount
// specified in the settings
base.fadeOnFocus = function () {
if (base.showing) {
base.setOpacity(base.options.fadeOpacity);
}
};
base.setOpacity = function (opacity) {
base.$label.stop().animate({ opacity: opacity }, base.options.fadeDuration);
base.showing = (opacity > 0.0);
};
// Checks for empty as a fail safe
// set blur to true when passing from
// the blur event
base.checkForEmpty = function (blur) {
if (base.$field.val() === "") {
base.prepForShow();
base.setOpacity(blur ? 1.0 : base.options.fadeOpacity);
} else {
base.setOpacity(0.0);
}
};
base.prepForShow = function (e) {
if (!base.showing) {
// Prepare for a animate in...
base.$label.css({opacity: 0.0}).show();
// Reattach the keydown event
base.$field.bind('keydown.infieldlabel', function (e) {
base.hideOnChange(e);
});
}
};
base.hideOnChange = function (e) {
if (
(e.keyCode === 16) || // Skip Shift
(e.keyCode === 9) // Skip Tab
) {
return;
}
if (base.showing) {
base.$label.hide();
base.showing = false;
}
// Remove keydown event to save on CPU processing
base.$field.unbind('keydown.infieldlabel');
};
// Run the initialization method
base.init();
};
$.InFieldLabels.defaultOptions = {
fadeOpacity: 0.5, // Once a field has focus, how transparent should the label be
fadeDuration: 300 // How long should it take to animate from 1.0 opacity to the fadeOpacity
};
$.fn.inFieldLabels = function (options) {
return this.each(function () {
// Find input or textarea based on for= attribute
// The for attribute on the label must contain the ID
// of the input or textarea element
var for_attr = $(this).attr('for'), $field;
if (!for_attr) {
return; // Nothing to attach, since the for field wasn't used
}
// Find the referenced input or textarea element
$field = $(
"input#" + for_attr + "[type='text']," +
"input#" + for_attr + "[type='search']," +
"input#" + for_attr + "[type='tel']," +
"input#" + for_attr + "[type='url']," +
"input#" + for_attr + "[type='email']," +
"input#" + for_attr + "[type='password']," +
"textarea#" + for_attr
);
if ($field.length === 0) {
return; // Again, nothing to attach
}
// Only create object for input[text], input[password], or textarea
(new $.InFieldLabels(this, $field[0], options));
});
};
}(jQuery));

6
media/js/script.coffee Normal file
View File

@ -0,0 +1,6 @@
$ =>
$(document).bind('keyup', '/', -> $('input#search-query').focus() )
$('div.infield label').inFieldLabels()
false

View File

@ -1 +0,0 @@
$(function() {});

View File

@ -33,7 +33,7 @@ class PublicTagResource(ModelResource):
def dehydrate(self, bundle):
bundle.data['absolute_url'] = '/public/tag/%s/' % bundle.obj.slug
bundle.data['snipts'] = '/api/public/snipt/?tag=%d' % bundle.obj.id
#bundle.data['snipts'] = '/api/public/snipt/?tag=%d' % bundle.obj.id
bundle.data['count'] = bundle.obj.taggit_taggeditem_items.filter(
snipt__public=True).count()
return bundle

8
snipts/urls.py Normal file
View File

@ -0,0 +1,8 @@
from django.conf.urls.defaults import *
from snipts import views
urlpatterns = patterns('',
url(r'^$', views.home, name='home'),
)

View File

@ -1 +1,13 @@
# Create your views here.
from annoying.decorators import render_to
from snipts.api import PublicTagResource
@render_to('home.html')
def home(request):
tr = PublicTagResource()
tags_queryset = tr.cached_obj_get_list()[:20]
tags_bundles = (tr.build_bundle(request=request, obj=tag) for tag in tags_queryset)
tags = [tr.full_dehydrate(bundle) for bundle in tags_bundles]
return {
'tags': tags
}

View File

@ -19,7 +19,10 @@
{% compress js %}
<script type="text/javascript" src="/media/js/jquery.js"></script>
<script type="text/javascript" src="/media/js/script.js"></script>
<script type="text/javascript" src="/media/js/jquery.infieldlabel.js"></script>
<script type="text/javascript" src="/media/js/jquery.hotkeys.js"></script>
<script type="text/javascript" src="/media/js/coffee-script.js"></script>
<script type="text/coffeescript" src="/media/js/script.coffee"></script>
{% if debug %}
<script type="text/javascript" src="/media/js/less.js"></script>
{% endif %}
@ -43,12 +46,73 @@
<header>
<div class="inner">
<div class="shadey"></div>
<h1><a href="/">Snipt</a></h1>
<form class="search" action="/public/search/" method="get">
<fieldset>
<div class="fields infield">
<label for="search-query">Search public snipts</label>
<input type="text" id="search-query" name="q" value="" />
</div>
</fieldset>
</form>
<nav class="public">
<ul>
<li>
<a href="/" class="active">Public snipts</a>
</li>
{% if not request.user.is_authenticated %}
<li>
<a href="/login/">Log in</a>
</li>
<li>
<a href="/signup/">Sign up</a>
</li>
{% endif %}
</ul>
</nav>
<aside class="nav"></aside>
</div>
</header>
<section class="main">
{% block content %}{% endblock %}
<section class="main group">
<div class="inner">
{% block content %}{% endblock %}
</div>
<div class="left-y ruler"></div>
<div class="right-y ruler"></div>
<aside class="main">
<section class="ad">
<div class="asset"></div>
<div class="meta">
Ads by Carbon
</div>
</section>
<section class="tags">
<h1>Popular public tags</h1>
<ul>
{% for tag in tags %}
<li>
<a href="{{ tag.data.absolute_url }}">{{ tag.data.name }} ({{ tag.data.count }})</a>
</li>
{% endfor %}
</ul>
<a href="/public/tags/" class="view-all">View all &raquo;</a>
</section>
<nav class="footer">
<ul>
<li class="api">
<a href="/api/">API</a>
</li>
<li class="twitter">
<a href="https://twitter.com/#!/snipt">@snipt</a>
</li>
<li class="pro">
<a href="/pro/">Go Pro</a>
</li>
</ul>
</nav>
</aside>
</section>
{% if not debug %}

View File

@ -3,7 +3,6 @@ from django.views.generic.simple import direct_to_template
from django.conf.urls.defaults import *
from django.contrib import admin
from tastypie.api import Api
from views import home
admin.autodiscover()
@ -22,5 +21,5 @@ urlpatterns = patterns('',
url(r'^api/', include(public_api.urls)),
url(r'^$', home),
url(r'^', include('snipts.urls')),
)

View File

@ -1,5 +0,0 @@
from annoying.decorators import render_to
@render_to('home.html')
def home(request):
return {}