Added lawnchair to list of working utilities, and am adding the editor.

This commit is contained in:
Elf M. Sternberg 2012-07-15 10:53:33 -07:00
parent de33547e83
commit f4090dd0d2
7 changed files with 819 additions and 146 deletions

View File

@ -91,12 +91,9 @@ module.exports = (grunt) ->
install:
src: [
"src/index.html"
"src/priority.js"
"src/*_tmpl.js"
"src/style.css"
"libs/jquery/jquery-1.7.2.js"
"libs/require.js"
"libs/lawnchair/lawnchair.js"
]
dest: "dist"
@ -106,7 +103,7 @@ module.exports = (grunt) ->
uglify: {}
grunt.registerTask "default", "coffee:dev recess:dev haml:dev hamltojs:dev"
grunt.registerTask "default", "coffee:dev recess:dev haml:dev hamltojs:dev install"
# _ _ _ __ __ _ _ _ _ _____ __ __ _
# | || | /_\ | \/ | | | |_ ___ | || |_ _| \/ | |
@ -143,7 +140,7 @@ module.exports = (grunt) ->
grunt.registerHelper "templatize", (src, dest, done) ->
file = grunt.file.read(src)
out = path.basename(src, ".html")
grunt.file.write path.join(dest, out + ".js"), "define(" + _und.template(file).source + ");"
grunt.file.write path.join(dest, out + ".js"), "define(function() { return " + _und.template(result.stdout).source + "});"
done()
grunt.registerMultiTask "templatize", "Compile Underscored HTML to Javascript", ->
@ -169,7 +166,7 @@ module.exports = (grunt) ->
grunt.utils.spawn args, (err, result) ->
console.log err if err
out = path.basename(src, ".haml")
grunt.file.write path.join(dest, out + ".js"), "define(" + _und.template(result.stdout).source + ");"
grunt.file.write path.join(dest, out + ".js"), "define(function() { return " + _und.template(result.stdout).source + "});"
done()
grunt.registerMultiTask "hamltojs", "Compile Underscored HAML to Javascript", ->

View File

@ -111,7 +111,7 @@ module.exports = function(grunt) {
findNestedDependencies: true
},
install: {
src: ["src/index.html", "src/priority.js", "src/*_tmpl.js", "src/style.css", "libs/jquery/jquery-1.7.2.js", "libs/require.js"],
src: ["libs/jquery/jquery-1.7.2.js", "libs/require.js", "libs/lawnchair/lawnchair.js"],
dest: "dist"
},
mocha: {
@ -119,7 +119,7 @@ module.exports = function(grunt) {
},
uglify: {}
});
grunt.registerTask("default", "coffee:dev recess:dev haml:dev hamltojs:dev");
grunt.registerTask("default", "coffee:dev recess:dev haml:dev hamltojs:dev install");
grunt.registerHelper("haml", function(src, dest, done) {
var args;
args = {
@ -149,7 +149,7 @@ module.exports = function(grunt) {
var file, out;
file = grunt.file.read(src);
out = path.basename(src, ".html");
grunt.file.write(path.join(dest, out + ".js"), "define(" + _und.template(file).source + ");");
grunt.file.write(path.join(dest, out + ".js"), "define(function() { return " + _und.template(result.stdout).source + "});");
return done();
});
grunt.registerMultiTask("templatize", "Compile Underscored HTML to Javascript", function() {
@ -176,7 +176,7 @@ module.exports = function(grunt) {
console.log(err);
}
out = path.basename(src, ".haml");
grunt.file.write(path.join(dest, out + ".js"), "define(" + _und.template(result.stdout).source + ");");
grunt.file.write(path.join(dest, out + ".js"), "define(function() { return " + _und.template(result.stdout).source + "});");
return done();
});
});

438
libs/lawnchair/lawnchair.js Normal file
View File

@ -0,0 +1,438 @@
/**
* Lawnchair!
* ---
* clientside json store
*
*/
var Lawnchair = function (options, callback) {
// ensure Lawnchair was called as a constructor
if (!(this instanceof Lawnchair)) return new Lawnchair(options, callback);
// lawnchair requires json
if (!JSON) throw 'JSON unavailable! Include http://www.json.org/json2.js to fix.'
// options are optional; callback is not
if (arguments.length <= 2 && arguments.length > 0) {
callback = (typeof arguments[0] === 'function') ? arguments[0] : arguments[1];
options = (typeof arguments[0] === 'function') ? {} : arguments[0];
} else {
throw 'Incorrect # of ctor args!'
}
// TODO perhaps allow for pub/sub instead?
if (typeof callback !== 'function') throw 'No callback was provided';
// default configuration
this.record = options.record || 'record' // default for records
this.name = options.name || 'records' // default name for underlying store
// mixin first valid adapter
var adapter
// if the adapter is passed in we try to load that only
if (options.adapter) {
for (var i = 0, l = Lawnchair.adapters.length; i < l; i++) {
if (Lawnchair.adapters[i].adapter === options.adapter) {
adapter = Lawnchair.adapters[i].valid() ? Lawnchair.adapters[i] : undefined;
break;
}
}
// otherwise find the first valid adapter for this env
}
else {
for (var i = 0, l = Lawnchair.adapters.length; i < l; i++) {
adapter = Lawnchair.adapters[i].valid() ? Lawnchair.adapters[i] : undefined
if (adapter) break
}
}
// we have failed
if (!adapter) throw 'No valid adapter.'
// yay! mixin the adapter
for (var j in adapter)
this[j] = adapter[j]
// call init for each mixed in plugin
for (var i = 0, l = Lawnchair.plugins.length; i < l; i++)
Lawnchair.plugins[i].call(this)
// init the adapter
this.init(options, callback)
}
Lawnchair.adapters = []
/**
* queues an adapter for mixin
* ===
* - ensures an adapter conforms to a specific interface
*
*/
Lawnchair.adapter = function (id, obj) {
// add the adapter id to the adapter obj
// ugly here for a cleaner dsl for implementing adapters
obj['adapter'] = id
// methods required to implement a lawnchair adapter
var implementing = 'adapter valid init keys save batch get exists all remove nuke'.split(' ')
, indexOf = this.prototype.indexOf
// mix in the adapter
for (var i in obj) {
if (indexOf(implementing, i) === -1) throw 'Invalid adapter! Nonstandard method: ' + i
}
// if we made it this far the adapter interface is valid
// insert the new adapter as the preferred adapter
Lawnchair.adapters.splice(0,0,obj)
}
Lawnchair.plugins = []
/**
* generic shallow extension for plugins
* ===
* - if an init method is found it registers it to be called when the lawnchair is inited
* - yes we could use hasOwnProp but nobody here is an asshole
*/
Lawnchair.plugin = function (obj) {
for (var i in obj)
i === 'init' ? Lawnchair.plugins.push(obj[i]) : this.prototype[i] = obj[i]
}
/**
* helpers
*
*/
Lawnchair.prototype = {
isArray: Array.isArray || function(o) { return Object.prototype.toString.call(o) === '[object Array]' },
/**
* this code exists for ie8... for more background see:
* http://www.flickr.com/photos/westcoastlogic/5955365742/in/photostream
*/
indexOf: function(ary, item, i, l) {
if (ary.indexOf) return ary.indexOf(item)
for (i = 0, l = ary.length; i < l; i++) if (ary[i] === item) return i
return -1
},
// awesome shorthand callbacks as strings. this is shameless theft from dojo.
lambda: function (callback) {
return this.fn(this.record, callback)
},
// first stab at named parameters for terse callbacks; dojo: first != best // ;D
fn: function (name, callback) {
return typeof callback == 'string' ? new Function(name, callback) : callback
},
// returns a unique identifier (by way of Backbone.localStorage.js)
// TODO investigate smaller UUIDs to cut on storage cost
uuid: function () {
var S4 = function () {
return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}
return (S4()+S4()+"-"+S4()+"-"+S4()+"-"+S4()+"-"+S4()+S4()+S4());
},
// a classic iterator
each: function (callback) {
var cb = this.lambda(callback)
// iterate from chain
if (this.__results) {
for (var i = 0, l = this.__results.length; i < l; i++) cb.call(this, this.__results[i], i)
}
// otherwise iterate the entire collection
else {
this.all(function(r) {
for (var i = 0, l = r.length; i < l; i++) cb.call(this, r[i], i)
})
}
return this
}
// --
};
// window.name code courtesy Remy Sharp: http://24ways.org/2009/breaking-out-the-edges-of-the-browser
Lawnchair.adapter('window-name', (function(index, store) {
if (typeof window==='undefined') {
window = { top: { } }; // node/optimizer compatibility
}
var data = window.top.name ? JSON.parse(window.top.name) : {}
return {
valid: function () {
return typeof window.top.name != 'undefined'
},
init: function (options, callback) {
data[this.name] = data[this.name] || {index:[],store:{}}
index = data[this.name].index
store = data[this.name].store
this.fn(this.name, callback).call(this, this)
},
keys: function (callback) {
this.fn('keys', callback).call(this, index)
return this
},
save: function (obj, cb) {
// data[key] = value + ''; // force to string
// window.top.name = JSON.stringify(data);
var key = obj.key || this.uuid()
this.exists(key, function(exists) {
if (!exists) {
if (obj.key) delete obj.key
index.push(key)
}
store[key] = obj
window.top.name = JSON.stringify(data) // TODO wow, this is the only diff from the memory adapter
if (cb) {
obj.key = key
this.lambda(cb).call(this, obj)
}
})
return this
},
batch: function (objs, cb) {
var r = []
for (var i = 0, l = objs.length; i < l; i++) {
this.save(objs[i], function(record) {
r.push(record)
})
}
if (cb) this.lambda(cb).call(this, r)
return this
},
get: function (keyOrArray, cb) {
var r;
if (this.isArray(keyOrArray)) {
r = []
for (var i = 0, l = keyOrArray.length; i < l; i++) {
r.push(store[keyOrArray[i]])
}
} else {
r = store[keyOrArray]
if (r) r.key = keyOrArray
}
if (cb) this.lambda(cb).call(this, r)
return this
},
exists: function (key, cb) {
this.lambda(cb).call(this, !!(store[key]))
return this
},
all: function (cb) {
var r = []
for (var i = 0, l = index.length; i < l; i++) {
var obj = store[index[i]]
obj.key = index[i]
r.push(obj)
}
this.fn(this.name, cb).call(this, r)
return this
},
remove: function (keyOrArray, cb) {
var del = this.isArray(keyOrArray) ? keyOrArray : [keyOrArray]
for (var i = 0, l = del.length; i < l; i++) {
delete store[del[i]]
index.splice(this.indexOf(index, del[i]), 1)
}
window.top.name = JSON.stringify(data)
if (cb) this.lambda(cb).call(this)
return this
},
nuke: function (cb) {
store = {}
index = []
window.top.name = JSON.stringify(data)
if (cb) this.lambda(cb).call(this)
return this
}
}
/////
})())
/**
* dom storage adapter
* ===
* - originally authored by Joseph Pecoraro
*
*/
//
// TODO does it make sense to be chainable all over the place?
// chainable: nuke, remove, all, get, save, all
// not chainable: valid, keys
//
Lawnchair.adapter('dom', (function() {
var storage = window.localStorage
// the indexer is an encapsulation of the helpers needed to keep an ordered index of the keys
var indexer = function(name) {
return {
// the key
key: name + '._index_',
// returns the index
all: function() {
var a = storage.getItem(this.key)
if (a) {
a = JSON.parse(a)
}
if (a === null) storage.setItem(this.key, JSON.stringify([])) // lazy init
return JSON.parse(storage.getItem(this.key))
},
// adds a key to the index
add: function (key) {
var a = this.all()
a.push(key)
storage.setItem(this.key, JSON.stringify(a))
},
// deletes a key from the index
del: function (key) {
var a = this.all(), r = []
// FIXME this is crazy inefficient but I'm in a strata meeting and half concentrating
for (var i = 0, l = a.length; i < l; i++) {
if (a[i] != key) r.push(a[i])
}
storage.setItem(this.key, JSON.stringify(r))
},
// returns index for a key
find: function (key) {
var a = this.all()
for (var i = 0, l = a.length; i < l; i++) {
if (key === a[i]) return i
}
return false
}
}
}
// adapter api
return {
// ensure we are in an env with localStorage
valid: function () {
return !!storage && function() {
// in mobile safari if safe browsing is enabled, window.storage
// is defined but setItem calls throw exceptions.
var success = true
var value = Math.random()
try {
storage.setItem(value, value)
} catch (e) {
success = false
}
storage.removeItem(value)
return success
}()
},
init: function (options, callback) {
this.indexer = indexer(this.name)
if (callback) this.fn(this.name, callback).call(this, this)
},
save: function (obj, callback) {
var key = obj.key ? this.name + '.' + obj.key : this.name + '.' + this.uuid()
// if the key is not in the index push it on
if (this.indexer.find(key) === false) this.indexer.add(key)
// now we kil the key and use it in the store colleciton
delete obj.key;
storage.setItem(key, JSON.stringify(obj))
obj.key = key.slice(this.name.length + 1)
if (callback) {
this.lambda(callback).call(this, obj)
}
return this
},
batch: function (ary, callback) {
var saved = []
// not particularily efficient but this is more for sqlite situations
for (var i = 0, l = ary.length; i < l; i++) {
this.save(ary[i], function(r){
saved.push(r)
})
}
if (callback) this.lambda(callback).call(this, saved)
return this
},
// accepts [options], callback
keys: function(callback) {
if (callback) {
var name = this.name
, keys = this.indexer.all().map(function(r){ return r.replace(name + '.', '') })
this.fn('keys', callback).call(this, keys)
}
return this // TODO options for limit/offset, return promise
},
get: function (key, callback) {
if (this.isArray(key)) {
var r = []
for (var i = 0, l = key.length; i < l; i++) {
var k = this.name + '.' + key[i]
var obj = storage.getItem(k)
if (obj) {
obj = JSON.parse(obj)
obj.key = key[i]
r.push(obj)
}
}
if (callback) this.lambda(callback).call(this, r)
} else {
var k = this.name + '.' + key
var obj = storage.getItem(k)
if (obj) {
obj = JSON.parse(obj)
obj.key = key
}
if (callback) this.lambda(callback).call(this, obj)
}
return this
},
exists: function (key, cb) {
var exists = this.indexer.find(this.name+'.'+key) === false ? false : true ;
this.lambda(cb).call(this, exists);
return this;
},
// NOTE adapters cannot set this.__results but plugins do
// this probably should be reviewed
all: function (callback) {
var idx = this.indexer.all()
, r = []
, o
, k
for (var i = 0, l = idx.length; i < l; i++) {
k = idx[i] //v
o = JSON.parse(storage.getItem(k))
o.key = k.replace(this.name + '.', '')
r.push(o)
}
if (callback) this.fn(this.name, callback).call(this, r)
return this
},
remove: function (keyOrObj, callback) {
var key = this.name + '.' + ((keyOrObj.key) ? keyOrObj.key : keyOrObj)
this.indexer.del(key)
storage.removeItem(key)
if (callback) this.lambda(callback).call(this)
return this
},
nuke: function (callback) {
this.all(function(r) {
for (var i = 0, l = r.length; i < l; i++) {
this.remove(r[i]);
}
if (callback) this.lambda(callback).call(this)
})
return this
}
}})());

View File

@ -0,0 +1,3 @@
.edit-priority
.input.edit-priority-field(type="text" value="<%= p.name %>" data-for="<%= p.pos %>")
.button.delete-priority-field(data-for="<%= p.pos %>")

View File

@ -12,13 +12,15 @@
%title Priority / Ignore
%body
#content
#leftbrain.column
%h1.prioritize Today I Will Pay Attention To:
#priorities
#rightbrain.column
%h1.prioritize Today I Will Ignore:
#ignorities
#grid.container
.flow
.row-fluid
#leftbrain.span6
%h1#prioritize(data-for="0") Today I Will Pay Attention To:
#priorities
#rightbrain.span6
%h1#ignorize(data-for="0") Today I Will Ignore:
#ignorities
#message(style="display:none")
%h2 How to Use

View File

@ -2,47 +2,70 @@ require.config
paths:
'jquery': 'jquery-1.7.2'
require ['jquery', 'priority_tmpl'], ($, priority_template) ->
require ['jquery', 'priority_tmpl', 'lawnchair'], ($, priority_template) ->
class Prioritize
constructor(@repo) ->
constructor: (@repo) ->
@repo.get 'priorities', (p) =>
@priorities = if p? and p.priorities? then p.priorities else []
@render()
$('body').on 'click', @render
$('#thumbsup').on 'click', () => @newPriority('priority')
$('#thumbsdn').on 'click', () => @newPriority('ignore')
$('#prioritize').on 'click', (ev) => @editPriority(ev, 'priority')
$('#ignorize').on 'click', (ev) => @editPriority(ev, 'ignore')
editPriority: (ev, ty = 'parent') =>
newPriority: (ty, ev) =>
ev.stopPropagation()
return if $('.edit-priority').length > 0
target = if ty == 'priority' then $('#priorities') else $('#ignorities')
target.append(edit_priorities_template({fur: ty}))
input = $('input.edit-priority-field', target)
maybeNewPrioritySave = (ev) =>
prioritySave = =>
@priorities.push({cat: ty, name: input.val()})
@save()
code = if ev.keyCode then ev.keyCode else ev.which
return prioritySave() if code == 13
return @cleanAndRender() if code == 27
input.on 'keyup', maybeNewPrioritySave
$('.delete-priority-field', target).on 'click', @render
input.focus()
save: ->
@repo.save {key: 'priorities', 'priorities': @priorities}, () =>
@render()
clean: ->
@priorities = ({name: p.name, cat: p.cat} for p in @priorities when c.name.trim() != "")
cleanAndRender: ->
@clean()
@render()
save: ->
@repo.save {key: 'priorities', 'priorities': @priorities}, =>
@render()
render: =>
priority_enumerate = (cat) ->
(c for c in @priorities if c.cat == cat)
priority_enumerate = (cat) =>
r = []
for i in [0...@priorities.length]
if @priorities[i].cat == cat
r.push({name: @priorities[i].name, cat: @priorities[i].cat, pos: i})
r
priority_render = (cat) ->
$('#priority_list').html(priority_template({priorities: priority_enumerate('priority')}))
$('#ignore_list').html(priority_template({priorities: priority_enumerate('ignore')}))
$('#priorities').html(priority_template({priorities: priority_enumerate('priority')}))
$('#ignorities').html(priority_template({priorities: priority_enumerate('ignore')}))
$ ->
prioritize = new Lawnchair {name: 'Prioritize'}, ->
p = this
p.save
key: 'priorities',
priorities: [
{cat: 'priority', name: 'Omaha, Stormy, Raeney'}
{cat: 'ignore', name: 'Politics'}
{cat: 'priority', name: 'Spiral Genetics'}
{cat: 'priority', name: 'Looking for Work'}
{cat: 'priority', name: 'Writing'}
{cat: 'priority', name: 'Productivity Core'}
{cat: 'priority', name: 'Story Core'}
{cat: 'ignore', name: 'Smut'}
{cat: 'ignore', name: 'Religious Arguments'}
{cat: 'ignore', name: 'PASWO'}
{cat: 'ignore', name: 'Twitter'}
], ->
handler = new Prioritize(p)
handler = new Prioritize(this)
handler.render()

View File

@ -55,41 +55,320 @@ input[type="search"]::-webkit-search-cancel-button {
}
* {
border: 0;
margin: 0;
padding: 0;
}
body {
font: 13pt/190% Calibri,Georgia,"Lucida Bright",Lucidabright,"Bitstream Vera Serif",serif;
font: 13pt/190% Montserrat,Calibri,Georgia,"Lucida Bright",Lucidabright,"Bitstream Vera Serif",serif;
background-color: #fff;
}
body {
margin: .25in .75in .25in 1.5in;
}
.clearoncolumn {
clear: none;
.clearfix {
*zoom: 1;
&:before,
&:after {
display: table;
content: "";
}
&:after {
clear: both;
}
}
@media only screen and (min-width: 480px) {
body {
margin: .25in .75in .25in 1.5in;
}
.clearoncolumn {
clear: none;
}
// Block level inputs
.input-block-level {
display: block;
width: 100%;
min-height: 28px; // Make inputs at least the height of their button counterpart
.box-sizing(border-box); // Makes inputs behave like true block-level elements
}
@media only screen and (max-width: 479px) {
body {
margin: 2% 2% 0 6%;
// GRID
// --------------------------------------------------
// Default 940px grid
// -------------------------
@gridColumns: 12;
@gridColumnWidth: 60px;
@gridGutterWidth: 20px;
@gridRowWidth: (@gridColumns * @gridColumnWidth) + (@gridGutterWidth * (@gridColumns - 1));
// Fluid grid
// -------------------------
@fluidGridColumnWidth: 6.382978723%;
@fluidGridGutterWidth: 2.127659574%;
#grid {
.core (@gridColumnWidth, @gridGutterWidth) {
.spanX (@index) when (@index > 0) {
(~".span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.clearoncolumn {
clear: both;
.spanX (0) {}
.offsetX (@index) when (@index > 0) {
(~".offset@{index}") { .offset(@index); }
.offsetX(@index - 1);
}
.offsetX (0) {}
.offset (@columns) {
margin-left: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns + 1));
}
.span (@columns) {
width: (@gridColumnWidth * @columns) + (@gridGutterWidth * (@columns - 1));
}
.row {
margin-left: @gridGutterWidth * -1;
.clearfix();
}
[class*="span"] {
float: left;
margin-left: @gridGutterWidth;
}
// Set the container width, and override it for fixed navbars in media queries
.container,
.navbar-fixed-top .container,
.navbar-fixed-bottom .container { .span(@gridColumns); }
// generate .spanX and .offsetX
.spanX (@gridColumns);
.offsetX (@gridColumns);
}
.fluid (@fluidGridColumnWidth, @fluidGridGutterWidth) {
.spanX (@index) when (@index > 0) {
(~".span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.spanX (0) {}
.span (@columns) {
width: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1));
*width: (@fluidGridColumnWidth * @columns) + (@fluidGridGutterWidth * (@columns - 1)) - (.5 / @gridRowWidth * 100 * 1%);
}
.row-fluid {
width: 100%;
.clearfix();
[class*="span"] {
.input-block-level();
float: left;
margin-left: @fluidGridGutterWidth;
*margin-left: @fluidGridGutterWidth - (.5 / @gridRowWidth * 100 * 1%);
}
[class*="span"]:first-child {
margin-left: 0;
}
// generate .spanX
.spanX (@gridColumns);
}
}
.input(@gridColumnWidth, @gridGutterWidth) {
.spanX (@index) when (@index > 0) {
(~"input.span@{index}, textarea.span@{index}, .uneditable-input.span@{index}") { .span(@index); }
.spanX(@index - 1);
}
.spanX (0) {}
.span(@columns) {
width: ((@gridColumnWidth) * @columns) + (@gridGutterWidth * (@columns - 1)) - 10;
}
input,
textarea,
.uneditable-input {
margin-left: 0; // override margin-left from core grid system
}
// generate .spanX
.spanX (@gridColumns);
}
}
@media (min-width: 768px) and (max-width: 979px) {
// Fixed grid
#grid > .core(42px, 20px);
// Fluid grid
#grid > .fluid(5.801104972%, 2.762430939%);
// Input grid
#grid > .input(42px, 20px);
// No need to reset .thumbnails here since it is the same @gridGutterWidth
}
@media (min-width: 1200px) {
// Fixed grid
#grid > .core(70px, 30px);
// Fluid grid
#grid > .fluid(5.982905983%, 2.564102564%);
// Input grid
#grid > .input(70px, 30px);
// Thumbnails
.thumbnails {
margin-left: -30px;
}
.thumbnails > li {
margin-left: 30px;
}
.row-fluid .thumbnails {
margin-left: 0;
}
}
@media (max-width: 480px) {
// Smooth out the collapsing/expanding nav
.nav-collapse {
-webkit-transform: translate3d(0, 0, 0); // activate the GPU
}
// Block level the page header small tag for readability
.page-header h1 small {
display: block;
line-height: @baseLineHeight;
}
// Update checkboxes for iOS
input[type="checkbox"],
input[type="radio"] {
border: 1px solid #ccc;
}
// Remove the horizontal form styles
.form-horizontal .control-group > label {
float: none;
width: auto;
padding-top: 0;
text-align: left;
}
.modal-header .close {
padding: 10px;
margin: -10px;
}
// Carousel
.carousel-caption {
position: static;
}
}
// LANDSCAPE PHONE TO SMALL DESKTOP & PORTRAIT TABLET
// --------------------------------------------------
@media (max-width: 767px) {
// Padding to set content in a bit
body {
padding-left: 20px;
padding-right: 20px;
}
// Negative indent the now static "fixed" navbar
.navbar-fixed-top,
.navbar-fixed-bottom {
margin-left: -20px;
margin-right: -20px;
}
// Remove padding on container given explicit padding set on body
.container-fluid {
padding: 0;
}
// TYPOGRAPHY
// ----------
// Reset horizontal dl
.dl-horizontal {
dt {
float: none;
clear: none;
width: auto;
text-align: left;
}
dd {
margin-left: 0;
}
}
// GRID & CONTAINERS
// -----------------
// Remove width from containers
.container {
width: auto;
}
// Fluid rows
.row-fluid {
width: 100%;
}
// Undo negative margin on rows and thumbnails
.row,
.thumbnails {
margin-left: 0;
}
// Make all grid-sized elements block level again
[class*="span"],
.row-fluid [class*="span"] {
float: none;
display: block;
width: auto;
margin-left: 0;
}
// FORM FIELDS
// -----------
// Make span* classes full width
.input-large,
.input-xlarge,
.input-xxlarge,
input[class*="span"],
select[class*="span"],
textarea[class*="span"],
.uneditable-input {
.input-block-level();
}
// But don't let it screw up prepend/append inputs
.input-prepend input,
.input-append input,
.input-prepend input[class*="span"],
.input-append input[class*="span"] {
display: inline-block; // redeclare so they don't wrap to new lines
width: auto;
}
}
@baseLineHeight: 18px;
// Box sizing
.box-sizing(@boxmodel) {
-webkit-box-sizing: @boxmodel;
-moz-box-sizing: @boxmodel;
-ms-box-sizing: @boxmodel;
box-sizing: @boxmodel;
}
p,li,ul {
@ -110,92 +389,23 @@ ul + p {
margin-top: 1em;
}
#content {
max-width: 732px;
}
#braindiv {
#msg {
font-size: 24px;
color: #999;
#prioritize { background: url(thumbsup.png) top left no-repeat; }
#ignorize { background: url(thumbsdown.png) top left no-repeat; }
p {
width: 7em;
font-size: 20px;
margin: -3px 0 -8px 0;
padding: 0 0 0 0;
.doing {
color: #c00;
}
}
}
}
#braindiv {
float: left;
width: 45%;
padding-right: 5%;
#img {
width: 164px;
height: 226px;
background: url(brain-in-a-jar.jpg) top right no-repeat;
padding: 0 0 1em 0;
}
}
@media only screen and (min-width: 480px) {
#braindiv {
float: left;
width: 45%;
padding-right: 5%;
#img {
width: 164px;
height: 226px;
background: url(brain-in-a-jar.jpg) top right no-repeat;
padding: 0 0 1em 0;
}
}
}
@media only screen and (max-width: 479px) {
#braindiv {
width: 100%;
#img {
float: left;
width: 37.5%;
min-width: 122px;
height: 165px;
background: url(brain-in-a-jar-sm.jpg) top right no-repeat;
padding: 0 0 1em 0;
}
#msg {
float: right;
width: 60.353125%;
}
padding-bottom: 2em;
}
}
#rightnow {
float: left;
width: 49.9%;
#grid {
margin: 0 auto;
h1 {
display: block;
float: left;
padding-bottom: 0;
min-height: 72px;
border: none;
color: #333;
font-size: 20px;
font-size: 24px;
font-weight: normal;
line-height: 1.2;
padding-left: 80px;
padding-top: 18px;
strong {
font-weight: bold;
}