diff --git a/.gitignore b/.gitignore
index f98fdf7bf9..e2340d2aa7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,6 +4,9 @@
*.swp
*.orig
*.DS_Store
+:2e_*
+:2e#
+.AppleDouble
database.sqlite
courseware/static/js/mathjax/*
db.newaskbot
diff --git a/djangoapps/courseware/capa/capa_problem.py b/djangoapps/courseware/capa/capa_problem.py
index e164429f11..f5739fd8b0 100644
--- a/djangoapps/courseware/capa/capa_problem.py
+++ b/djangoapps/courseware/capa/capa_problem.py
@@ -25,7 +25,7 @@ from mako.template import Template
from util import contextualize_text
import inputtypes
-from responsetypes import NumericalResponse, FormulaResponse, CustomResponse, SchematicResponse, MultipleChoiceResponse, StudentInputError, TrueFalseResponse, ExternalResponse,ImageResponse
+from responsetypes import NumericalResponse, FormulaResponse, CustomResponse, SchematicResponse, MultipleChoiceResponse, StudentInputError, TrueFalseResponse, ExternalResponse,ImageResponse,OptionResponse
import calc
import eia
@@ -40,8 +40,9 @@ response_types = {'numericalresponse':NumericalResponse,
'multiplechoiceresponse':MultipleChoiceResponse,
'truefalseresponse':TrueFalseResponse,
'imageresponse':ImageResponse,
+ 'optionresponse':OptionResponse,
}
-entry_types = ['textline', 'schematic', 'choicegroup','textbox','imageinput']
+entry_types = ['textline', 'schematic', 'choicegroup','textbox','imageinput','optioninput']
solution_types = ['solution'] # extra things displayed after "show answers" is pressed
response_properties = ["responseparam", "answer"] # these get captured as student responses
@@ -186,6 +187,13 @@ class LoncapaProblem(object):
if answer:
answer_map[entry.get('id')] = contextualize_text(answer, self.context)
+ # include solutions from ... stanzas
+ # Tentative merge; we should figure out how we want to handle hints and solutions
+ for entry in self.tree.xpath("//"+"|//".join(solution_types)):
+ answer = etree.tostring(entry)
+ if answer:
+ answer_map[entry.get('id')] = answer
+
return answer_map
# ======= Private ========
@@ -241,7 +249,24 @@ class LoncapaProblem(object):
if self.student_answers and problemid in self.student_answers:
value = self.student_answers[problemid]
- return getattr(inputtypes, problemtree.tag)(problemtree, value, status) #TODO
+ #### This code is a hack. It was merged to help bring two branches
+ #### in sync, but should be replaced. msg should be passed in a
+ #### response_type
+ # prepare the response message, if it exists in correct_map
+ if 'msg' in self.correct_map:
+ msg = self.correct_map['msg']
+ elif ('msg_%s' % problemid) in self.correct_map:
+ msg = self.correct_map['msg_%s' % problemid]
+ else:
+ msg = ''
+
+ #if settings.DEBUG:
+ # print "[courseware.capa.capa_problem.extract_html] msg = ",msg
+
+ # do the rendering
+ #render_function = html_special_response[problemtree.tag]
+ render_function = getattr(inputtypes, problemtree.tag)
+ return render_function(problemtree, value, status, msg) # render the special response (textline, schematic,...)
tree=Element(problemtree.tag)
for item in problemtree:
@@ -287,6 +312,7 @@ class LoncapaProblem(object):
answer_id = 1
for entry in tree.xpath("|".join(['//'+response.tag+'[@id=$id]//'+x for x in (entry_types + solution_types)]),
id=response_id_str):
+ # assign one answer_id for each entry_type or solution_type
entry.attrib['response_id'] = str(response_id)
entry.attrib['answer_id'] = str(answer_id)
entry.attrib['id'] = "%s_%i_%i"%(self.problem_id, response_id, answer_id)
diff --git a/djangoapps/courseware/capa/inputtypes.py b/djangoapps/courseware/capa/inputtypes.py
index e093a7929c..0388b35d0b 100644
--- a/djangoapps/courseware/capa/inputtypes.py
+++ b/djangoapps/courseware/capa/inputtypes.py
@@ -6,11 +6,16 @@
Module containing the problem elements which render into input objects
- textline
-- textbox (change this to textarea?)
+- textbox (change this to textarea?)
- schemmatic
+- choicegroup (for multiplechoice: checkbox, radio, or select option)
+- imageinput (for clickable image)
+- optioninput (for option list)
These are matched by *.html files templates/*.html which are mako templates with the actual html.
+Each input type takes the xml tree as 'element', the previous answer as 'value', and the graded status as 'status'
+
'''
# TODO: rename "state" to "status" for all below
@@ -18,6 +23,7 @@ These are matched by *.html files templates/*.html which are mako templates with
# but it will turn into a dict containing both the answer and any associated message for the problem ID for the input element.
import re
+import shlex # for splitting quoted strings
from django.conf import settings
@@ -27,9 +33,42 @@ from lxml import etree
from mitxmako.shortcuts import render_to_string
#-----------------------------------------------------------------------------
-#takes the xml tree as 'element', the student's previous answer as 'value', and the graded status as 'state'
-def choicegroup(element, value, state, msg=""):
+def optioninput(element, value, status, msg=''):
+ '''
+ Select option input type.
+
+ Example:
+
+ The location of the sky
+ '''
+ eid=element.get('id')
+ options = element.get('options')
+ if not options:
+ raise Exception,"[courseware.capa.inputtypes.optioninput] Missing options specification in " + etree.tostring(element)
+ oset = shlex.shlex(options[1:-1])
+ oset.quotes = "'"
+ oset.whitespace = ","
+ oset = [x[1:-1] for x in list(oset)]
+
+ # osetdict = dict([('option_%s_%s' % (eid,x),oset[x]) for x in range(len(oset)) ]) # make dict with IDs
+ osetdict = dict([(oset[x],oset[x]) for x in range(len(oset)) ]) # make dict with key,value same
+ if settings.DEBUG:
+ print '[courseware.capa.inputtypes.optioninput] osetdict=',osetdict
+
+ context={'id':eid,
+ 'value':value,
+ 'state':status,
+ 'msg':msg,
+ 'options':osetdict,
+ }
+
+ html=render_to_string("optioninput.html", context)
+ return etree.XML(html)
+
+#-----------------------------------------------------------------------------
+
+def choicegroup(element, value, status, msg=''):
'''
Radio button inputs: multiple choice or true/false
@@ -47,7 +86,7 @@ def choicegroup(element, value, state, msg=""):
for choice in element:
assert choice.tag =="choice", "only tags should be immediate children of a "
choices[choice.get("name")] = etree.tostring(choice[0]) # TODO: what if choice[0] has math tags in it?
- context={'id':eid, 'value':value, 'state':state, 'type':type, 'choices':choices}
+ context={'id':eid, 'value':value, 'state':status, 'type':type, 'choices':choices}
html=render_to_string("choicegroup.html", context)
return etree.XML(html)
@@ -60,9 +99,9 @@ def textline(element, value, state, msg=""):
return etree.XML(html)
#-----------------------------------------------------------------------------
-# TODO: Make a wrapper for
-# TODO: Make an AJAX loop to confirm equation is okay in real-time as user types
-def jstextline(element, value, state, msg=""):
+
+def js_textline(element, value, status, msg=''):
+ ## TODO: Code should follow PEP8 (4 spaces per indentation level)
'''
textline is used for simple one-line inputs, like formularesponse and symbolicresponse.
'''
@@ -72,7 +111,7 @@ def jstextline(element, value, state, msg=""):
dojs = element.get('dojs') # dojs is used for client-side javascript display & return
# when dojs=='math', a `{::}`
# and a hidden textarea with id=input_eid_fromjs will be output
- context = {'id':eid, 'value':value, 'state':state, 'count':count, 'size': size,
+ context = {'id':eid, 'value':value, 'state':status, 'count':count, 'size': size,
'dojs':dojs,
'msg':msg,
}
@@ -81,7 +120,7 @@ def jstextline(element, value, state, msg=""):
#-----------------------------------------------------------------------------
## TODO: Make a wrapper for
-def textbox(element, value, state, msg=''):
+def textbox(element, value, status, msg=''):
'''
The textbox is used for code input. The message is the return HTML string from
evaluating the code, eg error messages, and output from the code tests.
@@ -91,12 +130,12 @@ def textbox(element, value, state, msg=''):
eid=element.get('id')
count = int(eid.split('_')[-2])-1 # HACK
size = element.get('size')
- context = {'id':eid, 'value':value, 'state':state, 'count':count, 'size': size, 'msg':msg}
+ context = {'id':eid, 'value':value, 'state':status, 'count':count, 'size': size, 'msg':msg}
html=render_to_string("textbox.html", context)
return etree.XML(html)
#-----------------------------------------------------------------------------
-def schematic(element, value, state):
+def schematic(element, value, status, msg=''):
eid = element.get('id')
height = element.get('height')
width = element.get('width')
@@ -120,7 +159,7 @@ def schematic(element, value, state):
#-----------------------------------------------------------------------------
### TODO: Move out of inputtypes
-def math(element, value, state, msg=''):
+def math(element, value, status, msg=''):
'''
This is not really an input type. It is a convention from Lon-CAPA, used for
displaying a math equation.
@@ -134,21 +173,27 @@ def math(element, value, state, msg=''):
TODO: use shorter tags (but this will require converting problem XML files!)
'''
- mathstr = element.text[1:-1]
- if '\\displaystyle' in mathstr:
- isinline = False
- mathstr = mathstr.replace('\\displaystyle','')
- else:
- isinline = True
+ mathstr = re.sub('\$(.*)\$','[mathjaxinline]\\1[/mathjaxinline]',element.text)
+ mtag = 'mathjax'
+ if not '\\displaystyle' in mathstr: mtag += 'inline'
+ else: mathstr = mathstr.replace('\\displaystyle','')
+ mathstr = mathstr.replace('mathjaxinline]','%s]'%mtag)
- html=render_to_string("mathstring.html",{'mathstr':mathstr,'isinline':isinline,'tail':element.tail})
+ #if '\\displaystyle' in mathstr:
+ # isinline = False
+ # mathstr = mathstr.replace('\\displaystyle','')
+ #else:
+ # isinline = True
+ # html=render_to_string("mathstring.html",{'mathstr':mathstr,'isinline':isinline,'tail':element.tail})
+
+ html = '%s%s' % (mathstr,element.tail)
xhtml = etree.XML(html)
# xhtml.tail = element.tail # don't forget to include the tail!
return xhtml
#-----------------------------------------------------------------------------
-def solution(element, value, state, msg=''):
+def solution(element, value, status, msg=''):
'''
This is not really an input type. It is just a ... which is given an ID,
that is used for displaying an extended answer (a problem "solution") after "show answers"
@@ -159,7 +204,7 @@ def solution(element, value, state, msg=''):
size = element.get('size')
context = {'id':eid,
'value':value,
- 'state':state,
+ 'state':status,
'size': size,
'msg':msg,
}
diff --git a/djangoapps/courseware/capa/responsetypes.py b/djangoapps/courseware/capa/responsetypes.py
index 7fb682faf6..d9b18428fe 100644
--- a/djangoapps/courseware/capa/responsetypes.py
+++ b/djangoapps/courseware/capa/responsetypes.py
@@ -32,6 +32,8 @@ from lxml.html.soupparser import fromstring as fromstring_bs # uses Beautiful So
import calc
import eia
+from util import contextualize_text
+
def compare_with_tolerance(v1, v2, tol):
''' Compare v1 to v2 with maximum tolerance tol
tol is relative if it ends in %; otherwise, it is absolute
@@ -61,6 +63,8 @@ class GenericResponse(object):
#Every response type needs methods "grade" and "get_answers"
+#-----------------------------------------------------------------------------
+
class MultipleChoiceResponse(GenericResponse):
'''
Example:
@@ -84,6 +88,7 @@ class MultipleChoiceResponse(GenericResponse):
self.correct_choices = [choice.get('name') for choice in self.correct_choices]
self.context = context
+ self.answer_field = xml.find('choicegroup') # assumes only ONE choicegroup within this response
self.answer_id = xml.xpath('//*[@id=$id]//choicegroup/@id',
id=xml.get('id'))
if not len(self.answer_id) == 1:
@@ -100,9 +105,14 @@ class MultipleChoiceResponse(GenericResponse):
return {self.answer_id:self.correct_choices}
def preprocess_response(self):
+ '''
+ Initialize name attributes in stanzas in the in this response.
+ '''
i=0
for response in self.xml.xpath("choicegroup"):
- response.set("type", "MultipleChoice")
+ rtype = response.get('type')
+ if rtype not in ["MultipleChoice"]:
+ response.set("type", "MultipleChoice") # force choicegroup to be MultipleChoice if not valid
for choice in list(response):
if choice.get("name") == None:
choice.set("name", "choice_"+str(i))
@@ -131,6 +141,42 @@ class TrueFalseResponse(MultipleChoiceResponse):
return {self.answer_id : 'incorrect'}
+#-----------------------------------------------------------------------------
+
+class OptionResponse(GenericResponse):
+ '''
+ Example:
+
+
+ The location of the sky
+ The location of the earth
+
+
+ TODO: handle direction and randomize
+
+ '''
+ def __init__(self, xml, context):
+ self.xml = xml
+ self.answer_fields = xml.findall('optioninput')
+ if settings.DEBUG:
+ print '[courseware.capa.responsetypes.OR.init] answer_fields=%s' % (self.answer_fields)
+ self.context = context
+
+ def grade(self, student_answers):
+ cmap = {}
+ amap = self.get_answers()
+ for aid in amap:
+ if aid in student_answers and student_answers[aid]==amap[aid]:
+ cmap[aid] = 'correct'
+ else:
+ cmap[aid] = 'incorrect'
+ return cmap
+
+ def get_answers(self):
+ amap = dict([(af.get('id'),af.get('correct')) for af in self.answer_fields])
+ return amap
+
+#-----------------------------------------------------------------------------
class NumericalResponse(GenericResponse):
def __init__(self, xml, context):
@@ -219,43 +265,153 @@ def sympy_check2():
self.answer_ids = xml.xpath('//*[@id=$id]//textline/@id',
id=xml.get('id'))
self.context = context
- answer_list = xml.xpath('//*[@id=$id]//answer',
- id=xml.get('id'))
- if len(answer_list):
- answer=answer_list[0]
- else:
- raise Exception("Invalid custom response -- no checker code")
- answer_src = answer.get('src')
- if answer_src != None:
- self.code = open(settings.DATA_DIR+'src/'+answer_src).read()
- else:
- self.code = answer.text
+ # if has an "expect" attribute then save that
+ self.expect = xml.get('expect')
+ self.myid = xml.get('id')
+
+ # the ... stanza should be local to the current . So try looking there first.
+ self.code = None
+ answer = None
+ try:
+ answer = xml.xpath('//*[@id=$id]//answer',id=xml.get('id'))[0]
+ except IndexError,err:
+ # print "xml = ",etree.tostring(xml,pretty_print=True)
+
+ # if we have a "cfn" attribute then look for the function specified by cfn, in the problem context
+ # ie the comparison function is defined in the stanza instead
+ cfn = xml.get('cfn')
+ if cfn:
+ if settings.DEBUG: print "[courseware.capa.responsetypes] cfn = ",cfn
+ if cfn in context:
+ self.code = context[cfn]
+ else:
+ print "can't find cfn in context = ",context
+
+ if not self.code:
+ if not answer:
+ # raise Exception,"[courseware.capa.responsetypes.customresponse] missing code checking script! id=%s" % self.myid
+ print "[courseware.capa.responsetypes.customresponse] missing code checking script! id=%s" % self.myid
+ self.code = ''
+ else:
+ answer_src = answer.get('src')
+ if answer_src != None:
+ self.code = open(settings.DATA_DIR+'src/'+answer_src).read()
+ else:
+ self.code = answer.text
def grade(self, student_answers):
'''
student_answers is a dict with everything from request.POST, but with the first part
of each key removed (the string before the first "_").
'''
- from capa_problem import global_context
- submission = [student_answers[k] for k in sorted(self.answer_ids)]
- self.context.update({'submission':submission})
- exec self.code in global_context, self.context
- return zip(sorted(self.answer_ids), self.context['correct'])
+
+ def getkey2(dict,key,default):
+ """utilify function: get dict[key] if key exists, or return default"""
+ if dict.has_key(key):
+ return dict[key]
+ return default
+
+ idset = sorted(self.answer_ids) # ordered list of answer id's
+ submission = [student_answers[k] for k in idset] # ordered list of answers
+ fromjs = [ getkey2(student_answers,k+'_fromjs',None) for k in idset ] # ordered list of fromjs_XXX responses (if exists)
+
+ # if there is only one box, and it's empty, then don't evaluate
+ if len(idset)==1 and not submission[0]:
+ return {idset[0]:'no_answer_entered'}
+
+ gctxt = self.context['global_context']
+
+ correct = ['unknown'] * len(idset)
+ messages = [''] * len(idset)
+
+ # put these in the context of the check function evaluator
+ # note that this doesn't help the "cfn" version - only the exec version
+ self.context.update({'xml' : self.xml, # our subtree
+ 'response_id' : self.myid, # my ID
+ 'expect': self.expect, # expected answer (if given as attribute)
+ 'submission':submission, # ordered list of student answers from entry boxes in our subtree
+ 'idset':idset, # ordered list of ID's of all entry boxes in our subtree
+ 'fromjs':fromjs, # ordered list of all javascript inputs in our subtree
+ 'answers':student_answers, # dict of student's responses, with keys being entry box IDs
+ 'correct':correct, # the list to be filled in by the check function
+ 'messages':messages, # the list of messages to be filled in by the check function
+ 'testdat':'hello world',
+ })
+
+ # exec the check function
+ if type(self.code)==str:
+ try:
+ exec self.code in self.context['global_context'], self.context
+ except Exception,err:
+ print "oops in customresponse (code) error %s" % err
+ print "context = ",self.context
+ print traceback.format_exc()
+ else: # self.code is not a string; assume its a function
+
+ # this is an interface to the Tutor2 check functions
+ fn = self.code
+ try:
+ answer_given = submission[0] if (len(idset)==1) else submission
+ if fn.func_code.co_argcount>=4: # does it want four arguments (the answers dict, myname)?
+ ret = fn(self.expect,answer_given,student_answers,self.answer_ids[0])
+ elif fn.func_code.co_argcount>=3: # does it want a third argument (the answers dict)?
+ ret = fn(self.expect,answer_given,student_answers)
+ else:
+ ret = fn(self.expect,answer_given)
+ except Exception,err:
+ print "oops in customresponse (cfn) error %s" % err
+ # print "context = ",self.context
+ print traceback.format_exc()
+ if settings.DEBUG: print "[courseware.capa.responsetypes.customresponse.grade] ret = ",ret
+ if type(ret)==dict:
+ correct[0] = 'correct' if ret['ok'] else 'incorrect'
+ msg = ret['msg']
+
+ if 1:
+ # try to clean up message html
+ msg = ''+msg+''
+ msg = etree.tostring(fromstring_bs(msg),pretty_print=True)
+ msg = msg.replace('
','')
+ #msg = re.sub('(.*)','\\1',msg,flags=re.M|re.DOTALL) # python 2.7
+ msg = re.sub('(?ms)(.*)','\\1',msg)
+
+ messages[0] = msg
+ else:
+ correct[0] = 'correct' if ret else 'incorrect'
+
+ # build map giving "correct"ness of the answer(s)
+ #correct_map = dict(zip(idset, self.context['correct']))
+ correct_map = {}
+ for k in range(len(idset)):
+ correct_map[idset[k]] = correct[k]
+ correct_map['msg_%s' % idset[k]] = messages[k]
+ return correct_map
def get_answers(self):
- # Since this is explicitly specified in the problem, this will
- # be handled by capa_problem
+ '''
+ Give correct answer expected for this response.
+
+ capa_problem handles correct_answers from entry objects like textline, and that
+ is what should be used when this response has multiple entry objects.
+
+ but for simplicity, if an "expect" attribute was given by the content author
+ ie then return it now.
+ '''
+ if len(self.answer_ids)>1:
+ return {}
+ if self.expect:
+ return {self.answer_ids[0] : self.expect}
return {}
#-----------------------------------------------------------------------------
class ExternalResponse(GenericResponse):
- '''
+ """
Grade the student's input using an external server.
Typically used by coding problems.
- '''
+ """
def __init__(self, xml, context):
self.xml = xml
self.answer_ids = xml.xpath('//*[@id=$id]//textbox/@id|//*[@id=$id]//textline/@id',
@@ -471,10 +627,6 @@ class ImageResponse(GenericResponse):
raise Exception,'[capamodule.capa.responsetypes.imageinput] error grading %s (input=%s)' % (err,aid,given)
(gx,gy) = [int(x) for x in m.groups()]
- if settings.DEBUG:
- print "[capamodule.capa.responsetypes.imageinput] llx,lly,urx,ury=",(llx,lly,urx,ury)
- print "[capamodule.capa.responsetypes.imageinput] gx,gy=",(gx,gy)
-
# answer is correct if (x,y) is within the specified rectangle
if (llx <= gx <= urx) and (lly <= gy <= ury):
correct_map[aid] = 'correct'
diff --git a/djangoapps/courseware/content_parser.py b/djangoapps/courseware/content_parser.py
index 9ae937e52e..adb10f7dfc 100644
--- a/djangoapps/courseware/content_parser.py
+++ b/djangoapps/courseware/content_parser.py
@@ -24,7 +24,9 @@ try: # This lets us do __name__ == ='__main__'
from student.models import UserTestGroup
from mitxmako.shortcuts import render_to_string
from util.cache import cache
+ from multicourse import multicourse_settings
except:
+ print "Could not import/content_parser"
settings = None
''' This file will eventually form an abstraction layer between the
@@ -181,7 +183,7 @@ def course_xml_process(tree):
propogate_downward_tag(tree, "rerandomize")
return tree
-def course_file(user):
+def course_file(user,coursename=None):
''' Given a user, return course.xml'''
if user.is_authenticated():
@@ -189,6 +191,11 @@ def course_file(user):
else:
filename = 'guest_course.xml'
+ # if a specific course is specified, then use multicourse to get the right path to the course XML directory
+ if coursename and settings.ENABLE_MULTICOURSE:
+ xp = multicourse_settings.get_course_xmlpath(coursename)
+ filename = xp + filename # prefix the filename with the path
+
groups = user_groups(user)
options = {'dev_content':settings.DEV_CONTENT,
'groups' : groups}
@@ -210,13 +217,24 @@ def course_file(user):
return tree
-def section_file(user, section):
- ''' Given a user and the name of a section, return that section
+def section_file(user, section, coursename=None, dironly=False):
+ '''
+ Given a user and the name of a section, return that section.
+ This is done specific to each course.
+ If dironly=True then return the sections directory.
'''
filename = section+".xml"
- if filename not in os.listdir(settings.DATA_DIR + '/sections/'):
- print filename+" not in "+str(os.listdir(settings.DATA_DIR + '/sections/'))
+ # if a specific course is specified, then use multicourse to get the right path to the course XML directory
+ xp = ''
+ if coursename and settings.ENABLE_MULTICOURSE: xp = multicourse_settings.get_course_xmlpath(coursename)
+
+ dirname = settings.DATA_DIR + xp + '/sections/'
+
+ if dironly: return dirname
+
+ if filename not in os.listdir(dirname):
+ print filename+" not in "+str(os.listdir(dirname))
return None
options = {'dev_content':settings.DEV_CONTENT,
@@ -226,7 +244,7 @@ def section_file(user, section):
return tree
-def module_xml(user, module, id_tag, module_id):
+def module_xml(user, module, id_tag, module_id, coursename=None):
''' Get XML for a module based on module and module_id. Assumes
module occurs once in courseware XML file or hidden section. '''
# Sanitize input
@@ -239,14 +257,15 @@ def module_xml(user, module, id_tag, module_id):
id_tag=id_tag,
id=module_id)
#result_set=doc.xpathEval(xpath_search)
- doc = course_file(user)
- section_list = (s[:-4] for s in os.listdir(settings.DATA_DIR+'/sections') if s[-4:]=='.xml')
+ doc = course_file(user,coursename)
+ sdirname = section_file(user,'',coursename,True) # get directory where sections information is stored
+ section_list = (s[:-4] for s in os.listdir(sdirname) if s[-4:]=='.xml')
result_set=doc.xpath(xpath_search)
if len(result_set)<1:
for section in section_list:
try:
- s = section_file(user, section)
+ s = section_file(user, section, coursename)
except etree.XMLSyntaxError:
ex= sys.exc_info()
raise ContentException("Malformed XML in " + section+ "("+str(ex[1].msg)+")")
diff --git a/djangoapps/courseware/grades.py b/djangoapps/courseware/grades.py
index 67816dc04e..2013dc28b5 100644
--- a/djangoapps/courseware/grades.py
+++ b/djangoapps/courseware/grades.py
@@ -67,7 +67,7 @@ course_settings = Settings()
-def grade_sheet(student):
+def grade_sheet(student,coursename=None):
"""
This pulls a summary of all problems in the course. It returns a dictionary with two datastructures:
@@ -77,7 +77,7 @@ def grade_sheet(student):
- grade_summary is the output from the course grader. More information on the format is in the docstring for CourseGrader.
"""
- dom=content_parser.course_file(student)
+ dom=content_parser.course_file(student,coursename)
course = dom.xpath('//course/@name')[0]
xmlChapters = dom.xpath('//course[@name=$course]/chapter', course=course)
@@ -103,7 +103,7 @@ def grade_sheet(student):
scores=[]
if len(problems)>0:
for p in problems:
- (correct,total) = get_score(student, p, response_by_id)
+ (correct,total) = get_score(student, p, response_by_id, coursename=coursename)
if settings.GENERATE_PROFILE_SCORES:
if total > 1:
@@ -167,7 +167,7 @@ def aggregate_scores(scores, section_name = "summary"):
return all_total, graded_total
-def get_score(user, problem, cache):
+def get_score(user, problem, cache, coursename=None):
## HACK: assumes max score is fixed per problem
id = problem.get('id')
correct = 0.0
@@ -196,7 +196,7 @@ def get_score(user, problem, cache):
## HACK 1: We shouldn't specifically reference capa_module
## HACK 2: Backwards-compatibility: This should be written when a grade is saved, and removed from the system
from module_render import I4xSystem
- system = I4xSystem(None, None, None)
+ system = I4xSystem(None, None, None, coursename=coursename)
total=float(courseware.modules.capa_module.Module(system, etree.tostring(problem), "id").max_score())
response.max_grade = total
response.save()
diff --git a/djangoapps/courseware/module_render.py b/djangoapps/courseware/module_render.py
index 9bb7872a66..0e317f7004 100644
--- a/djangoapps/courseware/module_render.py
+++ b/djangoapps/courseware/module_render.py
@@ -22,6 +22,11 @@ import courseware.modules
log = logging.getLogger("mitx.courseware")
class I4xSystem(object):
+ '''
+ This is an abstraction such that x_modules can function independent
+ of the courseware (e.g. import into other types of courseware, LMS,
+ or if we want to have a sandbox server for user-contributed content)
+ '''
def __init__(self, ajax_url, track_function, render_function, filestore=None):
self.ajax_url = ajax_url
self.track_function = track_function
@@ -29,6 +34,10 @@ class I4xSystem(object):
self.filestore = OSFS(settings.DATA_DIR)
self.render_function = render_function
self.exception404 = Http404
+ def __repr__(self):
+ return repr(self.__dict__)
+ def __str__(self):
+ return str(self.__dict__)
def object_cache(cache, user, module_type, module_id):
# We don't look up on user -- all queries include user
@@ -50,6 +59,7 @@ def make_track_function(request):
def f(event_type, event):
return track.views.server_track(request, event_type, event, page='x_module')
return f
+
def grade_histogram(module_id):
''' Print out a histogram of grades on a given problem.
Part of staff member debug info.
@@ -83,6 +93,10 @@ def render_x_module(user, request, xml_module, module_object_preload):
else:
state = smod.state
+ # get coursename if stored
+ if 'coursename' in request.session: coursename = request.session['coursename']
+ else: coursename = None
+
# Create a new instance
ajax_url = settings.MITX_ROOT_URL + '/modx/'+module_type+'/'+module_id+'/'
system = I4xSystem(track_function = make_track_function(request),
@@ -104,6 +118,7 @@ def render_x_module(user, request, xml_module, module_object_preload):
state=instance.get_state())
smod.save()
module_object_preload.append(smod)
+
# Grab content
content = instance.get_html()
init_js = instance.get_init_js()
diff --git a/djangoapps/courseware/modules/capa_module.py b/djangoapps/courseware/modules/capa_module.py
index 7a43051026..0b75faa491 100644
--- a/djangoapps/courseware/modules/capa_module.py
+++ b/djangoapps/courseware/modules/capa_module.py
@@ -21,6 +21,7 @@ from mitxmako.shortcuts import render_to_string
from x_module import XModule
from courseware.capa.capa_problem import LoncapaProblem, StudentInputError
import courseware.content_parser as content_parser
+from multicourse import multicourse_settings
log = logging.getLogger("mitx.courseware")
@@ -115,18 +116,19 @@ class Module(XModule):
if len(explain) == 0:
explain = False
- html=render_to_string('problem.html',
- {'problem' : content,
- 'id' : self.item_id,
- 'check_button' : check_button,
- 'reset_button' : reset_button,
- 'save_button' : save_button,
- 'answer_available' : self.answer_available(),
- 'ajax_url' : self.ajax_url,
- 'attempts_used': self.attempts,
- 'attempts_allowed': self.max_attempts,
- 'explain': explain
- })
+ context = {'problem' : content,
+ 'id' : self.item_id,
+ 'check_button' : check_button,
+ 'reset_button' : reset_button,
+ 'save_button' : save_button,
+ 'answer_available' : self.answer_available(),
+ 'ajax_url' : self.ajax_url,
+ 'attempts_used': self.attempts,
+ 'attempts_allowed': self.max_attempts,
+ 'explain': explain,
+ }
+
+ html=render_to_string('problem.html', context)
if encapsulate:
html = '
+Why do bicycles benefit from having larger wheels when going up a bump as shown in the picture?
+Assume that for both bicycles:
+1.) The tires have equal air pressure.
+2.) The bicycles never leave the contact with the bump.
+3.) The bicycles have the same mass. The bicycle tires (regardless of size) have the same mass.
+
+
+
+
+
+
+
The bicycles with larger wheels have more time to go over the bump. This decreases the magnitude of the force needed to lift the bicycle.
+
+
+
+
+
+
+
The bicycles with larger wheels always have a smaller vertical displacement regardless of speed.
+
+
+
+
+
+
+
The bicycles with larger wheels experience a force backward with less magnitude for the same amount of time.
+
+
+
+
+
+
+
The bicycles with larger wheels experience a force backward with less magnitude for a greater amount of time.
+
+
+
+
+
+
+
The bicycles with larger wheels have more kinetic energy turned into gravitational potential energy.
+
+
+
+
+
+
+
The bicycles with larger wheels have more rotational kinetic energy, so the horizontal velocity of the biker changes less.
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/djangoapps/courseware/tests.py b/djangoapps/courseware/tests.py
index 5688d698b2..682927efb7 100644
--- a/djangoapps/courseware/tests.py
+++ b/djangoapps/courseware/tests.py
@@ -63,6 +63,9 @@ class ModelsTest(unittest.TestCase):
exception_happened = True
self.assertTrue(exception_happened)
+#-----------------------------------------------------------------------------
+# tests of capa_problem inputtypes
+
class MultiChoiceTest(unittest.TestCase):
def test_MC_grade(self):
multichoice_file = os.path.dirname(__file__)+"/test_files/multichoice.xml"
@@ -93,6 +96,38 @@ class MultiChoiceTest(unittest.TestCase):
self.assertEquals(test_lcp.grade_answers(false_answers)['1_2_1'], 'incorrect')
false_answers = {'1_2_1':['choice_foil1', 'choice_foil2', 'choice_foil3']}
self.assertEquals(test_lcp.grade_answers(false_answers)['1_2_1'], 'incorrect')
+
+class ImageResponseTest(unittest.TestCase):
+ def test_ir_grade(self):
+ imageresponse_file = os.path.dirname(__file__)+"/test_files/imageresponse.xml"
+ test_lcp = lcp.LoncapaProblem(open(imageresponse_file), '1')
+ correct_answers = {'1_2_1':'(490,11)-(556,98)',
+ '1_2_2':'(242,202)-(296,276)'}
+ test_answers = {'1_2_1':'[500,20]',
+ '1_2_2':'[250,300]',
+ }
+ self.assertEquals(test_lcp.grade_answers(test_answers)['1_2_1'], 'correct')
+ self.assertEquals(test_lcp.grade_answers(test_answers)['1_2_2'], 'incorrect')
+
+class OptionResponseTest(unittest.TestCase):
+ '''
+ Run this with
+
+ python manage.py test courseware.OptionResponseTest
+ '''
+ def test_or_grade(self):
+ optionresponse_file = os.path.dirname(__file__)+"/test_files/optionresponse.xml"
+ test_lcp = lcp.LoncapaProblem(open(optionresponse_file), '1')
+ correct_answers = {'1_2_1':'True',
+ '1_2_2':'False'}
+ test_answers = {'1_2_1':'True',
+ '1_2_2':'True',
+ }
+ self.assertEquals(test_lcp.grade_answers(test_answers)['1_2_1'], 'correct')
+ self.assertEquals(test_lcp.grade_answers(test_answers)['1_2_2'], 'incorrect')
+
+#-----------------------------------------------------------------------------
+# Grading tests
class GradesheetTest(unittest.TestCase):
@@ -118,7 +153,7 @@ class GradesheetTest(unittest.TestCase):
all, graded = aggregate_scores(scores)
self.assertAlmostEqual(all, Score(earned=5, possible=15, graded=False, section="summary"))
self.assertAlmostEqual(graded, Score(earned=5, possible=10, graded=True, section="summary"))
-
+
class GraderTest(unittest.TestCase):
empty_gradesheet = {
diff --git a/djangoapps/courseware/views.py b/djangoapps/courseware/views.py
index 6f991e261c..9b6a67b056 100644
--- a/djangoapps/courseware/views.py
+++ b/djangoapps/courseware/views.py
@@ -18,6 +18,7 @@ from module_render import render_module, make_track_function, I4xSystem
from models import StudentModule
from student.models import UserProfile
from util.errors import record_exception
+from multicourse import multicourse_settings
import courseware.content_parser as content_parser
import courseware.modules
@@ -35,11 +36,16 @@ template_imports={'urllib':urllib}
def gradebook(request):
if 'course_admin' not in content_parser.user_groups(request.user):
raise Http404
+
+ # TODO: This should be abstracted out. We repeat this logic many times.
+ if 'coursename' in request.session: coursename = request.session['coursename']
+ else: coursename = None
+
student_objects = User.objects.all()[:100]
student_info = [{'username' :s.username,
'id' : s.id,
'email': s.email,
- 'grade_info' : grades.grade_sheet(s),
+ 'grade_info' : grades.grade_sheet(s,coursename),
'realname' : UserProfile.objects.get(user = s).name
} for s in student_objects]
@@ -61,6 +67,9 @@ def profile(request, student_id = None):
user_info = UserProfile.objects.get(user=student) # request.user.profile_cache #
+ if 'coursename' in request.session: coursename = request.session['coursename']
+ else: coursename = None
+
context={'name':user_info.name,
'username':student.username,
'location':user_info.location,
@@ -69,7 +78,7 @@ def profile(request, student_id = None):
'format_url_params' : content_parser.format_url_params,
'csrf':csrf(request)['csrf_token']
}
- context.update(grades.grade_sheet(student))
+ context.update(grades.grade_sheet(student,coursename))
return render_to_response('profile.html', context)
@@ -79,7 +88,7 @@ def render_accordion(request,course,chapter,section):
if not course:
course = "6.002 Spring 2012"
- toc=content_parser.toc_from_xml(content_parser.course_file(request.user), chapter, section)
+ toc=content_parser.toc_from_xml(content_parser.course_file(request.user,course), chapter, section)
active_chapter=1
for i in range(len(toc)):
if toc[i]['active']:
@@ -100,8 +109,11 @@ def render_section(request, section):
if not settings.COURSEWARE_ENABLED:
return redirect('/')
+ if 'coursename' in request.session: coursename = request.session['coursename']
+ else: coursename = None
+
try:
- dom = content_parser.section_file(user, section)
+ dom = content_parser.section_file(user, section, coursename)
except:
record_exception(log, "Unable to parse courseware xml")
return render_to_response('courseware-error.html', {})
@@ -139,13 +151,21 @@ def render_section(request, section):
@cache_control(no_cache=True, no_store=True, must_revalidate=True)
-def index(request, course="6.002 Spring 2012", chapter="Using the System", section="Hints"):
+def index(request, course=None, chapter="Using the System", section="Hints"):
''' Displays courseware accordion, and any associated content.
'''
user = request.user
if not settings.COURSEWARE_ENABLED:
return redirect('/')
+ if course==None:
+ if not settings.ENABLE_MULTICOURSE:
+ course = "6.002 Spring 2012"
+ elif 'coursename' in request.session:
+ course = request.session['coursename']
+ else:
+ course = settings.COURSE_DEFAULT
+
# Fixes URLs -- we don't get funny encoding characters from spaces
# so they remain readable
## TODO: Properly replace underscores
@@ -153,13 +173,15 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti
chapter=chapter.replace("_"," ")
section=section.replace("_"," ")
- # HACK: Force course to 6.002 for now
- # Without this, URLs break
- if course!="6.002 Spring 2012":
+ # use multicourse module to determine if "course" is valid
+ #if course!=settings.COURSE_NAME.replace('_',' '):
+ if not multicourse_settings.is_valid_course(course):
return redirect('/')
+ request.session['coursename'] = course # keep track of current course being viewed in django's request.session
+
try:
- dom = content_parser.course_file(user)
+ dom = content_parser.course_file(user,course) # also pass course to it, for course-specific XML path
except:
record_exception(log, "Unable to parse courseware xml")
return render_to_response('courseware-error.html', {})
@@ -184,6 +206,7 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti
context = {
'csrf': csrf(request)['csrf_token'],
'accordion': render_accordion(request, course, chapter, section)
+ 'COURSE_TITLE':multicourse_settings.get_course_title(course),
}
try:
@@ -226,9 +249,13 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
ajax_url = settings.MITX_ROOT_URL + '/modx/'+module+'/'+id+'/'
+ # get coursename if stored
+ if 'coursename' in request.session: coursename = request.session['coursename']
+ else: coursename = None
+
# Grab the XML corresponding to the request from course.xml
try:
- xml = content_parser.module_xml(request.user, module, 'id', id)
+ xml = content_parser.module_xml(request.user, module, 'id', id, coursename)
except:
record_exception(log, "Unable to load module during ajax call")
if 'text/html' in request.accepted_types:
@@ -267,3 +294,98 @@ def modx_dispatch(request, module=None, dispatch=None, id=None):
s.save()
# Return whatever the module wanted to return to the client/caller
return HttpResponse(ajax_return)
+
+def quickedit(request, id=None):
+ '''
+ quick-edit capa problem.
+
+ Maybe this should be moved into capa/views.py
+ Or this should take a "module" argument, and the quickedit moved into capa_module.
+ '''
+ print "WARNING: UNDEPLOYABLE CODE. FOR DEV USE ONLY."
+ print "In deployed use, this will only edit on one server"
+ print "We need a setting to disable for production where there is"
+ print "a load balanacer"
+ if not request.user.is_staff():
+ return redirect('/')
+
+ # get coursename if stored
+ if 'coursename' in request.session: coursename = request.session['coursename']
+ else: coursename = None
+
+ def get_lcp(coursename,id):
+ # Grab the XML corresponding to the request from course.xml
+ module = 'problem'
+ xml = content_parser.module_xml(request.user, module, 'id', id, coursename)
+
+ ajax_url = settings.MITX_ROOT_URL + '/modx/'+module+'/'+id+'/'
+
+ # Create the module (instance of capa_module.Module)
+ system = I4xSystem(track_function = make_track_function(request),
+ render_function = None,
+ ajax_url = ajax_url,
+ filestore = None,
+ coursename = coursename,
+ role = 'staff' if request.user.is_staff else 'student', # TODO: generalize this
+ )
+ instance=courseware.modules.get_module_class(module)(system,
+ xml,
+ id,
+ state=None)
+ lcp = instance.lcp
+ pxml = lcp.tree
+ pxmls = etree.tostring(pxml,pretty_print=True)
+
+ return instance, pxmls
+
+ instance, pxmls = get_lcp(coursename,id)
+
+ # if there was a POST, then process it
+ msg = ''
+ if 'qesubmit' in request.POST:
+ action = request.POST['qesubmit']
+ if "Revert" in action:
+ msg = "Reverted to original"
+ elif action=='Change Problem':
+ key = 'quickedit_%s' % id
+ if not key in request.POST:
+ msg = "oops, missing code key=%s" % key
+ else:
+ newcode = request.POST[key]
+
+ # see if code changed
+ if str(newcode)==str(pxmls) or '\n'+str(newcode)==str(pxmls):
+ msg = "No changes"
+ else:
+ # check new code
+ isok = False
+ try:
+ newxml = etree.fromstring(newcode)
+ isok = True
+ except Exception,err:
+ msg = "Failed to change problem: XML error \"%s\"" % err
+
+ if isok:
+ filename = instance.lcp.fileobject.name
+ fp = open(filename,'w') # TODO - replace with filestore call?
+ fp.write(newcode)
+ fp.close()
+ msg = "Problem changed! (%s)" % filename
+ instance, pxmls = get_lcp(coursename,id)
+
+ lcp = instance.lcp
+
+ # get the rendered problem HTML
+ phtml = instance.get_problem_html()
+
+ context = {'id':id,
+ 'msg' : msg,
+ 'lcp' : lcp,
+ 'filename' : lcp.fileobject.name,
+ 'pxmls' : pxmls,
+ 'phtml' : phtml,
+ 'init_js':instance.get_init_js(),
+ }
+
+ result = render_to_response('quickedit.html', context)
+ return result
diff --git a/static/css/print.css b/djangoapps/multicourse/__init__.py
similarity index 100%
rename from static/css/print.css
rename to djangoapps/multicourse/__init__.py
diff --git a/djangoapps/multicourse/multicourse_settings.py b/djangoapps/multicourse/multicourse_settings.py
new file mode 100644
index 0000000000..99c9ef8620
--- /dev/null
+++ b/djangoapps/multicourse/multicourse_settings.py
@@ -0,0 +1,73 @@
+# multicourse/multicourse_settings.py
+#
+# central module for providing fixed settings (course name, number, title)
+# for multiple courses. Loads this information from django.conf.settings
+#
+# Allows backward compatibility with settings configurations without
+# multiple courses specified.
+#
+# The central piece of configuration data is the dict COURSE_SETTINGS, with
+# keys being the COURSE_NAME (spaces ok), and the value being a dict of
+# parameter,value pairs. The required parameters are:
+#
+# - number : course number (used in the simplewiki pages)
+# - title : humanized descriptive course title
+#
+# Optional parameters:
+#
+# - xmlpath : path (relative to data directory) for this course (defaults to "")
+#
+# If COURSE_SETTINGS does not exist, then fallback to 6.002_Spring_2012 default,
+# for now.
+
+from django.conf import settings
+
+#-----------------------------------------------------------------------------
+# load course settings
+
+if hasattr(settings,'COURSE_SETTINGS'): # in the future, this could be replaced by reading an XML file
+ COURSE_SETTINGS = settings.COURSE_SETTINGS
+
+elif hasattr(settings,'COURSE_NAME'): # backward compatibility
+ COURSE_SETTINGS = {settings.COURSE_NAME: {'number': settings.COURSE_NUMBER,
+ 'title': settings.COURSE_TITLE,
+ },
+ }
+else: # default to 6.002_Spring_2012
+ COURSE_SETTINGS = {'6.002_Spring_2012': {'number': '6.002x',
+ 'title': 'Circuits and Electronics',
+ },
+ }
+
+#-----------------------------------------------------------------------------
+# wrapper functions around course settings
+
+def get_course_settings(coursename):
+ if not coursename:
+ if hasattr(settings,'COURSE_DEFAULT'):
+ coursename = settings.COURSE_DEFAULT
+ else:
+ coursename = '6.002_Spring_2012'
+ if coursename in COURSE_SETTINGS: return COURSE_SETTINGS[coursename]
+ coursename = coursename.replace(' ','_')
+ if coursename in COURSE_SETTINGS: return COURSE_SETTINGS[coursename]
+ return None
+
+def is_valid_course(coursename):
+ return not (get_course_settings==None)
+
+def get_course_property(coursename,property):
+ cs = get_course_settings(coursename)
+ if not cs: return '' # raise exception instead?
+ if property in cs: return cs[property]
+ return '' # default
+
+def get_course_xmlpath(coursename):
+ return get_course_property(coursename,'xmlpath')
+
+def get_course_title(coursename):
+ return get_course_property(coursename,'title')
+
+def get_course_number(coursename):
+ return get_course_property(coursename,'number')
+
diff --git a/djangoapps/multicourse/views.py b/djangoapps/multicourse/views.py
new file mode 100644
index 0000000000..d0662b710e
--- /dev/null
+++ b/djangoapps/multicourse/views.py
@@ -0,0 +1 @@
+# multicourse/views.py
diff --git a/djangoapps/simplewiki/views.py b/djangoapps/simplewiki/views.py
index fcd98bfeb1..34a81e6b57 100644
--- a/djangoapps/simplewiki/views.py
+++ b/djangoapps/simplewiki/views.py
@@ -9,6 +9,8 @@ from django.utils import simplejson
from django.utils.translation import ugettext_lazy as _
from mitxmako.shortcuts import render_to_response
+from multicourse import multicourse_settings
+
from models import Revision, Article, CreateArticleForm, RevisionFormWithTitle, RevisionForm
import wiki_settings
@@ -17,6 +19,11 @@ def view(request, wiki_url):
if err:
return err
+ if 'coursename' in request.session: coursename = request.session['coursename']
+ else: coursename = None
+
+ course_number = multicourse_settings.get_course_number(coursename)
+
perm_err = check_permissions(request, article, check_read=True, check_deleted=True)
if perm_err:
return perm_err
@@ -25,7 +32,7 @@ def view(request, wiki_url):
'wiki_write': article.can_write_l(request.user),
'wiki_attachments_write': article.can_attach(request.user),
'wiki_current_revision_deleted' : not (article.current_revision.deleted == 0),
- 'wiki_title' : article.title + " - MITX 6.002x Wiki"
+ 'wiki_title' : article.title + " - MITX %s Wiki" % course_number
}
d.update(csrf(request))
return render_to_response('simplewiki_view.html', d)
diff --git a/djangoapps/ssl_auth/__init__.py b/djangoapps/ssl_auth/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
diff --git a/djangoapps/ssl_auth/ssl_auth.py b/djangoapps/ssl_auth/ssl_auth.py
new file mode 100755
index 0000000000..8c96d4b9a6
--- /dev/null
+++ b/djangoapps/ssl_auth/ssl_auth.py
@@ -0,0 +1,281 @@
+"""
+User authentication backend for ssl (no pw required)
+"""
+
+from django.conf import settings
+from django.contrib import auth
+from django.contrib.auth.models import User, check_password
+from django.contrib.auth.backends import ModelBackend
+from django.contrib.auth.middleware import RemoteUserMiddleware
+from django.core.exceptions import ImproperlyConfigured
+import os, string, re
+from random import choice
+
+from student.models import UserProfile
+
+#-----------------------------------------------------------------------------
+
+def ssl_dn_extract_info(dn):
+ '''
+ Extract username, email address (may be anyuser@anydomain.com) and full name
+ from the SSL DN string. Return (user,email,fullname) if successful, and None
+ otherwise.
+ '''
+ ss = re.search('/emailAddress=(.*)@([^/]+)',dn)
+ if ss:
+ user = ss.group(1)
+ email = "%s@%s" % (user,ss.group(2))
+ else:
+ return None
+ ss = re.search('/CN=([^/]+)/',dn)
+ if ss:
+ fullname = ss.group(1)
+ else:
+ return None
+ return (user,email,fullname)
+
+def check_nginx_proxy(request):
+ '''
+ Check for keys in the HTTP header (META) to se if we are behind an ngix reverse proxy.
+ If so, get user info from the SSL DN string and return that, as (user,email,fullname)
+ '''
+ m = request.META
+ if m.has_key('HTTP_X_REAL_IP'): # we're behind a nginx reverse proxy, which has already done ssl auth
+ if not m.has_key('HTTP_SSL_CLIENT_S_DN'):
+ return None
+ dn = m['HTTP_SSL_CLIENT_S_DN']
+ return ssl_dn_extract_info(dn)
+ return None
+
+#-----------------------------------------------------------------------------
+
+def get_ssl_username(request):
+ x = check_nginx_proxy(request)
+ if x:
+ return x[0]
+ env = request._req.subprocess_env
+ if env.has_key('SSL_CLIENT_S_DN_Email'):
+ email = env['SSL_CLIENT_S_DN_Email']
+ user = email[:email.index('@')]
+ return user
+ return None
+
+#-----------------------------------------------------------------------------
+
+class NginxProxyHeaderMiddleware(RemoteUserMiddleware):
+ '''
+ Django "middleware" function for extracting user information from HTTP request.
+
+ '''
+ # this field is generated by nginx's reverse proxy
+ header = 'HTTP_SSL_CLIENT_S_DN' # specify the request.META field to use
+
+ def process_request(self, request):
+ # AuthenticationMiddleware is required so that request.user exists.
+ if not hasattr(request, 'user'):
+ raise ImproperlyConfigured(
+ "The Django remote user auth middleware requires the"
+ " authentication middleware to be installed. Edit your"
+ " MIDDLEWARE_CLASSES setting to insert"
+ " 'django.contrib.auth.middleware.AuthenticationMiddleware'"
+ " before the RemoteUserMiddleware class.")
+
+ #raise ImproperlyConfigured('[ProxyHeaderMiddleware] request.META=%s' % repr(request.META))
+
+ try:
+ username = request.META[self.header] # try the nginx META key first
+ except KeyError:
+ try:
+ env = request._req.subprocess_env # else try the direct apache2 SSL key
+ if env.has_key('SSL_CLIENT_S_DN'):
+ username = env['SSL_CLIENT_S_DN']
+ else:
+ raise ImproperlyConfigured('no ssl key, env=%s' % repr(env))
+ username = ''
+ except:
+ # If specified header doesn't exist then return (leaving
+ # request.user set to AnonymousUser by the
+ # AuthenticationMiddleware).
+ return
+ # If the user is already authenticated and that user is the user we are
+ # getting passed in the headers, then the correct user is already
+ # persisted in the session and we don't need to continue.
+
+ #raise ImproperlyConfigured('[ProxyHeaderMiddleware] username=%s' % username)
+
+ if request.user.is_authenticated():
+ if request.user.username == self.clean_username(username, request):
+ #raise ImproperlyConfigured('%s already authenticated (%s)' % (username,request.user.username))
+ return
+ # We are seeing this user for the first time in this session, attempt
+ # to authenticate the user.
+ #raise ImproperlyConfigured('calling auth.authenticate, remote_user=%s' % username)
+ user = auth.authenticate(remote_user=username)
+ if user:
+ # User is valid. Set request.user and persist user in the session
+ # by logging the user in.
+ request.user = user
+ if settings.DEBUG: print "[ssl_auth.ssl_auth.NginxProxyHeaderMiddleware] logging in user=%s" % user
+ auth.login(request, user)
+
+ def clean_username(self,username,request):
+ '''
+ username is the SSL DN string - extract the actual username from it and return
+ '''
+ info = ssl_dn_extract_info(username)
+ if not info:
+ return None
+ (username,email,fullname) = info
+ return username
+
+#-----------------------------------------------------------------------------
+
+class SSLLoginBackend(ModelBackend):
+ '''
+ Django authentication back-end which auto-logs-in a user based on having
+ already authenticated with an MIT certificate (SSL).
+ '''
+ def authenticate(self, username=None, password=None, remote_user=None):
+
+ # remote_user is from the SSL_DN string. It will be non-empty only when
+ # the user has already passed the server authentication, which means
+ # matching with the certificate authority.
+ if not remote_user:
+ # no remote_user, so check username (but don't auto-create user)
+ if not username:
+ return None
+ return None # pass on to another authenticator backend
+ #raise ImproperlyConfigured("in SSLLoginBackend, username=%s, remote_user=%s" % (username,remote_user))
+ try:
+ user = User.objects.get(username=username) # if user already exists don't create it
+ return user
+ except User.DoesNotExist:
+ return None
+ return None
+
+ #raise ImproperlyConfigured("in SSLLoginBackend, username=%s, remote_user=%s" % (username,remote_user))
+ #if not os.environ.has_key('HTTPS'):
+ # return None
+ #if not os.environ.get('HTTPS')=='on': # only use this back-end if HTTPS on
+ # return None
+
+ def GenPasswd(length=8, chars=string.letters + string.digits):
+ return ''.join([choice(chars) for i in range(length)])
+
+ # convert remote_user to user, email, fullname
+ info = ssl_dn_extract_info(remote_user)
+ #raise ImproperlyConfigured("[SSLLoginBackend] looking up %s" % repr(info))
+ if not info:
+ #raise ImproperlyConfigured("[SSLLoginBackend] remote_user=%s, info=%s" % (remote_user,info))
+ return None
+ (username,email,fullname) = info
+
+ try:
+ user = User.objects.get(username=username) # if user already exists don't create it
+ except User.DoesNotExist:
+ raise "User does not exist. Not creating user; potential schema consistency issues"
+ #raise ImproperlyConfigured("[SSLLoginBackend] creating %s" % repr(info))
+ user = User(username=username, password=GenPasswd()) # create new User
+ user.is_staff = False
+ user.is_superuser = False
+ # get first, last name from fullname
+ name = fullname
+ if not name.count(' '):
+ user.first_name = " "
+ user.last_name = name
+ mn = ''
+ else:
+ user.first_name = name[:name.find(' ')]
+ ml = name[name.find(' '):].strip()
+ if ml.count(' '):
+ user.last_name = ml[ml.rfind(' '):]
+ mn = ml[:ml.rfind(' ')]
+ else:
+ user.last_name = ml
+ mn = ''
+ # set email
+ user.email = email
+ # cleanup last name
+ user.last_name = user.last_name.strip()
+ # save
+ user.save()
+
+ # auto-create user profile
+ up = UserProfile(user=user)
+ up.name = fullname
+ up.save()
+
+ #tui = user.get_profile()
+ #tui.middle_name = mn
+ #tui.role = 'Misc'
+ #tui.section = None # no section assigned at first
+ #tui.save()
+ # return None
+ return user
+
+ def get_user(self, user_id):
+ #if not os.environ.has_key('HTTPS'):
+ # return None
+ #if not os.environ.get('HTTPS')=='on': # only use this back-end if HTTPS on
+ # return None
+ try:
+ return User.objects.get(pk=user_id)
+ except User.DoesNotExist:
+ return None
+
+#-----------------------------------------------------------------------------
+# OLD!
+
+class AutoLoginBackend:
+ def authenticate(self, username=None, password=None):
+ raise ImproperlyConfigured("in AutoLoginBackend, username=%s" % username)
+ if not os.environ.has_key('HTTPS'):
+ return None
+ if not os.environ.get('HTTPS')=='on':# only use this back-end if HTTPS on
+ return None
+
+ def GenPasswd(length=8, chars=string.letters + string.digits):
+ return ''.join([choice(chars) for i in range(length)])
+
+ try:
+ user = User.objects.get(username=username)
+ except User.DoesNotExist:
+ user = User(username=username, password=GenPasswd())
+ user.is_staff = False
+ user.is_superuser = False
+ # get first, last name
+ name = os.environ.get('SSL_CLIENT_S_DN_CN').strip()
+ if not name.count(' '):
+ user.first_name = " "
+ user.last_name = name
+ mn = ''
+ else:
+ user.first_name = name[:name.find(' ')]
+ ml = name[name.find(' '):].strip()
+ if ml.count(' '):
+ user.last_name = ml[ml.rfind(' '):]
+ mn = ml[:ml.rfind(' ')]
+ else:
+ user.last_name = ml
+ mn = ''
+ # get email
+ user.email = os.environ.get('SSL_CLIENT_S_DN_Email')
+ # save
+ user.save()
+ tui = user.get_profile()
+ tui.middle_name = mn
+ tui.role = 'Misc'
+ tui.section = None# no section assigned at first
+ tui.save()
+ # return None
+ return user
+
+ def get_user(self, user_id):
+ if not os.environ.has_key('HTTPS'):
+ return None
+ if not os.environ.get('HTTPS')=='on':# only use this back-end if HTTPS on
+ return None
+ try:
+ return User.objects.get(pk=user_id)
+ except User.DoesNotExist:
+ return None
diff --git a/envs/aws.py b/envs/aws.py
index de770a2399..7363cbb3f7 100644
--- a/envs/aws.py
+++ b/envs/aws.py
@@ -8,7 +8,8 @@ Common traits:
"""
import json
-from common import *
+from envs.logsettings import get_logger_config
+from envs.common import *
############################### ALWAYS THE SAME ################################
DEBUG = False
@@ -31,10 +32,10 @@ LOG_DIR = ENV_TOKENS['LOG_DIR']
CACHES = ENV_TOKENS['CACHES']
-LOGGING = logsettings.get_logger_config(LOG_DIR,
- logging_env=ENV_TOKENS['LOGGING_ENV'],
- syslog_addr=(ENV_TOKENS['SYSLOG_SERVER'], 514),
- debug=False)
+LOGGING = get_logger_config(LOG_DIR,
+ logging_env=ENV_TOKENS['LOGGING_ENV'],
+ syslog_addr=(ENV_TOKENS['SYSLOG_SERVER'], 514),
+ debug=False)
############################## SECURE AUTH ITEMS ###############################
# Secret things: passwords, access keys, etc.
diff --git a/envs/common.py b/envs/common.py
index 3576b31968..e5456d22bb 100644
--- a/envs/common.py
+++ b/envs/common.py
@@ -24,8 +24,7 @@ import tempfile
import djcelery
from path import path
-from askbotsettings import * # this is where LIVESETTINGS_OPTIONS comes from
-import logsettings
+from envs.askbotsettings import * # this is where LIVESETTINGS_OPTIONS comes from
################################### FEATURES ###################################
COURSEWARE_ENABLED = True
diff --git a/envs/content.py b/envs/content.py
index c02e7bb72e..495bbeedac 100644
--- a/envs/content.py
+++ b/envs/content.py
@@ -2,7 +2,7 @@
These are debug machines used for content creators, so they're kind of a cross
between dev machines and AWS machines.
"""
-from aws import *
+from envs.aws import *
DEBUG = True
TEMPLATE_DEBUG = True
diff --git a/envs/dev.py b/envs/dev.py
index 51769c732d..73ac37107a 100644
--- a/envs/dev.py
+++ b/envs/dev.py
@@ -7,15 +7,16 @@ sessions. Assumes structure:
/mitx # The location of this repo
/log # Where we're going to write log files
"""
-from common import *
+from envs.common import *
+from envs.logsettings import get_logger_config
DEBUG = False
TEMPLATE_DEBUG = False
-LOGGING = logsettings.get_logger_config(ENV_ROOT / "log",
- logging_env="dev",
- tracking_filename="tracking.log",
- debug=True)
+LOGGING = get_logger_config(ENV_ROOT / "log",
+ logging_env="dev",
+ tracking_filename="tracking.log",
+ debug=True)
DATABASES = {
'default': {
diff --git a/envs/devplus.py b/envs/devplus.py
index 2ec38b53a0..4f763b925c 100644
--- a/envs/devplus.py
+++ b/envs/devplus.py
@@ -13,7 +13,7 @@ Dir structure:
/log # Where we're going to write log files
"""
-from dev import *
+from envs.dev import *
DATABASES = {
'default': {
diff --git a/envs/static.py b/envs/static.py
index 1e7adeb9db..65309c4795 100644
--- a/envs/static.py
+++ b/envs/static.py
@@ -7,14 +7,15 @@ sessions. Assumes structure:
/mitx # The location of this repo
/log # Where we're going to write log files
"""
-from common import *
+from envs.common import *
+from envs.logsettings import get_logger_config
STATIC_GRAB = True
-LOGGING = logsettings.get_logger_config(ENV_ROOT / "log",
- logging_env="dev",
- tracking_filename="tracking.log",
- debug=False)
+LOGGING = get_logger_config(ENV_ROOT / "log",
+ logging_env="dev",
+ tracking_filename="tracking.log",
+ debug=False)
DATABASES = {
'default': {
diff --git a/envs/test.py b/envs/test.py
index 9aa030c15a..bf83511786 100644
--- a/envs/test.py
+++ b/envs/test.py
@@ -7,7 +7,8 @@ sessions. Assumes structure:
/mitx # The location of this repo
/log # Where we're going to write log files
"""
-from common import *
+from envs.common import *
+from envs.logsettings import get_logger_config
import os
INSTALLED_APPS = [
@@ -25,7 +26,8 @@ for app in os.listdir(PROJECT_ROOT / 'djangoapps'):
TEST_RUNNER = 'django_nose.NoseTestSuiteRunner'
# Local Directories
-COURSES_ROOT = PROJECT_ROOT / "test_data"
+TEST_ROOT = path("test_root")
+COURSES_ROOT = TEST_ROOT / "data"
DATA_DIR = COURSES_ROOT
MAKO_TEMPLATES['course'] = [DATA_DIR]
MAKO_TEMPLATES['sections'] = [DATA_DIR / 'sections']
@@ -34,10 +36,10 @@ MAKO_TEMPLATES['main'] = [PROJECT_ROOT / 'templates',
DATA_DIR / 'info',
DATA_DIR / 'problems']
-LOGGING = logsettings.get_logger_config(PROJECT_ROOT / "log",
- logging_env="dev",
- tracking_filename="tracking.log",
- debug=True)
+LOGGING = get_logger_config(TEST_ROOT / "log",
+ logging_env="dev",
+ tracking_filename="tracking.log",
+ debug=True)
DATABASES = {
'default': {
diff --git a/lib/loncapa/__init__.py b/lib/loncapa/__init__.py
new file mode 100644
index 0000000000..b734967d0a
--- /dev/null
+++ b/lib/loncapa/__init__.py
@@ -0,0 +1,3 @@
+#!/usr/bin/python
+
+from loncapa_check import *
diff --git a/lib/loncapa/loncapa_check.py b/lib/loncapa/loncapa_check.py
new file mode 100644
index 0000000000..259c7909ac
--- /dev/null
+++ b/lib/loncapa/loncapa_check.py
@@ -0,0 +1,17 @@
+#!/usr/bin/python
+#
+# File: mitx/lib/loncapa/loncapa_check.py
+#
+# Python functions which duplicate the standard comparison functions available to LON-CAPA problems.
+# Used in translating LON-CAPA problems to i4x problem specification language.
+
+import random
+
+def lc_random(lower,upper,stepsize):
+ '''
+ like random.randrange but lower and upper can be non-integer
+ '''
+ nstep = int((upper-lower)/(1.0*stepsize))
+ choices = [lower+x*stepsize for x in range(nstep)]
+ return random.choice(choices)
+
diff --git a/lib/mitxmako/shortcuts.py b/lib/mitxmako/shortcuts.py
index 432acbcba9..7286a4e259 100644
--- a/lib/mitxmako/shortcuts.py
+++ b/lib/mitxmako/shortcuts.py
@@ -34,6 +34,9 @@ def render_to_string(template_name, dictionary, context=None, namespace='main'):
context_dictionary.update(d)
if context:
context_dictionary.update(context)
+ ## HACK
+ ## We should remove this, and possible set COURSE_TITLE in the middleware from the session.
+ if 'COURSE_TITLE' not in context_dictionary: context_dictionary['COURSE_TITLE'] = ''
# fetch and render template
template = middleware.lookup[namespace].get_template(template_name)
return template.render(**context_dictionary)
diff --git a/lib/util/views.py b/lib/util/views.py
index 6708e7c7a4..d95f1e9a22 100644
--- a/lib/util/views.py
+++ b/lib/util/views.py
@@ -2,7 +2,6 @@ import datetime
import json
import sys
-from django.conf import settings
from django.conf import settings
from django.contrib.auth.models import User
from django.core.context_processors import csrf
@@ -61,3 +60,9 @@ def send_feedback(request):
def info(request):
''' Info page (link from main header) '''
return render_to_response("info.html", {})
+
+def mitxhome(request):
+ ''' Home page (link from main header). List of courses. '''
+ if settings.ENABLE_MULTICOURSE:
+ return render_to_response("mitxhome.html", {})
+ return info(request)
diff --git a/rakefile b/rakefile
index 6fced22658..df0db9a56d 100644
--- a/rakefile
+++ b/rakefile
@@ -29,12 +29,17 @@ INSTALL_DIR_PATH = File.join(DEPLOY_DIR, NORMALIZED_DEPLOY_NAME)
CLOBBER.include(BUILD_DIR, REPORT_DIR, 'cover*', '.coverage')
CLEAN.include("#{BUILD_DIR}/*.deb", "#{BUILD_DIR}/util")
+def select_executable(*cmds)
+ cmds.find_all{ |cmd| system("which #{cmd} > /dev/null 2>&1") }[0] || fail("No executables found from #{cmds.join(', ')}")
+end
+
+
task :default => [:pep8, :pylint, :test]
directory REPORT_DIR
task :pep8 => REPORT_DIR do
- sh("pep8 djangoapps | tee #{REPORT_DIR}/pep8.report")
+ sh("pep8 --ignore=E501 djangoapps | tee #{REPORT_DIR}/pep8.report")
end
task :pylint => REPORT_DIR do
@@ -47,7 +52,8 @@ end
task :test => REPORT_DIR do
ENV['NOSE_XUNIT_FILE'] = File.join(REPORT_DIR, "nosetests.xml")
- sh("django-admin.py test --settings=envs.test --pythonpath=. $(ls djangoapps)")
+ django_admin = ENV['DJANGO_ADMIN_PATH'] || select_executable('django-admin.py', 'django-admin')
+ sh("#{django_admin} test --settings=envs.test --pythonpath=. $(ls djangoapps)")
end
task :package do
diff --git a/settings.py b/settings.py
index e0119c6fb0..9a11c42ae6 100644
--- a/settings.py
+++ b/settings.py
@@ -8,6 +8,7 @@ import djcelery
### Dark code. Should be enabled in local settings for devel.
ENABLE_MULTICOURSE = False # set to False to disable multicourse display (see lib.util.views.mitxhome)
+QUICKEDIT = False
###
@@ -20,19 +21,11 @@ COURSE_TITLE = "Circuits and Electronics"
COURSE_DEFAULT = '6.002_Spring_2012'
-COURSE_LIST = {'6.002_Spring_2012': {'number' : '6.002x',
- 'title' : 'Circuits and Electronics',
- 'datapath': '6002x/',
- },
- '8.02_Spring_2013': {'number' : '8.02x',
- 'title' : 'Electricity & Magnetism',
- 'datapath': '802x/',
- },
- '8.01_Spring_2013': {'number' : '8.01x',
- 'title' : 'Mechanics',
- 'datapath': '801x/',
- },
- }
+COURSE_SETTINGS = {'6.002_Spring_2012': {'number' : '6.002x',
+ 'title' : 'Circuits and Electronics',
+ 'xmlpath': '6002x/',
+ }
+ }
ROOT_URLCONF = 'urls'
@@ -151,6 +144,7 @@ MIDDLEWARE_CLASSES = (
'django.contrib.messages.middleware.MessageMiddleware',
'track.middleware.TrackMiddleware',
'mitxmako.middleware.MakoMiddleware',
+ #'ssl_auth.ssl_auth.NginxProxyHeaderMiddleware', # ssl authentication behind nginx proxy
#'debug_toolbar.middleware.DebugToolbarMiddleware',
# Uncommenting the following will prevent csrf token from being re-set if you
@@ -180,6 +174,8 @@ INSTALLED_APPS = (
'util',
'masquerade',
'django_jasmine',
+ #'ssl_auth', ## Broken. Disabled for now.
+ 'multicourse', # multiple courses
# Uncomment the next line to enable the admin:
# 'django.contrib.admin',
# Uncomment the next line to enable admin documentation:
diff --git a/static/css/application.css b/static/css/application.css
index 2f21bf7b48..01d358d395 100644
--- a/static/css/application.css
+++ b/static/css/application.css
@@ -118,10 +118,10 @@ input, select {
font-style: italic; }
.clearfix:after, .topbar:after, nav.sequence-nav:after, div.book-wrapper section.book nav:after, div.wiki-wrapper section.wiki-body header:after, html body section.main-content:after, html body section.outside-app:after, div.header-wrapper header:after, div.header-wrapper header hgroup:after, div.header-wrapper header nav ul:after, footer:after, li.calc-main div#calculator_wrapper form:after, li.calc-main div#calculator_wrapper form div.input-wrapper:after, div.leanModal_box#enroll ol:after, div.course-wrapper section.course-content .problem-set:after, div.course-wrapper section.course-content section.problems-wrapper:after, div.course-wrapper section.course-content div#seq_content:after, div.course-wrapper section.course-content ol.vert-mod > li:after, section.course-content div.video-subtitles div.video-wrapper section.video-controls:after, section.course-content div.video-subtitles div.video-wrapper section.video-controls div#slider:after, section.course-content nav.sequence-bottom ul:after, section.tool-wrapper:after, section.tool-wrapper div#controlls-container:after, section.tool-wrapper div#controlls-container div.graph-controls div.music-wrapper:after, section.tool-wrapper div#controlls-container div.graph-controls div.inputs-wrapper:after, section.tool-wrapper div#controlls-container div.schematic-sliders div.top-sliders:after, div.book-wrapper section.book nav ul:after, div.info-wrapper section.updates > ol > li:after, div.info-wrapper section.handouts ol li:after, div.profile-wrapper section.course-info header:after, div.profile-wrapper section.course-info > ol > li:after, div#wiki_panel div#wiki_create_form:after, div.wiki-wrapper section.wiki-body:after, ul.badge-list li.badge:after {
+ clear: both;
content: ".";
display: block;
height: 0;
- clear: both;
visibility: hidden; }
.wrapper, html body section.main-content, html body section.outside-app, div.header-wrapper header, footer {
@@ -165,6 +165,7 @@ h1.top-header, div.course-wrapper section.course-content ol.vert-mod > li header
text-shadow: none;
-webkit-font-smoothing: antialiased; }
.button:hover, input[type="submit"]:hover, input[type="button"]:hover, button:hover, div.question-header div.question-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.answer-block div.question-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.paginator div.question-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.question-header div.answer-block div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.answer-block div.question-header div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.answer-block div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.paginator div.answer-block div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.answer-block div.paginator div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.question-header div.paginator div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.paginator div.question-header div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, div.paginator div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:hover, .button:focus, input[type="submit"]:focus, input[type="button"]:focus, button:focus, div.question-header div.question-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.answer-block div.question-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.paginator div.question-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.question-header div.answer-block div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.answer-block div.question-header div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.answer-block div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.paginator div.answer-block div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.answer-block div.paginator div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.question-header div.paginator div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.paginator div.question-header div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus, div.paginator div.answer-container div.comments-container div.comments-content div.comment div.comment-body div.comment-meta a.edit:focus {
+ border: 1px solid #555555;
-webkit-box-shadow: inset 0 1px 0 #bbbbbb, 0 0 3px #cccccc;
-moz-box-shadow: inset 0 1px 0 #bbbbbb, 0 0 3px #cccccc;
box-shadow: inset 0 1px 0 #bbbbbb, 0 0 3px #cccccc;
@@ -174,13 +175,21 @@ h1.top-header, div.course-wrapper section.course-content ol.vert-mod > li header
background-image: -moz-linear-gradient(top, #a2a2a2, #7b7b7b);
background-image: -ms-linear-gradient(top, #a2a2a2, #7b7b7b);
background-image: -o-linear-gradient(top, #a2a2a2, #7b7b7b);
- background-image: linear-gradient(top, #a2a2a2, #7b7b7b);
- border: 1px solid #555555; }
+ background-image: linear-gradient(top, #a2a2a2, #7b7b7b); }
.light-button, div.history-controls input[type="submit"], body.askbot section.main-content div.discussion-wrapper div.discussion-content a.tabula-rasa, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content a.tabula-rasa, body.askbot section.main-content div.discussion-wrapper div.discussion-content .tabula-rasa, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content .tabula-rasa, div.discussion-wrapper aside div.view-profile a, ul.question-list div.post-own-question a, div#question-list div.post-own-question a, div.question-header div.question-container div.comments-container div.comments-content form.post-comments button:last-child, div.answer-block div.question-container div.comments-container div.comments-content form.post-comments button:last-child, div.paginator div.question-container div.comments-container div.comments-content form.post-comments button:last-child, div.question-header div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:last-child, div.answer-block div.question-header div.answer-container div.comments-container div.comments-content form.post-comments button:last-child, div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:last-child, div.paginator div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:last-child, div.answer-block div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:last-child, div.question-header div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:last-child, div.paginator div.question-header div.answer-container div.comments-container div.comments-content form.post-comments button:last-child, div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:last-child, div.paginator span.next, div.paginator span.prev, form.answer-form div.preview-toggle a, form.question-form div.preview-toggle a, a.light-button, body.askbot section.main-content div.discussion-wrapper div.discussion-content a.tabula-rasa, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content a.tabula-rasa, div.discussion-wrapper aside div.view-profile a, ul.question-list div.post-own-question a, div#question-list div.post-own-question a, form.answer-form div.preview-toggle a, form.question-form div.preview-toggle a {
+ border: 1px solid #ccc;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ -ms-border-radius: 3px;
+ -o-border-radius: 3px;
+ border-radius: 3px;
-webkit-box-shadow: inset 0 1px 0 white;
-moz-box-shadow: inset 0 1px 0 white;
box-shadow: inset 0 1px 0 white;
+ color: #666;
+ cursor: pointer;
+ font: normal 14px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
background-color: white;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #eeeeee));
background-image: -webkit-linear-gradient(top, white, #eeeeee);
@@ -188,19 +197,11 @@ h1.top-header, div.course-wrapper section.course-content ol.vert-mod > li header
background-image: -ms-linear-gradient(top, white, #eeeeee);
background-image: -o-linear-gradient(top, white, #eeeeee);
background-image: linear-gradient(top, white, #eeeeee);
- -webkit-border-radius: 3px;
- -moz-border-radius: 3px;
- -ms-border-radius: 3px;
- -o-border-radius: 3px;
- border-radius: 3px;
- border: 1px solid #ccc;
padding: 4px 8px;
- color: #666;
- font: normal 14px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
text-decoration: none;
- cursor: pointer;
-webkit-font-smoothing: antialiased; }
.light-button:hover, div.history-controls input[type="submit"]:hover, body.askbot section.main-content div.discussion-wrapper div.discussion-content a.tabula-rasa:hover, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content a.tabula-rasa:hover, body.askbot section.main-content div.discussion-wrapper div.discussion-content .tabula-rasa:hover, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content .tabula-rasa:hover, div.discussion-wrapper aside div.view-profile a:hover, ul.question-list div.post-own-question a:hover, div#question-list div.post-own-question a:hover, div.question-header div.question-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.answer-block div.question-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.paginator div.question-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.question-header div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.answer-block div.question-header div.answer-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.paginator div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.answer-block div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.question-header div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.paginator div.question-header div.answer-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:hover:last-child, div.paginator span.next:hover, div.paginator span.prev:hover, form.answer-form div.preview-toggle a:hover, form.question-form div.preview-toggle a:hover, .light-button:focus, div.history-controls input[type="submit"]:focus, body.askbot section.main-content div.discussion-wrapper div.discussion-content a.tabula-rasa:focus, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content a.tabula-rasa:focus, body.askbot section.main-content div.discussion-wrapper div.discussion-content .tabula-rasa:focus, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content .tabula-rasa:focus, div.discussion-wrapper aside div.view-profile a:focus, ul.question-list div.post-own-question a:focus, div#question-list div.post-own-question a:focus, div.question-header div.question-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.answer-block div.question-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.paginator div.question-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.question-header div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.answer-block div.question-header div.answer-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.paginator div.answer-block div.answer-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.answer-block div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.question-header div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.paginator div.question-header div.answer-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.paginator div.answer-container div.comments-container div.comments-content form.post-comments button:focus:last-child, div.paginator span.next:focus, div.paginator span.prev:focus, form.answer-form div.preview-toggle a:focus, form.question-form div.preview-toggle a:focus, a.light-button:hover, body.askbot section.main-content div.discussion-wrapper div.discussion-content a.tabula-rasa:hover, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content a.tabula-rasa:hover, div.discussion-wrapper aside div.view-profile a:hover, ul.question-list div.post-own-question a:hover, div#question-list div.post-own-question a:hover, form.answer-form div.preview-toggle a:hover, form.question-form div.preview-toggle a:hover, a.light-button:focus, body.askbot section.main-content div.discussion-wrapper div.discussion-content a.tabula-rasa:focus, html body.askbot section.outside-app div.discussion-wrapper div.discussion-content a.tabula-rasa:focus, div.discussion-wrapper aside div.view-profile a:focus, ul.question-list div.post-own-question a:focus, div#question-list div.post-own-question a:focus, form.answer-form div.preview-toggle a:focus, form.question-form div.preview-toggle a:focus {
+ border: 1px solid #ccc;
background-color: white;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #e6e6e6));
background-image: -webkit-linear-gradient(top, white, #e6e6e6);
@@ -208,14 +209,13 @@ h1.top-header, div.course-wrapper section.course-content ol.vert-mod > li header
background-image: -ms-linear-gradient(top, white, #e6e6e6);
background-image: -o-linear-gradient(top, white, #e6e6e6);
background-image: linear-gradient(top, white, #e6e6e6);
- border: 1px solid #ccc;
text-decoration: none; }
.action-link a, div.question-list-header section.question-list-meta div.question-sort nav a, div.answer-controls div.answer-sort nav a {
color: #993333; }
.action-link a:hover, div.question-list-header section.question-list-meta div.question-sort nav a:hover, div.answer-controls div.answer-sort nav a:hover {
- text-decoration: none;
- color: #4d1919; }
+ color: #4d1919;
+ text-decoration: none; }
.content, div.course-wrapper section.course-content, div.book-wrapper section.book, div.info-wrapper section.updates, div.profile-wrapper section.course-info, div.gradebook-wrapper section.gradebook-content, div.wiki-wrapper section.wiki-body {
-webkit-box-shadow: inset 0 0 2px 3px #f3f3f3;
@@ -260,20 +260,20 @@ h1.top-header, div.course-wrapper section.course-content ol.vert-mod > li header
letter-spacing: 0;
text-transform: none; }
.sidebar a, section.course-index a, div.book-wrapper section.book-sidebar a, div.info-wrapper section.handouts a, div.profile-wrapper section.user-info a, div#wiki_panel a, div.discussion-wrapper aside a {
- font-style: normal;
- border: none; }
+ border: none;
+ font-style: normal; }
.sidebar .bottom-border, section.course-index .bottom-border, div.book-wrapper section.book-sidebar .bottom-border, div.info-wrapper section.handouts .bottom-border, div.profile-wrapper section.user-info .bottom-border, div#wiki_panel .bottom-border, div.discussion-wrapper aside .bottom-border, .sidebar h3, section.course-index .sidebar h3, .sidebar section.course-index h3, div.book-wrapper section.book-sidebar .sidebar h3, .sidebar div.book-wrapper section.book-sidebar h3, div.info-wrapper section.handouts .sidebar h3, .sidebar div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info .sidebar h3, .sidebar div.profile-wrapper section.user-info h3, div#wiki_panel .sidebar h3, .sidebar div#wiki_panel h3, div.discussion-wrapper aside .sidebar h3, .sidebar div.discussion-wrapper aside h3, .sidebar section.course-index h3, section.course-index .sidebar h3, section.course-index h3, div.book-wrapper section.book-sidebar section.course-index h3, section.course-index div.book-wrapper section.book-sidebar h3, div.info-wrapper section.handouts section.course-index h3, section.course-index div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info section.course-index h3, section.course-index div.profile-wrapper section.user-info h3, div#wiki_panel section.course-index h3, section.course-index div#wiki_panel h3, div.discussion-wrapper aside section.course-index h3, section.course-index div.discussion-wrapper aside h3, .sidebar div.book-wrapper section.book-sidebar h3, div.book-wrapper section.book-sidebar .sidebar h3, section.course-index div.book-wrapper section.book-sidebar h3, div.book-wrapper section.book-sidebar section.course-index h3, div.book-wrapper section.book-sidebar h3, div.info-wrapper section.handouts div.book-wrapper section.book-sidebar h3, div.book-wrapper section.book-sidebar div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info div.book-wrapper section.book-sidebar h3, div.book-wrapper section.book-sidebar div.profile-wrapper section.user-info h3, div#wiki_panel div.book-wrapper section.book-sidebar h3, div.book-wrapper section.book-sidebar div#wiki_panel h3, div.discussion-wrapper aside div.book-wrapper section.book-sidebar h3, div.book-wrapper section.book-sidebar div.discussion-wrapper aside h3, .sidebar div.info-wrapper section.handouts h3, div.info-wrapper section.handouts .sidebar h3, section.course-index div.info-wrapper section.handouts h3, div.info-wrapper section.handouts section.course-index h3, div.book-wrapper section.book-sidebar div.info-wrapper section.handouts h3, div.info-wrapper section.handouts div.book-wrapper section.book-sidebar h3, div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info div.info-wrapper section.handouts h3, div.info-wrapper section.handouts div.profile-wrapper section.user-info h3, div#wiki_panel div.info-wrapper section.handouts h3, div.info-wrapper section.handouts div#wiki_panel h3, div.discussion-wrapper aside div.info-wrapper section.handouts h3, div.info-wrapper section.handouts div.discussion-wrapper aside h3, .sidebar div.profile-wrapper section.user-info h3, div.profile-wrapper section.user-info .sidebar h3, section.course-index div.profile-wrapper section.user-info h3, div.profile-wrapper section.user-info section.course-index h3, div.book-wrapper section.book-sidebar div.profile-wrapper section.user-info h3, div.profile-wrapper section.user-info div.book-wrapper section.book-sidebar h3, div.info-wrapper section.handouts div.profile-wrapper section.user-info h3, div.profile-wrapper section.user-info div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info h3, div#wiki_panel div.profile-wrapper section.user-info h3, div.profile-wrapper section.user-info div#wiki_panel h3, div.discussion-wrapper aside div.profile-wrapper section.user-info h3, div.profile-wrapper section.user-info div.discussion-wrapper aside h3, .sidebar div#wiki_panel h3, div#wiki_panel .sidebar h3, section.course-index div#wiki_panel h3, div#wiki_panel section.course-index h3, div.book-wrapper section.book-sidebar div#wiki_panel h3, div#wiki_panel div.book-wrapper section.book-sidebar h3, div.info-wrapper section.handouts div#wiki_panel h3, div#wiki_panel div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info div#wiki_panel h3, div#wiki_panel div.profile-wrapper section.user-info h3, div#wiki_panel h3, div.discussion-wrapper aside div#wiki_panel h3, div#wiki_panel div.discussion-wrapper aside h3, .sidebar div.discussion-wrapper aside h3, div.discussion-wrapper aside .sidebar h3, section.course-index div.discussion-wrapper aside h3, div.discussion-wrapper aside section.course-index h3, div.book-wrapper section.book-sidebar div.discussion-wrapper aside h3, div.discussion-wrapper aside div.book-wrapper section.book-sidebar h3, div.info-wrapper section.handouts div.discussion-wrapper aside h3, div.discussion-wrapper aside div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info div.discussion-wrapper aside h3, div.discussion-wrapper aside div.profile-wrapper section.user-info h3, div#wiki_panel div.discussion-wrapper aside h3, div.discussion-wrapper aside div#wiki_panel h3, div.discussion-wrapper aside h3, .sidebar div#wiki_panel input[type="button"], section.course-index .sidebar div#wiki_panel input[type="button"], .sidebar div#wiki_panel section.course-index input[type="button"], div.book-wrapper section.book-sidebar .sidebar div#wiki_panel input[type="button"], .sidebar div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts .sidebar div#wiki_panel input[type="button"], .sidebar div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info .sidebar div#wiki_panel input[type="button"], .sidebar div#wiki_panel div.profile-wrapper section.user-info input[type="button"], .sidebar div#wiki_panel input[type="button"], div.discussion-wrapper aside .sidebar div#wiki_panel input[type="button"], .sidebar div#wiki_panel div.discussion-wrapper aside input[type="button"], div#wiki_panel .sidebar input[type="button"], section.course-index div#wiki_panel .sidebar input[type="button"], div#wiki_panel .sidebar section.course-index input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel .sidebar input[type="button"], div#wiki_panel .sidebar div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div#wiki_panel .sidebar input[type="button"], div#wiki_panel .sidebar div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel .sidebar input[type="button"], div#wiki_panel .sidebar div.profile-wrapper section.user-info input[type="button"], div#wiki_panel .sidebar input[type="button"], div.discussion-wrapper aside div#wiki_panel .sidebar input[type="button"], div#wiki_panel .sidebar div.discussion-wrapper aside input[type="button"], .sidebar section.course-index div#wiki_panel input[type="button"], section.course-index div#wiki_panel .sidebar input[type="button"], section.course-index div#wiki_panel input[type="button"], div.book-wrapper section.book-sidebar section.course-index div#wiki_panel input[type="button"], section.course-index div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts section.course-index div#wiki_panel input[type="button"], section.course-index div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info section.course-index div#wiki_panel input[type="button"], section.course-index div#wiki_panel div.profile-wrapper section.user-info input[type="button"], section.course-index div#wiki_panel input[type="button"], div.discussion-wrapper aside section.course-index div#wiki_panel input[type="button"], section.course-index div#wiki_panel div.discussion-wrapper aside input[type="button"], .sidebar div#wiki_panel section.course-index input[type="button"], div#wiki_panel section.course-index .sidebar input[type="button"], div#wiki_panel section.course-index input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel section.course-index input[type="button"], div#wiki_panel section.course-index div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div#wiki_panel section.course-index input[type="button"], div#wiki_panel section.course-index div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel section.course-index input[type="button"], div#wiki_panel section.course-index div.profile-wrapper section.user-info input[type="button"], div#wiki_panel section.course-index input[type="button"], div.discussion-wrapper aside div#wiki_panel section.course-index input[type="button"], div#wiki_panel section.course-index div.discussion-wrapper aside input[type="button"], .sidebar div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel .sidebar input[type="button"], section.course-index div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel section.course-index input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div.info-wrapper section.handouts div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div.discussion-wrapper aside div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel div.discussion-wrapper aside input[type="button"], .sidebar div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar .sidebar input[type="button"], section.course-index div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar section.course-index input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.discussion-wrapper aside div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar div.discussion-wrapper aside input[type="button"], .sidebar div.info-wrapper section.handouts div#wiki_panel input[type="button"], div.info-wrapper section.handouts div#wiki_panel .sidebar input[type="button"], section.course-index div.info-wrapper section.handouts div#wiki_panel input[type="button"], div.info-wrapper section.handouts div#wiki_panel section.course-index input[type="button"], div.book-wrapper section.book-sidebar div.info-wrapper section.handouts div#wiki_panel input[type="button"], div.info-wrapper section.handouts div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div#wiki_panel input[type="button"], div.profile-wrapper section.user-info div.info-wrapper section.handouts div#wiki_panel input[type="button"], div.info-wrapper section.handouts div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div.info-wrapper section.handouts div#wiki_panel input[type="button"], div.discussion-wrapper aside div.info-wrapper section.handouts div#wiki_panel input[type="button"], div.info-wrapper section.handouts div#wiki_panel div.discussion-wrapper aside input[type="button"], .sidebar div#wiki_panel div.info-wrapper section.handouts input[type="button"], div#wiki_panel div.info-wrapper section.handouts .sidebar input[type="button"], section.course-index div#wiki_panel div.info-wrapper section.handouts input[type="button"], div#wiki_panel div.info-wrapper section.handouts section.course-index input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel div.info-wrapper section.handouts input[type="button"], div#wiki_panel div.info-wrapper section.handouts div.book-wrapper section.book-sidebar input[type="button"], div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel div.info-wrapper section.handouts input[type="button"], div#wiki_panel div.info-wrapper section.handouts div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.discussion-wrapper aside div#wiki_panel div.info-wrapper section.handouts input[type="button"], div#wiki_panel div.info-wrapper section.handouts div.discussion-wrapper aside input[type="button"], .sidebar div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div.profile-wrapper section.user-info div#wiki_panel .sidebar input[type="button"], section.course-index div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div.profile-wrapper section.user-info div#wiki_panel section.course-index input[type="button"], div.book-wrapper section.book-sidebar div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div.profile-wrapper section.user-info div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div.profile-wrapper section.user-info div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div.discussion-wrapper aside div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div.profile-wrapper section.user-info div#wiki_panel div.discussion-wrapper aside input[type="button"], .sidebar div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.profile-wrapper section.user-info .sidebar input[type="button"], section.course-index div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.profile-wrapper section.user-info section.course-index input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.profile-wrapper section.user-info div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.profile-wrapper section.user-info div.info-wrapper section.handouts input[type="button"], div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div.discussion-wrapper aside div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.profile-wrapper section.user-info div.discussion-wrapper aside input[type="button"], .sidebar div#wiki_panel input[type="button"], div#wiki_panel .sidebar input[type="button"], section.course-index div#wiki_panel input[type="button"], div#wiki_panel section.course-index input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div#wiki_panel input[type="button"], div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel input[type="button"], div.discussion-wrapper aside div#wiki_panel input[type="button"], div#wiki_panel div.discussion-wrapper aside input[type="button"], .sidebar div.discussion-wrapper aside div#wiki_panel input[type="button"], div.discussion-wrapper aside div#wiki_panel .sidebar input[type="button"], section.course-index div.discussion-wrapper aside div#wiki_panel input[type="button"], div.discussion-wrapper aside div#wiki_panel section.course-index input[type="button"], div.book-wrapper section.book-sidebar div.discussion-wrapper aside div#wiki_panel input[type="button"], div.discussion-wrapper aside div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div.discussion-wrapper aside div#wiki_panel input[type="button"], div.discussion-wrapper aside div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div.discussion-wrapper aside div#wiki_panel input[type="button"], div.discussion-wrapper aside div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div.discussion-wrapper aside div#wiki_panel input[type="button"], div.discussion-wrapper aside div#wiki_panel input[type="button"], .sidebar div#wiki_panel div.discussion-wrapper aside input[type="button"], div#wiki_panel div.discussion-wrapper aside .sidebar input[type="button"], section.course-index div#wiki_panel div.discussion-wrapper aside input[type="button"], div#wiki_panel div.discussion-wrapper aside section.course-index input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel div.discussion-wrapper aside input[type="button"], div#wiki_panel div.discussion-wrapper aside div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div#wiki_panel div.discussion-wrapper aside input[type="button"], div#wiki_panel div.discussion-wrapper aside div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel div.discussion-wrapper aside input[type="button"], div#wiki_panel div.discussion-wrapper aside div.profile-wrapper section.user-info input[type="button"], div#wiki_panel div.discussion-wrapper aside input[type="button"], div#wiki_panel div.discussion-wrapper aside input[type="button"], .sidebar div.info-wrapper section.handouts header, div.info-wrapper section.handouts .sidebar header, section.course-index div.info-wrapper section.handouts header, div.info-wrapper section.handouts section.course-index header, div.book-wrapper section.book-sidebar div.info-wrapper section.handouts header, div.info-wrapper section.handouts div.book-wrapper section.book-sidebar header, div.info-wrapper section.handouts header, div.profile-wrapper section.user-info div.info-wrapper section.handouts header, div.info-wrapper section.handouts div.profile-wrapper section.user-info header, div#wiki_panel div.info-wrapper section.handouts header, div.info-wrapper section.handouts div#wiki_panel header, div.discussion-wrapper aside div.info-wrapper section.handouts header, div.info-wrapper section.handouts div.discussion-wrapper aside header, .sidebar div.profile-wrapper section.user-info header, div.profile-wrapper section.user-info .sidebar header, section.course-index div.profile-wrapper section.user-info header, div.profile-wrapper section.user-info section.course-index header, div.book-wrapper section.book-sidebar div.profile-wrapper section.user-info header, div.profile-wrapper section.user-info div.book-wrapper section.book-sidebar header, div.info-wrapper section.handouts div.profile-wrapper section.user-info header, div.profile-wrapper section.user-info div.info-wrapper section.handouts header, div.profile-wrapper section.user-info header, div#wiki_panel div.profile-wrapper section.user-info header, div.profile-wrapper section.user-info div#wiki_panel header, div.discussion-wrapper aside div.profile-wrapper section.user-info header, div.profile-wrapper section.user-info div.discussion-wrapper aside header, .sidebar div#wiki_panel h2, div#wiki_panel .sidebar h2, section.course-index div#wiki_panel h2, div#wiki_panel section.course-index h2, div.book-wrapper section.book-sidebar div#wiki_panel h2, div#wiki_panel div.book-wrapper section.book-sidebar h2, div.info-wrapper section.handouts div#wiki_panel h2, div#wiki_panel div.info-wrapper section.handouts h2, div.profile-wrapper section.user-info div#wiki_panel h2, div#wiki_panel div.profile-wrapper section.user-info h2, div#wiki_panel h2, div.discussion-wrapper aside div#wiki_panel h2, div#wiki_panel div.discussion-wrapper aside h2, .sidebar div.discussion-wrapper aside h1, div.discussion-wrapper aside .sidebar h1, section.course-index div.discussion-wrapper aside h1, div.discussion-wrapper aside section.course-index h1, div.book-wrapper section.book-sidebar div.discussion-wrapper aside h1, div.discussion-wrapper aside div.book-wrapper section.book-sidebar h1, div.info-wrapper section.handouts div.discussion-wrapper aside h1, div.discussion-wrapper aside div.info-wrapper section.handouts h1, div.profile-wrapper section.user-info div.discussion-wrapper aside h1, div.discussion-wrapper aside div.profile-wrapper section.user-info h1, div#wiki_panel div.discussion-wrapper aside h1, div.discussion-wrapper aside div#wiki_panel h1, div.discussion-wrapper aside h1 {
+ border-bottom: 1px solid #d3d3d3;
-webkit-box-shadow: 0 1px 0 #eeeeee;
-moz-box-shadow: 0 1px 0 #eeeeee;
- box-shadow: 0 1px 0 #eeeeee;
- border-bottom: 1px solid #d3d3d3; }
+ box-shadow: 0 1px 0 #eeeeee; }
@media print {
.sidebar, section.course-index, div.book-wrapper section.book-sidebar, div.info-wrapper section.handouts, div.profile-wrapper section.user-info, div#wiki_panel, div.discussion-wrapper aside {
display: none; } }
.sidebar h3, section.course-index h3, div.book-wrapper section.book-sidebar h3, div.info-wrapper section.handouts h3, div.profile-wrapper section.user-info h3, div#wiki_panel h3, div.discussion-wrapper aside h3, .sidebar div#wiki_panel input[type="button"], div#wiki_panel .sidebar input[type="button"], section.course-index div#wiki_panel input[type="button"], div#wiki_panel section.course-index input[type="button"], div.book-wrapper section.book-sidebar div#wiki_panel input[type="button"], div#wiki_panel div.book-wrapper section.book-sidebar input[type="button"], div.info-wrapper section.handouts div#wiki_panel input[type="button"], div#wiki_panel div.info-wrapper section.handouts input[type="button"], div.profile-wrapper section.user-info div#wiki_panel input[type="button"], div#wiki_panel div.profile-wrapper section.user-info input[type="button"], div#wiki_panel input[type="button"], div.discussion-wrapper aside div#wiki_panel input[type="button"], div#wiki_panel div.discussion-wrapper aside input[type="button"] {
+ background: none;
border: none;
border-bottom: 1px solid #d3d3d3;
- background: none;
color: #000;
font-weight: normal;
margin: 0;
@@ -330,8 +330,8 @@ h1.top-header, div.course-wrapper section.course-content ol.vert-mod > li header
padding: 11.326px 22.652px;
position: relative; }
.sidebar header#open_close_accordion h2, section.course-index header#open_close_accordion h2, div.book-wrapper section.book-sidebar header#open_close_accordion h2, div.info-wrapper section.handouts header#open_close_accordion h2, div.profile-wrapper section.user-info header#open_close_accordion h2, div#wiki_panel header#open_close_accordion h2, div.discussion-wrapper aside header#open_close_accordion h2 {
- padding-right: 20px;
- margin: 0; }
+ margin: 0;
+ padding-right: 20px; }
.sidebar header#open_close_accordion a, section.course-index header#open_close_accordion a, div.book-wrapper section.book-sidebar header#open_close_accordion a, div.info-wrapper section.handouts header#open_close_accordion a, div.profile-wrapper section.user-info header#open_close_accordion a, div#wiki_panel header#open_close_accordion a, div.discussion-wrapper aside header#open_close_accordion a {
background: #eeeeee url("/static/images/slide-left-icon.png") center center no-repeat;
border: 1px solid #D3D3D3;
@@ -359,10 +359,10 @@ h1.top-header, div.course-wrapper section.course-content ol.vert-mod > li header
-moz-box-shadow: inset 0 1px 0 white, inset 1px 0 0 white;
box-shadow: inset 0 1px 0 white, inset 1px 0 0 white;
font-size: 12px;
- margin: -22.652px -22.652px 22.652px;
- text-shadow: 0 1px 0 #fff;
+ height: 46px;
line-height: 46px;
- height: 46px; }
+ margin: -22.652px -22.652px 22.652px;
+ text-shadow: 0 1px 0 #fff; }
@media print {
.topbar, nav.sequence-nav, div.book-wrapper section.book nav, div.wiki-wrapper section.wiki-body header {
display: none; } }
@@ -406,12 +406,12 @@ h1.top-header, div.course-wrapper section.course-content ol.vert-mod > li header
transition-delay: 0; }
p.ie-warning {
+ background: yellow;
display: block !important;
line-height: 1.3em;
- background: yellow;
+ margin-bottom: 0;
padding: 22.652px;
- text-align: left;
- margin-bottom: 0; }
+ text-align: left; }
:focus {
outline-color: #ccc; }
@@ -441,9 +441,11 @@ img {
height: auto; }
input[type="email"], input[type="number"], input[type="password"], input[type="search"], input[type="tel"], input[type="text"], input[type="url"], input[type="color"], input[type="date"], input[type="datetime"], input[type="datetime-local"], input[type="month"], input[type="time"], input[type="week"], textarea, form#wiki_revision .CodeMirror {
+ border: 1px solid #999;
-webkit-box-shadow: 0 -1px 0 white;
-moz-box-shadow: 0 -1px 0 white;
box-shadow: 0 -1px 0 white;
+ font: 14px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
background-color: #eeeeee;
background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #eeeeee), color-stop(100%, white));
background-image: -webkit-linear-gradient(top, #eeeeee, white);
@@ -451,8 +453,6 @@ input[type="email"], input[type="number"], input[type="password"], input[type="s
background-image: -ms-linear-gradient(top, #eeeeee, white);
background-image: -o-linear-gradient(top, #eeeeee, white);
background-image: linear-gradient(top, #eeeeee, white);
- border: 1px solid #999;
- font: 14px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
padding: 4px; }
input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, textarea:focus, form#wiki_revision .CodeMirror:focus {
border-color: #993333; }
@@ -473,11 +473,11 @@ a:hover, a:focus {
html {
margin-top: 0; }
html body {
+ background: #f4f4f4;
color: #333333;
font: 14px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
- text-align: center;
margin: 0;
- background: #f4f4f4; }
+ text-align: center; }
html body section.main-content, html body section.outside-app {
background: #fff;
border: 1px solid #bbb;
@@ -488,7 +488,8 @@ html body section.main-content, html body section.outside-app {
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
- margin-top: 3px; }
+ margin-top: 3px;
+ overflow: hidden; }
@media print {
html body section.main-content, html body section.outside-app {
border-bottom: 0;
@@ -506,12 +507,13 @@ html body section.main-content, html body section.outside-app {
border-radius: 4px;
margin-top: 11.326px; } }
html body div.qtip div.ui-tooltip-content {
- border: none;
+ background: #000;
background: rgba(0, 0, 0, 0.8);
+ border: none;
color: #fff;
font: 12px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
- margin-top: -30px;
- margin-right: -20px; }
+ margin-right: -20px;
+ margin-top: -30px; }
html body section.outside-app {
max-width: 600px;
padding: 22.652px; }
@@ -614,12 +616,12 @@ div.header-wrapper header nav ul li {
margin-bottom: 0;
float: left; }
div.header-wrapper header nav ul li a {
+ border: none;
color: #fff;
display: block;
+ font-style: normal;
font-weight: bold;
- padding: 10px 22.652px 8px;
- border: none;
- font-style: normal; }
+ padding: 10px 22.652px 8px; }
@media screen and (max-width: 1020px) {
div.header-wrapper header nav ul li a {
padding: 10px 15.856px 8px; } }
@@ -631,10 +633,10 @@ div.header-wrapper header nav ul li a:hover {
width: 100%;
float: none; }
div.header-wrapper header nav ul li {
- padding: auto;
display: table-cell;
- width: 16.6666666667%;
- text-align: center; } }
+ padding: auto;
+ text-align: center;
+ width: 16.6666666667%; } }
div.header-wrapper header nav .active, div.header-wrapper header nav.courseware li.courseware a, div.header-wrapper header nav.book li.book a, div.header-wrapper header nav.info li.info a, div.header-wrapper header nav.discussion li.discussion a, div.header-wrapper header nav.wiki li.wiki a, div.header-wrapper header nav.profile li.profile a, div.header-wrapper header nav section.course-index div#accordion h3.ui-accordion-header.ui-state-active, section.course-index div#accordion div.header-wrapper header nav h3.ui-accordion-header.ui-state-active, div.header-wrapper header nav section.course-index div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], section.course-index div#accordion div#wiki_panel div.header-wrapper header nav input.ui-accordion-header.ui-state-active[type="button"], div.header-wrapper header nav div#wiki_panel section.course-index div#accordion input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel section.course-index div#accordion div.header-wrapper header nav input.ui-accordion-header.ui-state-active[type="button"], div.header-wrapper header nav.sequence-nav ol li a.seq_video_active, div.header-wrapper header nav.sequence-nav ol li a.seq_other_active, div.header-wrapper header nav.sequence-nav ol li a.seq_vertical_active, div.header-wrapper header nav.sequence-nav ol li a.seq_problem_active {
background: #F4F4F4;
border: 1px solid #26080a;
@@ -695,11 +697,11 @@ footer nav ul.social li:after {
content: none;
display: none; }
footer nav ul.social li a {
+ border-bottom: 0;
display: block;
height: 29px;
- width: 28px;
text-indent: -9999px;
- border-bottom: 0; }
+ width: 28px; }
footer nav ul.social li a:hover {
opacity: .8; }
footer nav ul.social li.twitter a {
@@ -713,7 +715,6 @@ li.calc-main {
bottom: -126px;
left: 0;
position: fixed;
- width: 100%;
-webkit-transition-property: bottom;
-moz-transition-property: bottom;
-ms-transition-property: bottom;
@@ -734,26 +735,27 @@ li.calc-main {
-ms-transition-delay: 0;
-o-transition-delay: 0;
transition-delay: 0;
- z-index: 99;
- -webkit-appearance: none; }
+ -webkit-appearance: none;
+ width: 100%;
+ z-index: 99; }
li.calc-main.open {
bottom: -36px; }
li.calc-main.open div#calculator_wrapper form div.input-wrapper div.help-wrapper dl {
display: block; }
li.calc-main a.calc {
- text-indent: -9999px;
- overflow: hidden;
- display: block;
background: url("/static/images/calc-icon.png") rgba(17, 17, 17, 0.9) no-repeat center;
border-bottom: 0;
- color: #fff;
- float: right;
- margin-right: 10px;
-webkit-border-radius: 3px 3px 0 0;
-moz-border-radius: 3px 3px 0 0;
-ms-border-radius: 3px 3px 0 0;
-o-border-radius: 3px 3px 0 0;
border-radius: 3px 3px 0 0;
+ color: #fff;
+ float: right;
+ height: 20px;
+ text-indent: -9999px;
+ overflow: hidden;
+ display: block;
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
@@ -761,26 +763,26 @@ li.calc-main a.calc {
zoom: 1;
*display: inline;
*vertical-align: auto;
+ margin-right: 10px;
padding: 8px 12px;
- width: 16px;
- height: 20px;
position: relative;
- top: -36px; }
+ top: -36px;
+ width: 16px; }
li.calc-main a.calc:hover {
opacity: .8; }
li.calc-main a.calc.closed {
background-image: url("/static/images/close-calc-icon.png"); }
li.calc-main div#calculator_wrapper {
background: rgba(17, 17, 17, 0.9);
- position: relative;
- top: -36px;
clear: both;
- max-height: 90px; }
+ max-height: 90px;
+ position: relative;
+ top: -36px; }
li.calc-main div#calculator_wrapper form {
- padding: 22.652px;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
- box-sizing: border-box; }
+ box-sizing: border-box;
+ padding: 22.652px; }
li.calc-main div#calculator_wrapper form input#calculator_button {
background: #111;
border: 1px solid #000;
@@ -848,12 +850,12 @@ li.calc-main div#calculator_wrapper form div.input-wrapper div.help-wrapper {
right: 8px;
top: 15px; }
li.calc-main div#calculator_wrapper form div.input-wrapper div.help-wrapper a {
+ background: url("/static/images/info-icon.png") center center no-repeat;
+ height: 17px;
text-indent: -9999px;
overflow: hidden;
display: block;
- width: 17px;
- height: 17px;
- background: url("/static/images/info-icon.png") center center no-repeat; }
+ width: 17px; }
li.calc-main div#calculator_wrapper form div.input-wrapper div.help-wrapper dl {
background: #fff;
-webkit-border-radius: 3px;
@@ -865,13 +867,12 @@ li.calc-main div#calculator_wrapper form div.input-wrapper div.help-wrapper dl {
-moz-box-shadow: 0 0 3px #999999;
box-shadow: 0 0 3px #999999;
color: #333;
+ display: none;
opacity: 0;
padding: 10px;
position: absolute;
right: -40px;
top: -110px;
- width: 500px;
- display: none;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
@@ -891,7 +892,8 @@ li.calc-main div#calculator_wrapper form div.input-wrapper div.help-wrapper dl {
-moz-transition-delay: 0;
-ms-transition-delay: 0;
-o-transition-delay: 0;
- transition-delay: 0; }
+ transition-delay: 0;
+ width: 500px; }
li.calc-main div#calculator_wrapper form div.input-wrapper div.help-wrapper dl.shown {
opacity: 1;
top: -115px; }
@@ -904,14 +906,14 @@ li.calc-main div#calculator_wrapper form div.input-wrapper div.help-wrapper dl d
float: left; }
#lean_overlay {
- position: fixed;
- z-index: 100;
- top: 0px;
- left: 0px;
- height: 100%;
- width: 100%;
background: #000;
- display: none; }
+ display: none;
+ height: 100%;
+ left: 0px;
+ position: fixed;
+ top: 0px;
+ width: 100%;
+ z-index: 100; }
div.leanModal_box {
background: #fff;
@@ -941,8 +943,8 @@ div.leanModal_box a.modal_close {
width: 14px;
z-index: 2; }
div.leanModal_box a.modal_close:hover {
- text-decoration: none;
- color: #993333; }
+ color: #993333;
+ text-decoration: none; }
div.leanModal_box h1 {
border-bottom: 1px solid #eee;
font-size: 24px;
@@ -955,8 +957,8 @@ div.leanModal_box#enroll {
div.leanModal_box#enroll ol {
padding-top: 22.652px; }
div.leanModal_box#enroll ol li.terms, div.leanModal_box#enroll ol li.honor-code {
- width: auto;
- float: none; }
+ float: none;
+ width: auto; }
div.leanModal_box#enroll ol li div.tip {
display: none; }
div.leanModal_box#enroll ol li:hover div.tip {
@@ -997,16 +999,16 @@ div.leanModal_box form ol li.terms, div.leanModal_box form ol li.remember {
padding-top: 22.652px;
width: auto; }
div.leanModal_box form ol li.honor-code {
- width: auto;
- float: none; }
+ float: none;
+ width: auto; }
div.leanModal_box form ol li label {
display: block;
font-weight: bold; }
div.leanModal_box form ol li input[type="email"], div.leanModal_box form ol li input[type="number"], div.leanModal_box form ol li input[type="password"], div.leanModal_box form ol li input[type="search"], div.leanModal_box form ol li input[type="tel"], div.leanModal_box form ol li input[type="text"], div.leanModal_box form ol li input[type="url"], div.leanModal_box form ol li input[type="color"], div.leanModal_box form ol li input[type="date"], div.leanModal_box form ol li input[type="datetime"], div.leanModal_box form ol li input[type="datetime-local"], div.leanModal_box form ol li input[type="month"], div.leanModal_box form ol li input[type="time"], div.leanModal_box form ol li input[type="week"], div.leanModal_box form ol li textarea, div.leanModal_box form#wiki_revision ol li .CodeMirror {
- width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
- box-sizing: border-box; }
+ box-sizing: border-box;
+ width: 100%; }
div.leanModal_box form ol li input[type="checkbox"] {
margin-right: 10px; }
div.leanModal_box form ol li ul {
@@ -1073,12 +1075,12 @@ div#login header h1 {
padding-bottom: 0;
margin-bottom: 5.663px; }
div#login ol li {
- width: auto;
- float: none; }
+ float: none;
+ width: auto; }
div.lost-password {
- text-align: left;
- margin-top: 22.652px; }
+ margin-top: 22.652px;
+ text-align: left; }
div.lost-password a {
color: #999; }
div.lost-password a:hover {
@@ -1096,11 +1098,11 @@ div#apply_name_change ul, div#change_email ul, div#unenroll ul, div#deactivate-a
div#apply_name_change ul li, div#change_email ul li, div#unenroll ul li, div#deactivate-account ul li {
margin-bottom: 11.326px; }
div#apply_name_change ul li textarea, div#apply_name_change ul li form#wiki_revision .CodeMirror, form#wiki_revision div#apply_name_change ul li .CodeMirror, div#apply_name_change ul li input[type="email"], div#apply_name_change ul li input[type="number"], div#apply_name_change ul li input[type="password"], div#apply_name_change ul li input[type="search"], div#apply_name_change ul li input[type="tel"], div#apply_name_change ul li input[type="text"], div#apply_name_change ul li input[type="url"], div#apply_name_change ul li input[type="color"], div#apply_name_change ul li input[type="date"], div#apply_name_change ul li input[type="datetime"], div#apply_name_change ul li input[type="datetime-local"], div#apply_name_change ul li input[type="month"], div#apply_name_change ul li input[type="time"], div#apply_name_change ul li input[type="week"], div#change_email ul li textarea, div#change_email ul li form#wiki_revision .CodeMirror, form#wiki_revision div#change_email ul li .CodeMirror, div#change_email ul li input[type="email"], div#change_email ul li input[type="number"], div#change_email ul li input[type="password"], div#change_email ul li input[type="search"], div#change_email ul li input[type="tel"], div#change_email ul li input[type="text"], div#change_email ul li input[type="url"], div#change_email ul li input[type="color"], div#change_email ul li input[type="date"], div#change_email ul li input[type="datetime"], div#change_email ul li input[type="datetime-local"], div#change_email ul li input[type="month"], div#change_email ul li input[type="time"], div#change_email ul li input[type="week"], div#unenroll ul li textarea, div#unenroll ul li form#wiki_revision .CodeMirror, form#wiki_revision div#unenroll ul li .CodeMirror, div#unenroll ul li input[type="email"], div#unenroll ul li input[type="number"], div#unenroll ul li input[type="password"], div#unenroll ul li input[type="search"], div#unenroll ul li input[type="tel"], div#unenroll ul li input[type="text"], div#unenroll ul li input[type="url"], div#unenroll ul li input[type="color"], div#unenroll ul li input[type="date"], div#unenroll ul li input[type="datetime"], div#unenroll ul li input[type="datetime-local"], div#unenroll ul li input[type="month"], div#unenroll ul li input[type="time"], div#unenroll ul li input[type="week"], div#deactivate-account ul li textarea, div#deactivate-account ul li form#wiki_revision .CodeMirror, form#wiki_revision div#deactivate-account ul li .CodeMirror, div#deactivate-account ul li input[type="email"], div#deactivate-account ul li input[type="number"], div#deactivate-account ul li input[type="password"], div#deactivate-account ul li input[type="search"], div#deactivate-account ul li input[type="tel"], div#deactivate-account ul li input[type="text"], div#deactivate-account ul li input[type="url"], div#deactivate-account ul li input[type="color"], div#deactivate-account ul li input[type="date"], div#deactivate-account ul li input[type="datetime"], div#deactivate-account ul li input[type="datetime-local"], div#deactivate-account ul li input[type="month"], div#deactivate-account ul li input[type="time"], div#deactivate-account ul li input[type="week"] {
- display: block;
- width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
- box-sizing: border-box; }
+ box-sizing: border-box;
+ display: block;
+ width: 100%; }
div#apply_name_change ul li textarea, div#apply_name_change ul li form#wiki_revision .CodeMirror, form#wiki_revision div#apply_name_change ul li .CodeMirror, div#change_email ul li textarea, div#change_email ul li form#wiki_revision .CodeMirror, form#wiki_revision div#change_email ul li .CodeMirror, div#unenroll ul li textarea, div#unenroll ul li form#wiki_revision .CodeMirror, form#wiki_revision div#unenroll ul li .CodeMirror, div#deactivate-account ul li textarea, div#deactivate-account ul li form#wiki_revision .CodeMirror, form#wiki_revision div#deactivate-account ul li .CodeMirror {
height: 60px; }
div#apply_name_change ul li input[type="submit"], div#change_email ul li input[type="submit"], div#unenroll ul li input[type="submit"], div#deactivate-account ul li input[type="submit"] {
@@ -2694,7 +2696,19 @@ body.courseware {
div.course-wrapper ul, div.course-wrapper ol {
list-style: none; }
div.course-wrapper section.course-content {
- overflow: hidden; }
+ overflow: hidden;
+ -webkit-border-top-right-radius: 4px;
+ -moz-border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -ms-border-top-right-radius: 4px;
+ -o-border-top-right-radius: 4px;
+ border-top-right-radius: 4px;
+ -webkit-border-bottom-right-radius: 4px;
+ -moz-border-bottom-right-radius: 4px;
+ -moz-border-radius-bottomright: 4px;
+ -ms-border-bottom-right-radius: 4px;
+ -o-border-bottom-right-radius: 4px;
+ border-bottom-right-radius: 4px; }
div.course-wrapper section.course-content h1 {
margin: 0 0 22.652px; }
div.course-wrapper section.course-content p {
@@ -2937,6 +2951,12 @@ section.course-index div#accordion h3.ui-accordion-header a, section.course-inde
section.course-index div#accordion h3.ui-accordion-header.ui-state-hover, section.course-index div#accordion div#wiki_panel input.ui-accordion-header.ui-state-hover[type="button"], div#wiki_panel section.course-index div#accordion input.ui-accordion-header.ui-state-hover[type="button"] {
border: none;
border-bottom: 1px solid #d3d3d3; }
+section.course-index div#accordion h3.ui-accordion-header.ui-state-active, section.course-index div#accordion div#wiki_panel input.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel section.course-index div#accordion input.ui-accordion-header.ui-state-active[type="button"] {
+ background-image: -webkit-linear-gradient(-90deg, #f5f5f5, #e1e1e1);
+ background-image: -moz-linear-gradient(-90deg, #f5f5f5, #e1e1e1);
+ background-image: -ms-linear-gradient(-90deg, #f5f5f5, #e1e1e1);
+ background-image: -o-linear-gradient(-90deg, #f5f5f5, #e1e1e1);
+ background-image: linear-gradient(-90deg, #f5f5f5, #e1e1e1); }
section.course-index div#accordion ul.ui-accordion-content {
-webkit-border-radius: 0;
-moz-border-radius: 0;
@@ -2950,25 +2970,104 @@ section.course-index div#accordion ul.ui-accordion-content {
border: none;
border-bottom: 1px solid #c3c3c3;
font-size: 12px;
- margin: 0; }
+ margin: 0;
+ padding: 1em 1.5em; }
section.course-index div#accordion ul.ui-accordion-content li {
- position: relative; }
-section.course-index div#accordion ul.ui-accordion-content li.active {
- font-weight: bold; }
-section.course-index div#accordion ul.ui-accordion-content li.active span.subtitle {
- font-weight: normal; }
+ background: transparent;
+ border: 1px solid transparent;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ -ms-border-radius: 4px;
+ -o-border-radius: 4px;
+ border-radius: 4px;
+ margin-bottom: 11.326px;
+ position: relative;
+ padding: 5px 36px 5px 10px; }
section.course-index div#accordion ul.ui-accordion-content li a {
text-decoration: none;
- margin-bottom: 11.326px;
display: block;
- color: #000; }
-section.course-index div#accordion ul.ui-accordion-content li a:hover {
color: #666; }
section.course-index div#accordion ul.ui-accordion-content li a p {
+ font-weight: bold;
margin-bottom: 0; }
section.course-index div#accordion ul.ui-accordion-content li a p span.subtitle {
color: #666;
+ font-weight: normal;
display: block; }
+section.course-index div#accordion ul.ui-accordion-content li:after {
+ background: transparent;
+ border-top: 1px solid #b4b4b4;
+ border-right: 1px solid #b4b4b4;
+ content: "";
+ display: block;
+ height: 12px;
+ margin-top: -6px;
+ opacity: 0;
+ position: absolute;
+ top: 50%;
+ right: 30px;
+ -webkit-transform: rotate(45deg);
+ -moz-transform: rotate(45deg);
+ -ms-transform: rotate(45deg);
+ -o-transform: rotate(45deg);
+ transform: rotate(45deg);
+ width: 12px; }
+section.course-index div#accordion ul.ui-accordion-content li:hover {
+ background-image: -webkit-linear-gradient(-90deg, rgba(245, 245, 245, 0.4), rgba(230, 230, 230, 0.4));
+ background-image: -moz-linear-gradient(-90deg, rgba(245, 245, 245, 0.4), rgba(230, 230, 230, 0.4));
+ background-image: -ms-linear-gradient(-90deg, rgba(245, 245, 245, 0.4), rgba(230, 230, 230, 0.4));
+ background-image: -o-linear-gradient(-90deg, rgba(245, 245, 245, 0.4), rgba(230, 230, 230, 0.4));
+ background-image: linear-gradient(-90deg, rgba(245, 245, 245, 0.4), rgba(230, 230, 230, 0.4));
+ border-color: #c8c8c8; }
+section.course-index div#accordion ul.ui-accordion-content li:hover:after {
+ opacity: 1;
+ right: 15px;
+ -webkit-transition-property: all;
+ -moz-transition-property: all;
+ -ms-transition-property: all;
+ -o-transition-property: all;
+ transition-property: all;
+ -webkit-transition-duration: 0.2s;
+ -moz-transition-duration: 0.2s;
+ -ms-transition-duration: 0.2s;
+ -o-transition-duration: 0.2s;
+ transition-duration: 0.2s;
+ -webkit-transition-timing-function: linear;
+ -moz-transition-timing-function: linear;
+ -ms-transition-timing-function: linear;
+ -o-transition-timing-function: linear;
+ transition-timing-function: linear;
+ -webkit-transition-delay: 0;
+ -moz-transition-delay: 0;
+ -ms-transition-delay: 0;
+ -o-transition-delay: 0;
+ transition-delay: 0; }
+section.course-index div#accordion ul.ui-accordion-content li:hover > a p {
+ color: #333; }
+section.course-index div#accordion ul.ui-accordion-content li:active {
+ -webkit-box-shadow: inset 0 1px 14px 0 rgba(0, 0, 0, 0.1);
+ -moz-box-shadow: inset 0 1px 14px 0 rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 1px 14px 0 rgba(0, 0, 0, 0.1);
+ top: 1px; }
+section.course-index div#accordion ul.ui-accordion-content li:active:after {
+ opacity: 1;
+ right: 15px; }
+section.course-index div#accordion ul.ui-accordion-content li.active {
+ background: #f0f0f0;
+ background-image: -webkit-linear-gradient(-90deg, #f5f5f5, #e6e6e6);
+ background-image: -moz-linear-gradient(-90deg, #f5f5f5, #e6e6e6);
+ background-image: -ms-linear-gradient(-90deg, #f5f5f5, #e6e6e6);
+ background-image: -o-linear-gradient(-90deg, #f5f5f5, #e6e6e6);
+ background-image: linear-gradient(-90deg, #f5f5f5, #e6e6e6);
+ border-color: #c8c8c8;
+ font-weight: bold; }
+section.course-index div#accordion ul.ui-accordion-content li.active > a p {
+ color: #333; }
+section.course-index div#accordion ul.ui-accordion-content li.active span.subtitle {
+ font-weight: normal; }
+section.course-index div#accordion ul.ui-accordion-content li.active:after {
+ opacity: 1;
+ right: 15px; }
@-moz-document url-prefix() {
a.add-fullscreen {
@@ -2999,13 +3098,13 @@ section.course-content .dullify, section.course-content div.video-subtitles div.
section.course-content .dullify:hover, section.course-content div.video-subtitles div.video-wrapper section.video-controls ul.vcr:hover, section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls:hover {
opacity: 1; }
section.course-content div.video-subtitles {
- zoom: 1;
- padding: 6px 22.652px;
- margin: 0 -22.652px;
- border-top: 1px solid #e1e1e1;
- border-bottom: 1px solid #e1e1e1;
background: #f3f3f3;
- display: block; }
+ border-bottom: 1px solid #e1e1e1;
+ border-top: 1px solid #e1e1e1;
+ zoom: 1;
+ display: block;
+ margin: 0 -22.652px;
+ padding: 6px 22.652px; }
section.course-content div.video-subtitles:before, section.course-content div.video-subtitles:after {
content: "";
display: table; }
@@ -3013,49 +3112,49 @@ section.course-content div.video-subtitles:after {
clear: both; }
section.course-content div.video-subtitles div.video-wrapper {
float: left;
- width: 65.761%;
- margin-right: 2.717%; }
+ margin-right: 2.717%;
+ width: 65.761%; }
section.course-content div.video-subtitles div.video-wrapper div.video-player {
- position: relative;
+ height: 0;
+ overflow: hidden;
padding-bottom: 56.25%;
padding-top: 30px;
- height: 0;
- overflow: hidden; }
+ position: relative; }
section.course-content div.video-subtitles div.video-wrapper div.video-player object {
+ height: 100%;
+ left: 0;
position: absolute;
top: 0;
- left: 0;
- width: 100%;
- height: 100%; }
+ width: 100%; }
section.course-content div.video-subtitles div.video-wrapper div.video-player iframe#html5_player {
border: none;
display: none;
+ height: 100%;
+ left: 0;
position: absolute;
top: 0;
- left: 0;
- width: 100%;
- height: 100%; }
+ width: 100%; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls {
background: #333;
- position: relative;
border: 1px solid #000;
border-top: 0;
- color: #ccc; }
+ color: #ccc;
+ position: relative; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls:hover ul, section.course-content div.video-subtitles div.video-wrapper section.video-controls:hover div {
opacity: 1; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div#slider {
+ background: #c2c2c2;
+ border: none;
+ border-bottom: 1px solid #000;
-webkit-border-radius: 0;
-moz-border-radius: 0;
-ms-border-radius: 0;
-o-border-radius: 0;
border-radius: 0;
+ border-top: 1px solid #000;
-webkit-box-shadow: inset 0 1px 0 #eeeeee, 0 1px 0 #555555;
-moz-box-shadow: inset 0 1px 0 #eeeeee, 0 1px 0 #555555;
box-shadow: inset 0 1px 0 #eeeeee, 0 1px 0 #555555;
- background: #c2c2c2;
- border: none;
- border-top: 1px solid #000;
- border-bottom: 1px solid #000;
height: 7px;
-webkit-transition-property: height, 2s, ease-in-out;
-moz-transition-property: height, 2s, ease-in-out;
@@ -3097,29 +3196,36 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
font: bold 12px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
margin-bottom: 6px;
margin-right: 0;
+ overflow: visible;
padding: 4px;
text-align: center;
- -webkit-font-smoothing: antialiased;
text-shadow: 0 -1px 0 #732626;
- overflow: visible; }
+ -webkit-font-smoothing: antialiased; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div#slider .ui-tooltip.qtip .ui-tooltip-content::after {
- content: " ";
- width: 7px;
- height: 7px;
- display: block;
- position: absolute;
+ background: #993333;
+ border-bottom: 1px solid #4d1919;
+ border-right: 1px solid #4d1919;
bottom: -5px;
+ content: " ";
+ display: block;
+ height: 7px;
left: 50%;
margin-left: -3px;
+ position: absolute;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
- background: #993333;
- border-right: 1px solid #4d1919;
- border-bottom: 1px solid #4d1919; }
+ width: 7px; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div#slider a.ui-slider-handle {
+ background: #993333 url(/static/images/slider-handle.png) center center no-repeat;
+ -webkit-background-size: 50%;
+ -moz-background-size: 50%;
+ -ms-background-size: 50%;
+ -o-background-size: 50%;
+ background-size: 50%;
+ border: 1px solid #4d1919;
-webkit-border-radius: 15px;
-moz-border-radius: 15px;
-ms-border-radius: 15px;
@@ -3128,13 +3234,10 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
-webkit-box-shadow: inset 0 1px 0 #bf4040;
-moz-box-shadow: inset 0 1px 0 #bf4040;
box-shadow: inset 0 1px 0 #bf4040;
- background: #993333 url(/static/images/slider-handle.png) center center no-repeat;
- border: 1px solid #4d1919;
cursor: pointer;
height: 15px;
margin-left: -7px;
top: -4px;
- width: 15px;
-webkit-transition-property: height, 2s, ease-in-out;
-moz-transition-property: height, 2s, ease-in-out;
-ms-transition-property: height, 2s, ease-in-out;
@@ -3155,34 +3258,29 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
-ms-transition-delay: 0;
-o-transition-delay: 0;
transition-delay: 0;
- -webkit-background-size: 50%;
- -moz-background-size: 50%;
- -ms-background-size: 50%;
- -o-background-size: 50%;
- background-size: 50%; }
+ width: 15px; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div#slider a.ui-slider-handle:focus, section.course-content div.video-subtitles div.video-wrapper section.video-controls div#slider a.ui-slider-handle:hover {
background-color: #bf4040;
outline: none; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls ul.vcr {
float: left;
- margin-right: 22.652px;
list-style: none;
+ margin-right: 22.652px;
padding: 0; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls ul.vcr li {
float: left;
margin-bottom: 0; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls ul.vcr li a {
+ border-bottom: none;
+ border-right: 1px solid #000;
-webkit-box-shadow: 1px 0 0 #555555;
-moz-box-shadow: 1px 0 0 #555555;
box-shadow: 1px 0 0 #555555;
- border-bottom: none;
- border-right: 1px solid #000;
- display: block;
cursor: pointer;
+ display: block;
line-height: 46px;
padding: 0 16.989px;
text-indent: -9999px;
- width: 14px;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
@@ -3202,7 +3300,8 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
-moz-transition-delay: 0;
-ms-transition-delay: 0;
-o-transition-delay: 0;
- transition-delay: 0; }
+ transition-delay: 0;
+ width: 14px; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls ul.vcr li a.play {
background: url("/static/images/play-icon.png") center center no-repeat; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls ul.vcr li a.play:hover {
@@ -3212,9 +3311,9 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
section.course-content div.video-subtitles div.video-wrapper section.video-controls ul.vcr li a.pause:hover {
background-color: #444; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls ul.vcr li div#vidtime {
- padding-left: 16.989px;
font-weight: bold;
line-height: 46px;
+ padding-left: 16.989px;
-webkit-font-smoothing: antialiased; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls {
float: right; }
@@ -3224,12 +3323,13 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
background: url("/static/images/closed-arrow.png") 10px center no-repeat;
border-left: 1px solid #000;
border-right: 1px solid #000;
- display: block;
-webkit-box-shadow: 1px 0 0 #555555, inset 1px 0 0 #555555;
-moz-box-shadow: 1px 0 0 #555555, inset 1px 0 0 #555555;
box-shadow: 1px 0 0 #555555, inset 1px 0 0 #555555;
zoom: 1;
+ color: #fff;
cursor: pointer;
+ display: block;
line-height: 46px;
margin-right: 0;
padding-left: 15px;
@@ -3255,8 +3355,7 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
-o-transition-delay: 0;
transition-delay: 0;
-webkit-font-smoothing: antialiased;
- width: 110px;
- color: #fff; }
+ width: 110px; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a:before, section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a:after {
content: "";
display: table; }
@@ -3265,19 +3364,19 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a.open {
background: url("/static/images/open-arrow.png") 10px center no-repeat; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a.open ol#video_speeds {
- opacity: 1;
- display: block; }
+ display: block;
+ opacity: 1; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a h3, section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a div#wiki_panel input[type="button"], div#wiki_panel section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a input[type="button"] {
color: #999;
+ float: left;
font-size: 12px;
font-weight: normal;
- float: left;
letter-spacing: 1px;
padding: 0 5.663px 0 11.326px;
text-transform: uppercase; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a p.active {
- font-weight: bold;
float: left;
+ font-weight: bold;
margin-bottom: 0;
padding: 0 11.326px 0 0; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a ol#video_speeds {
@@ -3286,12 +3385,11 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
-webkit-box-shadow: inset 1px 0 0 #555555, 0 3px 0 #444444;
-moz-box-shadow: inset 1px 0 0 #555555, 0 3px 0 #444444;
box-shadow: inset 1px 0 0 #555555, 0 3px 0 #444444;
- left: -1px;
display: none;
+ left: -1px;
+ opacity: 0;
position: absolute;
top: 0;
- width: 100%;
- z-index: 10;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
@@ -3312,7 +3410,8 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
-ms-transition-delay: 0;
-o-transition-delay: 0;
transition-delay: 0;
- opacity: 0; }
+ width: 100%;
+ z-index: 10; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a ol#video_speeds li {
border-bottom: 1px solid #000;
-webkit-box-shadow: 0 1px 0 #555555;
@@ -3325,16 +3424,16 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
font-weight: bold; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a ol#video_speeds li:last-child {
border-bottom: 0;
- margin-top: 0;
-webkit-box-shadow: none;
-moz-box-shadow: none;
- box-shadow: none; }
+ box-shadow: none;
+ margin-top: 0; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a ol#video_speeds li:hover {
- color: #aaa;
- background-color: #666; }
+ background-color: #666;
+ color: #aaa; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls div.speeds a:hover {
- opacity: 1;
- background-color: #444; }
+ background-color: #444;
+ opacity: 1; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls a.add-fullscreen {
background: url(/static/images/fullscreen.png) center no-repeat;
border-right: 1px solid #000;
@@ -3370,21 +3469,21 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
transition-delay: 0;
width: 30px; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls a.add-fullscreen:hover {
+ background-color: #444;
color: #fff;
- text-decoration: none;
- background-color: #444; }
+ text-decoration: none; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls a.hide-subtitles {
- float: left;
- display: block;
- padding: 0 11.326px;
- margin-left: 0;
- color: #797979;
- line-height: 46px;
- width: 30px;
- text-indent: -9999px;
- font-weight: 800;
background: url("/static/images/cc.png") center no-repeat;
- -webkit-font-smoothing: antialiased;
+ color: #797979;
+ display: block;
+ float: left;
+ font-weight: 800;
+ line-height: 46px;
+ margin-left: 0;
+ opacity: 1;
+ padding: 0 11.326px;
+ position: relative;
+ text-indent: -9999px;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
@@ -3405,12 +3504,12 @@ section.course-content div.video-subtitles div.video-wrapper section.video-contr
-ms-transition-delay: 0;
-o-transition-delay: 0;
transition-delay: 0;
- opacity: 1;
- position: relative; }
+ -webkit-font-smoothing: antialiased;
+ width: 30px; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls a.hide-subtitles:hover {
+ background-color: #444;
color: #fff;
- text-decoration: none;
- background-color: #444; }
+ text-decoration: none; }
section.course-content div.video-subtitles div.video-wrapper section.video-controls div.secondary-controls a.hide-subtitles.off {
opacity: .7; }
section.course-content div.video-subtitles div.video-wrapper:hover section.video-controls ul, section.course-content div.video-subtitles div.video-wrapper:hover section.video-controls div {
@@ -3430,10 +3529,10 @@ section.course-content div.video-subtitles div.video-wrapper:hover section.video
width: 20px; }
section.course-content div.video-subtitles ol.subtitles {
float: left;
- width: 31.522%;
- padding-top: 10px;
max-height: 460px;
- overflow: hidden; }
+ overflow: hidden;
+ padding-top: 10px;
+ width: 31.522%; }
section.course-content div.video-subtitles ol.subtitles li {
border: 0;
color: #666;
@@ -3472,35 +3571,35 @@ section.course-content div.video-subtitles ol.subtitles li div:empty {
section.course-content div.video-subtitles.closed div.video-wrapper {
width: 100%; }
section.course-content div.video-subtitles.closed ol.subtitles {
- width: 0px;
- height: 0; }
+ height: 0;
+ width: 0px; }
section.course-content div.video-subtitles.fullscreen {
background: rgba(0, 0, 0, 0.95);
border: 0;
- margin: 0;
bottom: 0;
height: 100%;
left: 0;
+ margin: 0;
max-height: 100%;
+ overflow: hidden;
padding: 0;
position: fixed;
top: 0;
width: 100%;
- z-index: 999;
- overflow: hidden; }
+ z-index: 999; }
section.course-content div.video-subtitles.fullscreen.closed ol.subtitles {
- width: auto;
height: auto;
- right: -31.984%; }
+ right: -31.984%;
+ width: auto; }
section.course-content div.video-subtitles.fullscreen a.exit {
- position: absolute;
- top: 20px;
- left: 20px;
color: #aaa;
- text-transform: uppercase;
- letter-spacing: 1px;
+ display: none;
font-style: 12px;
- display: none; }
+ left: 20px;
+ letter-spacing: 1px;
+ position: absolute;
+ text-transform: uppercase;
+ top: 20px; }
section.course-content div.video-subtitles.fullscreen a.exit::after {
content: "✖";
display: -moz-inline-box;
@@ -3516,28 +3615,28 @@ section.course-content div.video-subtitles.fullscreen a.exit:hover {
section.course-content div.video-subtitles.fullscreen div.tc-wrapper div.video-wrapper {
width: 100%; }
section.course-content div.video-subtitles.fullscreen div.tc-wrapper object#myytplayer, section.course-content div.video-subtitles.fullscreen div.tc-wrapper iframe {
+ bottom: 0;
height: 100%;
+ left: 0;
+ overflow: hidden;
position: fixed;
- top: 0;
- bottom: 0;
- left: 0;
- overflow: hidden; }
+ top: 0; }
section.course-content div.video-subtitles.fullscreen div.tc-wrapper section.video-controls {
- position: absolute;
bottom: 0;
left: 0;
+ position: absolute;
width: 100%;
z-index: 9999; }
section.course-content div.video-subtitles.fullscreen ol.subtitles {
- position: fixed;
- top: 0;
- right: 0;
+ background: rgba(0, 0, 0, 0.8);
bottom: 0;
height: 100%;
- background: rgba(0, 0, 0, 0.8);
- padding: 22.652px;
- max-width: 23.482%;
max-height: 100%;
+ max-width: 23.482%;
+ padding: 22.652px;
+ position: fixed;
+ right: 0;
+ top: 0;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
@@ -3567,19 +3666,21 @@ div.course-wrapper.closed section.course-content div.video-subtitles ol.subtitle
max-height: 577px; }
nav.sequence-nav {
- -webkit-box-sizing: border-box;
- -moz-box-sizing: border-box;
- box-sizing: border-box;
+ border-bottom: 1px solid #e4d080;
margin-bottom: 22.652px;
position: relative;
- top: -1px; }
+ -webkit-border-top-right-radius: 4px;
+ -moz-border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -ms-border-top-right-radius: 4px;
+ -o-border-top-right-radius: 4px;
+ border-top-right-radius: 4px; }
nav.sequence-nav ol {
- border-bottom: 1px solid #e4d080;
- border-top: 1px solid #e4d080;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
display: table;
+ height: 100%;
padding-right: 8.696%;
width: 100%; }
nav.sequence-nav ol li {
@@ -3617,6 +3718,7 @@ nav.sequence-nav ol li a {
display: block;
height: 17px;
padding: 15px 0 14px;
+ position: relative;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
@@ -3665,25 +3767,27 @@ nav.sequence-nav ol li a.seq_vertical_visited, nav.sequence-nav ol li a.seq_prob
nav.sequence-nav ol li a.seq_vertical_active, nav.sequence-nav ol li a.seq_problem_active {
background-image: url("/static/images/sequence-nav/list-icon-current.png");
background-position: center; }
-nav.sequence-nav ol li p {
+nav.sequence-nav ol li a p {
background: #333;
color: #fff;
+ display: none;
line-height: 22.652px;
- margin: 0px 0 0 -5px;
+ left: 0px;
opacity: 0;
padding: 6px;
position: absolute;
+ top: 48px;
text-shadow: 0 -1px 0 black;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
-o-transition-property: all;
transition-property: all;
- -webkit-transition-duration: 0.6s;
- -moz-transition-duration: 0.6s;
- -ms-transition-duration: 0.6s;
- -o-transition-duration: 0.6s;
- transition-duration: 0.6s;
+ -webkit-transition-duration: 0.1s;
+ -moz-transition-duration: 0.1s;
+ -ms-transition-duration: 0.1s;
+ -o-transition-duration: 0.1s;
+ transition-duration: 0.1s;
-webkit-transition-timing-function: cubic-bezier(0.77, 0, 0.175, 1);
-moz-transition-timing-function: cubic-bezier(0.77, 0, 0.175, 1);
-ms-transition-timing-function: cubic-bezier(0.77, 0, 0.175, 1);
@@ -3694,16 +3798,13 @@ nav.sequence-nav ol li p {
-ms-transition-delay: 0;
-o-transition-delay: 0;
transition-delay: 0;
- white-space: pre-wrap;
+ white-space: pre;
z-index: 99; }
-nav.sequence-nav ol li p.shown {
- margin-top: 4px;
- opacity: 1; }
-nav.sequence-nav ol li p:empty {
+nav.sequence-nav ol li a p:empty {
background: none; }
-nav.sequence-nav ol li p:empty::after {
+nav.sequence-nav ol li a p:empty::after {
display: none; }
-nav.sequence-nav ol li p::after {
+nav.sequence-nav ol li a p::after {
background: #333;
content: " ";
display: block;
@@ -3717,9 +3818,13 @@ nav.sequence-nav ol li p::after {
-o-transform: rotate(45deg);
transform: rotate(45deg);
width: 10px; }
+nav.sequence-nav ol li a:hover p {
+ display: block;
+ margin-top: 4px;
+ opacity: 1; }
nav.sequence-nav ul {
- margin-right: 1px;
list-style: none !important;
+ height: 100%;
position: absolute;
right: 0;
top: 0;
@@ -3754,7 +3859,13 @@ nav.sequence-nav ul li.prev a {
nav.sequence-nav ul li.prev a:hover {
background-color: none; }
nav.sequence-nav ul li.next a {
- background-image: url("/static/images/sequence-nav/next-icon.png"); }
+ background-image: url("/static/images/sequence-nav/next-icon.png");
+ -webkit-border-top-right-radius: 4px;
+ -moz-border-top-right-radius: 4px;
+ -moz-border-radius-topright: 4px;
+ -ms-border-top-right-radius: 4px;
+ -o-border-top-right-radius: 4px;
+ border-top-right-radius: 4px; }
nav.sequence-nav ul li.next a:hover {
background-color: none; }
@@ -3834,14 +3945,14 @@ section.course-content nav.sequence-bottom ul li.next a:hover {
section.tool-wrapper {
background: #073642;
- border-top: 1px solid #000203;
border-bottom: 1px solid #000203;
+ border-top: 1px solid #000203;
-webkit-box-shadow: inset 0 0 0 4px #084150;
-moz-box-shadow: inset 0 0 0 4px #084150;
box-shadow: inset 0 0 0 4px #084150;
- margin: 22.652px -22.652px 0;
color: #839496;
- display: table; }
+ display: table;
+ margin: 22.652px -22.652px 0; }
section.tool-wrapper div#graph-container {
background: none;
-webkit-box-sizing: border-box;
@@ -3863,40 +3974,40 @@ section.tool-wrapper div#graph-container canvas {
width: 100%; }
section.tool-wrapper div#graph-container ul.ui-tabs-nav {
background: #062e39;
- margin: -22.652px -22.652px 0;
- padding: 0;
- position: relative;
- width: 110%;
+ border-bottom: 1px solid #03181d;
-webkit-border-radius: 0;
-moz-border-radius: 0;
-ms-border-radius: 0;
-o-border-radius: 0;
border-radius: 0;
- border-bottom: 1px solid #03181d; }
+ margin: -22.652px -22.652px 0;
+ padding: 0;
+ position: relative;
+ width: 110%; }
section.tool-wrapper div#graph-container ul.ui-tabs-nav li {
- margin-bottom: 0;
background: none;
- color: #fff;
border: none;
-webkit-border-radius: 0;
-moz-border-radius: 0;
-ms-border-radius: 0;
-o-border-radius: 0;
- border-radius: 0; }
+ border-radius: 0;
+ color: #fff;
+ margin-bottom: 0; }
section.tool-wrapper div#graph-container ul.ui-tabs-nav li.ui-tabs-selected {
- border-right: 1px solid #03181d;
+ background-color: #073642;
border-left: 1px solid #03181d;
- background-color: #073642; }
+ border-right: 1px solid #03181d; }
section.tool-wrapper div#graph-container ul.ui-tabs-nav li.ui-tabs-selected:first-child {
border-left: none; }
section.tool-wrapper div#graph-container ul.ui-tabs-nav li.ui-tabs-selected a {
color: #eee8d5; }
section.tool-wrapper div#graph-container ul.ui-tabs-nav li a {
border: none;
+ color: #839496;
font: bold 12px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
- text-transform: uppercase;
letter-spacing: 1px;
- color: #839496; }
+ text-transform: uppercase; }
section.tool-wrapper div#graph-container ul.ui-tabs-nav li a:hover {
color: #eee8d5; }
section.tool-wrapper div#controlls-container {
@@ -3913,14 +4024,14 @@ section.tool-wrapper div#controlls-container {
vertical-align: top;
width: 48.641%; }
section.tool-wrapper div#controlls-container div.graph-controls div.music-wrapper {
- padding: 0 0 22.652px;
- margin-bottom: 22.652px;
border-bottom: 1px solid #021014;
-webkit-box-shadow: 0 1px 0 #083e4b;
-moz-box-shadow: 0 1px 0 #083e4b;
- box-shadow: 0 1px 0 #083e4b; }
+ box-shadow: 0 1px 0 #083e4b;
+ margin-bottom: 22.652px;
+ padding: 0 0 22.652px; }
section.tool-wrapper div#controlls-container div.graph-controls div.music-wrapper input#playButton {
- display: block;
+ border-color: #001317;
border: 1px solid #3d5962;
-webkit-border-radius: 3px;
-moz-border-radius: 3px;
@@ -3944,9 +4055,9 @@ section.tool-wrapper div#controlls-container div.graph-controls div.music-wrappe
padding: 6px 18px 7px;
text-shadow: 0 1px 0 #31505a;
-webkit-background-clip: padding-box;
- font: bold 14px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
- border-color: #001317;
- float: right; }
+ display: block;
+ float: right;
+ font: bold 14px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif; }
section.tool-wrapper div#controlls-container div.graph-controls div.music-wrapper input#playButton:hover {
-webkit-box-shadow: inset 0 1px 0 0 #778589;
-moz-box-shadow: inset 0 1px 0 0 #778589;
@@ -4015,20 +4126,21 @@ section.tool-wrapper div#controlls-container div.graph-controls div.music-wrappe
-moz-box-shadow: none;
box-shadow: none; }
section.tool-wrapper div#controlls-container div.graph-controls div.inputs-wrapper {
- zoom: 1;
- margin-bottom: 22.652px;
- padding: 0 0 22.652px;
- margin-bottom: 22.652px;
border-bottom: 1px solid #021014;
-webkit-box-shadow: 0 1px 0 #083e4b;
-moz-box-shadow: 0 1px 0 #083e4b;
- box-shadow: 0 1px 0 #083e4b; }
+ box-shadow: 0 1px 0 #083e4b;
+ zoom: 1;
+ margin-bottom: 22.652px;
+ margin-bottom: 22.652px;
+ padding: 0 0 22.652px; }
section.tool-wrapper div#controlls-container div.graph-controls div.inputs-wrapper:before, section.tool-wrapper div#controlls-container div.graph-controls div.inputs-wrapper:after {
content: "";
display: table; }
section.tool-wrapper div#controlls-container div.graph-controls div.inputs-wrapper:after {
clear: both; }
section.tool-wrapper div#controlls-container div.graph-controls p {
+ font-weight: bold;
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
@@ -4037,9 +4149,8 @@ section.tool-wrapper div#controlls-container div.graph-controls p {
*display: inline;
*vertical-align: auto;
margin: 0;
- -webkit-font-smoothing: antialiased;
- font-weight: bold;
- text-shadow: 0 -1px 0 #021014; }
+ text-shadow: 0 -1px 0 #021014;
+ -webkit-font-smoothing: antialiased; }
section.tool-wrapper div#controlls-container div.graph-controls ul {
display: -moz-inline-box;
-moz-box-orient: vertical;
@@ -4061,20 +4172,20 @@ section.tool-wrapper div#controlls-container div.graph-controls ul li {
section.tool-wrapper div#controlls-container div.graph-controls ul li input {
margin-right: 5px; }
section.tool-wrapper div#controlls-container div.graph-controls div#graph-listen {
- margin-top: 8px;
- margin-right: 20px;
display: block;
- text-align: right;
float: left;
- margin-bottom: 0; }
+ margin-bottom: 0;
+ margin-right: 20px;
+ margin-top: 8px;
+ text-align: right; }
section.tool-wrapper div#controlls-container label {
-webkit-border-radius: 2px;
-moz-border-radius: 2px;
-ms-border-radius: 2px;
-o-border-radius: 2px;
border-radius: 2px;
- font-weight: bold;
color: #fff;
+ font-weight: bold;
padding: 3px;
-webkit-font-smoothing: antialiased; }
section.tool-wrapper div#controlls-container label[for="vinCheckbox"], section.tool-wrapper div#controlls-container label[for="vinRadioButton"] {
@@ -4088,13 +4199,14 @@ section.tool-wrapper div#controlls-container label[for="vcCheckbox"], section.to
section.tool-wrapper div#controlls-container label[for="vlCheckbox"], section.tool-wrapper div#controlls-container label[for="vlRadioButton"] {
color: #a26784; }
section.tool-wrapper div#controlls-container div.schematic-sliders div.top-sliders {
- padding: 0 0 22.652px;
- margin-bottom: 22.652px;
border-bottom: 1px solid #021014;
-webkit-box-shadow: 0 1px 0 #083e4b;
-moz-box-shadow: 0 1px 0 #083e4b;
- box-shadow: 0 1px 0 #083e4b; }
+ box-shadow: 0 1px 0 #083e4b;
+ margin-bottom: 22.652px;
+ padding: 0 0 22.652px; }
section.tool-wrapper div#controlls-container div.schematic-sliders div.top-sliders select#musicTypeSelect {
+ font: 16px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
@@ -4102,9 +4214,9 @@ section.tool-wrapper div#controlls-container div.schematic-sliders div.top-slide
zoom: 1;
*display: inline;
*vertical-align: auto;
- font: 16px "Open Sans", "Lucida Grande", "Lucida Sans Unicode", "Lucida Sans", Geneva, Verdana, sans-serif;
margin-bottom: 0; }
section.tool-wrapper div#controlls-container div.schematic-sliders div.top-sliders p {
+ font-weight: bold;
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
@@ -4112,24 +4224,23 @@ section.tool-wrapper div#controlls-container div.schematic-sliders div.top-slide
zoom: 1;
*display: inline;
*vertical-align: auto;
- -webkit-font-smoothing: antialiased;
- text-shadow: 0 -1px 0 #021014;
margin: 0 11.326px 22.652px 0;
- font-weight: bold; }
+ text-shadow: 0 -1px 0 #021014;
+ -webkit-font-smoothing: antialiased; }
section.tool-wrapper div#controlls-container div.schematic-sliders div.slider-label {
- margin-bottom: 11.326px;
font-weight: bold;
+ margin-bottom: 11.326px;
text-shadow: 0 -1px 0 #021014;
-webkit-font-smoothing: antialiased; }
section.tool-wrapper div#controlls-container div.schematic-sliders div.slider {
margin-bottom: 22.652px; }
section.tool-wrapper div#controlls-container div.schematic-sliders div.slider.ui-slider-horizontal {
- height: 0.4em;
background: #00232c;
border: 1px solid #000b0d;
-webkit-box-shadow: none;
-moz-box-shadow: none;
- box-shadow: none; }
+ box-shadow: none;
+ height: 0.4em; }
section.tool-wrapper div#controlls-container div.schematic-sliders div.slider .ui-slider-handle {
background: #637c84 url("/static/images/amplifier-slider-handle.png") center no-repeat;
border: 1px solid #000b0d;
@@ -4154,13 +4265,13 @@ div.book-wrapper section.book-sidebar ul#booknav li {
background: none;
padding-left: 30px; }
div.book-wrapper section.book-sidebar ul#booknav li div.hitarea {
- margin-left: -22px;
background-image: url("/static/images/treeview-default.gif");
+ margin-left: -22px;
position: relative;
top: 4px; }
div.book-wrapper section.book-sidebar ul#booknav li div.hitarea:hover {
- opacity: 0.6;
- filter: alpha(opacity=60); }
+ filter: alpha(opacity=60);
+ opacity: 0.6; }
div.book-wrapper section.book-sidebar ul#booknav li ul {
background: none; }
div.book-wrapper section.book-sidebar ul#booknav > li {
@@ -4172,22 +4283,22 @@ div.book-wrapper section.book-sidebar ul#booknav > li {
div.book-wrapper section.book nav a {
padding: 0 22.652px; }
div.book-wrapper section.book nav ul li.last {
- float: left;
- display: block; }
+ display: block;
+ float: left; }
div.book-wrapper section.book nav ul li.last a {
+ border-left: 0;
+ border-right: 1px solid #e4d080;
-webkit-box-shadow: inset -1px 0 0 #faf7e9;
-moz-box-shadow: inset -1px 0 0 #faf7e9;
- box-shadow: inset -1px 0 0 #faf7e9;
- border-right: 1px solid #e4d080;
- border-left: 0; }
+ box-shadow: inset -1px 0 0 #faf7e9; }
div.book-wrapper section.book nav ul li.next {
display: block;
float: right; }
div.book-wrapper section.book nav.bottom-nav {
- margin-top: 22.652px;
- margin-bottom: -22.652px;
border-bottom: 0;
- border-top: 1px solid #EDDFAA; }
+ border-top: 1px solid #EDDFAA;
+ margin-bottom: -22.652px;
+ margin-top: 22.652px; }
div.book-wrapper section.book section.page {
text-align: center; }
div.book-wrapper section.book section.page img {
@@ -4200,15 +4311,15 @@ div.book-wrapper.closed section.book-sidebar header#open_close_accordion {
div.book-wrapper.closed section.book-sidebar header#open_close_accordion a {
background-image: url("/static/images/slide-right-icon.png"); }
div.book-wrapper.closed section.book-sidebar header#open_close_accordion h2 {
- visibility: hidden;
- width: 10px;
- padding: 0; }
-div.book-wrapper.closed section.book-sidebar ul#booknav {
- visibility: hidden;
- width: 10px;
padding: 0;
+ visibility: hidden;
+ width: 10px; }
+div.book-wrapper.closed section.book-sidebar ul#booknav {
+ max-height: 100px;
overflow: hidden;
- max-height: 100px; }
+ padding: 0;
+ visibility: hidden;
+ width: 10px; }
div.book-wrapper.closed section.course-content {
width: 97.773%; }
@@ -4217,83 +4328,83 @@ div.info-wrapper section.updates > p {
div.info-wrapper section.updates > ol {
list-style: none; }
div.info-wrapper section.updates > ol > li {
- padding-bottom: 11.326px;
+ border-bottom: 1px solid #e3e3e3;
margin-bottom: 11.326px;
- border-bottom: 1px solid #e3e3e3; }
+ padding-bottom: 11.326px; }
div.info-wrapper section.updates > ol > li:first-child {
- padding: 11.326px;
- margin: 0 -11.326px 22.652px;
background: #f6efd4;
- border-bottom: 1px solid #eddfaa; }
+ border-bottom: 1px solid #eddfaa;
+ margin: 0 -11.326px 22.652px;
+ padding: 11.326px; }
div.info-wrapper section.updates > ol > li h2 {
float: left;
- width: 20.109%;
- margin: 0 2.024% 0 0; }
+ margin: 0 2.024% 0 0;
+ width: 20.109%; }
div.info-wrapper section.updates > ol > li section.update-description {
float: left;
- width: 77.174%;
- margin-bottom: 0; }
+ margin-bottom: 0;
+ width: 77.174%; }
div.info-wrapper section.updates > ol > li section.update-description li {
margin-bottom: 11.326px; }
div.info-wrapper section.updates > ol > li section.update-description p:last-child {
margin-bottom: 0; }
div.info-wrapper section.handouts {
+ border-left: 1px solid #d3d3d3;
-webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0;
-ms-border-radius: 0 4px 4px 0;
-o-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0;
- border-right: 0;
- border-left: 1px solid #d3d3d3; }
+ border-right: 0; }
div.info-wrapper section.handouts header {
padding: 11.326px 16.989px; }
div.info-wrapper section.handouts header h1 {
font-size: 18px;
margin: 0; }
div.info-wrapper section.handouts header p {
- margin-bottom: 0;
- margin-top: 4px;
+ color: #666;
font-size: 12px;
- color: #666; }
+ margin-bottom: 0;
+ margin-top: 4px; }
div.info-wrapper section.handouts ol {
- list-style: none;
- background: none; }
+ background: none;
+ list-style: none; }
div.info-wrapper section.handouts ol li {
+ background: none;
+ border-bottom: 1px solid #d3d3d3;
-webkit-box-shadow: 0 1px 0 #eeeeee;
-moz-box-shadow: 0 1px 0 #eeeeee;
box-shadow: 0 1px 0 #eeeeee;
- border-bottom: 1px solid #d3d3d3;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
padding: 7px 16.989px;
- background: none;
position: relative; }
div.info-wrapper section.handouts ol li.expandable h4, div.info-wrapper section.handouts ol li.collapsable h4 {
- padding-left: 18px;
font-style: 14px;
- font-weight: normal; }
+ font-weight: normal;
+ padding-left: 18px; }
div.info-wrapper section.handouts ol li ul {
background: none;
margin: 7px -16.989px 0; }
div.info-wrapper section.handouts ol li ul li {
- padding-left: 34.989px;
+ border-bottom: 0;
+ border-top: 1px solid #d3d3d3;
-webkit-box-shadow: inset 0 1px 0 #eeeeee;
-moz-box-shadow: inset 0 1px 0 #eeeeee;
box-shadow: inset 0 1px 0 #eeeeee;
- border-top: 1px solid #d3d3d3;
- border-bottom: 0; }
+ padding-left: 34.989px; }
div.info-wrapper section.handouts ol li:hover {
background-color: #e9e9e9; }
div.info-wrapper section.handouts ol li div.hitarea {
background-image: url("/static/images/treeview-default.gif");
- width: 100%;
- height: 100%;
- max-height: 20px;
display: block;
- position: absolute;
+ height: 100%;
left: 16.989px;
- margin-left: 0; }
+ margin-left: 0;
+ max-height: 20px;
+ position: absolute;
+ width: 100%; }
div.info-wrapper section.handouts ol li div.hitarea:hover {
opacity: 0.6;
filter: alpha(opacity=60); }
@@ -4303,21 +4414,22 @@ div.info-wrapper section.handouts ol li div.hitarea.collapsable-hitarea {
background-position: -64px -21px; }
div.info-wrapper section.handouts ol li h3, div.info-wrapper section.handouts ol li div#wiki_panel input[type="button"], div#wiki_panel div.info-wrapper section.handouts ol li input[type="button"] {
border-bottom: 0;
- text-transform: uppercase;
- font-weight: bold;
- color: #999;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
- font-size: 12px; }
+ color: #999;
+ font-size: 12px;
+ font-weight: bold;
+ text-transform: uppercase; }
div.info-wrapper section.handouts ol li p {
- margin: 0;
- text-transform: none;
+ font-size: 14px;
letter-spacing: 0;
- font-size: 14px; }
+ margin: 0;
+ text-transform: none; }
div.info-wrapper section.handouts ol li p a {
padding-right: 8px; }
div.info-wrapper section.handouts ol li p a:before {
+ color: #ccc;
content: "•";
display: -moz-inline-box;
-moz-box-orient: vertical;
@@ -4326,73 +4438,20 @@ div.info-wrapper section.handouts ol li p a:before {
zoom: 1;
*display: inline;
*vertical-align: auto;
- padding-right: 8px;
- color: #ccc; }
+ padding-right: 8px; }
div.info-wrapper section.handouts ol li p a:first-child:before {
content: "";
padding-right: 0; }
div.info-wrapper section.handouts ol li a {
- -webkit-transition-property: all;
- -moz-transition-property: all;
- -ms-transition-property: all;
- -o-transition-property: all;
- transition-property: all;
- -webkit-transition-duration: 0.15s;
- -moz-transition-duration: 0.15s;
- -ms-transition-duration: 0.15s;
- -o-transition-duration: 0.15s;
- transition-duration: 0.15s;
- -webkit-transition-timing-function: ease-out;
- -moz-transition-timing-function: ease-out;
- -ms-transition-timing-function: ease-out;
- -o-transition-timing-function: ease-out;
- transition-timing-function: ease-out;
- -webkit-transition-delay: 0;
- -moz-transition-delay: 0;
- -ms-transition-delay: 0;
- -o-transition-delay: 0;
- transition-delay: 0;
color: #4d4d4d;
- text-decoration: none;
display: -moz-inline-box;
-moz-box-orient: vertical;
display: inline-block;
vertical-align: baseline;
zoom: 1;
*display: inline;
- *vertical-align: auto; }
-div.info-wrapper section.handouts ol li a:hover {
- color: #993333; }
-
-div.profile-wrapper {
- color: #000; }
-div.profile-wrapper section.user-info {
- -webkit-border-radius: 0px 4px 4px 0;
- -moz-border-radius: 0px 4px 4px 0;
- -ms-border-radius: 0px 4px 4px 0;
- -o-border-radius: 0px 4px 4px 0;
- border-radius: 0px 4px 4px 0;
- border-left: 1px solid #d3d3d3;
- border-right: 0; }
-div.profile-wrapper section.user-info header {
- padding: 11.326px 22.652px;
- margin: 0; }
-div.profile-wrapper section.user-info header h1 {
- font-size: 18px;
- margin: 0;
- padding-right: 30px; }
-div.profile-wrapper section.user-info header a {
- position: absolute;
- top: 13px;
- right: 11.326px;
- text-transform: uppercase;
- font-size: 12px;
- color: #999; }
-div.profile-wrapper section.user-info header a:hover {
- color: #555; }
-div.profile-wrapper section.user-info ul {
- list-style: none; }
-div.profile-wrapper section.user-info ul li {
+ *vertical-align: auto;
+ text-decoration: none;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
@@ -4412,16 +4471,68 @@ div.profile-wrapper section.user-info ul li {
-moz-transition-delay: 0;
-ms-transition-delay: 0;
-o-transition-delay: 0;
- transition-delay: 0;
- color: #4d4d4d;
- display: block;
- text-decoration: none;
+ transition-delay: 0; }
+div.info-wrapper section.handouts ol li a:hover {
+ color: #993333; }
+
+div.profile-wrapper {
+ color: #000; }
+div.profile-wrapper section.user-info {
+ border-left: 1px solid #d3d3d3;
+ -webkit-border-radius: 0px 4px 4px 0;
+ -moz-border-radius: 0px 4px 4px 0;
+ -ms-border-radius: 0px 4px 4px 0;
+ -o-border-radius: 0px 4px 4px 0;
+ border-radius: 0px 4px 4px 0;
+ border-right: 0; }
+div.profile-wrapper section.user-info header {
+ margin: 0;
+ padding: 11.326px 22.652px; }
+div.profile-wrapper section.user-info header h1 {
+ font-size: 18px;
+ margin: 0;
+ padding-right: 30px; }
+div.profile-wrapper section.user-info header a {
+ color: #999;
+ font-size: 12px;
+ position: absolute;
+ right: 11.326px;
+ text-transform: uppercase;
+ top: 13px; }
+div.profile-wrapper section.user-info header a:hover {
+ color: #555; }
+div.profile-wrapper section.user-info ul {
+ list-style: none; }
+div.profile-wrapper section.user-info ul li {
+ border-bottom: 1px solid #d3d3d3;
-webkit-box-shadow: 0 1px 0 #eeeeee;
-moz-box-shadow: 0 1px 0 #eeeeee;
box-shadow: 0 1px 0 #eeeeee;
+ color: #4d4d4d;
+ display: block;
padding: 7px 22.652px;
- border-bottom: 1px solid #d3d3d3;
- position: relative; }
+ position: relative;
+ text-decoration: none;
+ -webkit-transition-property: all;
+ -moz-transition-property: all;
+ -ms-transition-property: all;
+ -o-transition-property: all;
+ transition-property: all;
+ -webkit-transition-duration: 0.15s;
+ -moz-transition-duration: 0.15s;
+ -ms-transition-duration: 0.15s;
+ -o-transition-duration: 0.15s;
+ transition-duration: 0.15s;
+ -webkit-transition-timing-function: ease-out;
+ -moz-transition-timing-function: ease-out;
+ -ms-transition-timing-function: ease-out;
+ -o-transition-timing-function: ease-out;
+ transition-timing-function: ease-out;
+ -webkit-transition-delay: 0;
+ -moz-transition-delay: 0;
+ -ms-transition-delay: 0;
+ -o-transition-delay: 0;
+ transition-delay: 0; }
div.profile-wrapper section.user-info ul li div#location_sub, div.profile-wrapper section.user-info ul li div#language_sub {
font-weight: bold;
display: -moz-inline-box;
@@ -4434,29 +4545,29 @@ div.profile-wrapper section.user-info ul li div#location_sub, div.profile-wrappe
div.profile-wrapper section.user-info ul li div#location_sub form, div.profile-wrapper section.user-info ul li div#language_sub form {
width: 100%; }
div.profile-wrapper section.user-info ul li div#location_sub input[type="text"], div.profile-wrapper section.user-info ul li div#language_sub input[type="text"] {
- margin: 11.326px 0;
- width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
- box-sizing: border-box; }
+ box-sizing: border-box;
+ margin: 11.326px 0;
+ width: 100%; }
div.profile-wrapper section.user-info ul li div#location_sub:empty, div.profile-wrapper section.user-info ul li div#language_sub:empty {
padding: 0; }
div.profile-wrapper section.user-info ul li div#description {
font-size: 12px; }
div.profile-wrapper section.user-info ul li a#change_language, div.profile-wrapper section.user-info ul li a#change_location, div.profile-wrapper section.user-info ul li a.edit-email, div.profile-wrapper section.user-info ul li a.name-edit, div.profile-wrapper section.user-info ul li a.email-edit {
+ color: #999;
+ font-size: 12px;
position: absolute;
- top: 9px;
right: 11.326px;
text-transform: uppercase;
- font-size: 12px;
- color: #999; }
+ top: 9px; }
div.profile-wrapper section.user-info ul li a#change_language:hover, div.profile-wrapper section.user-info ul li a#change_location:hover, div.profile-wrapper section.user-info ul li a.edit-email:hover, div.profile-wrapper section.user-info ul li a.name-edit:hover, div.profile-wrapper section.user-info ul li a.email-edit:hover {
color: #555; }
div.profile-wrapper section.user-info ul li p {
+ color: #999;
font-size: 12px;
margin-bottom: 0;
- margin-top: 4px;
- color: #999; }
+ margin-top: 4px; }
div.profile-wrapper section.user-info ul li a.deactivate {
color: #aaa;
font-style: italic; }
@@ -4485,16 +4596,16 @@ div.profile-wrapper section.user-info div#change_password_pop {
color: #4D4D4D;
padding: 7px 22.652px; }
div.profile-wrapper section.user-info div#change_password_pop h2 {
- margin-top: 0;
+ font-size: 14px;
font-weight: bold;
- text-transform: uppercase;
- font-size: 14px; }
+ margin-top: 0;
+ text-transform: uppercase; }
div.profile-wrapper section.course-info header h1 {
- margin: 0;
- float: left; }
+ float: left;
+ margin: 0; }
div.profile-wrapper section.course-info div#grade-detail-graph {
- width: 100%;
- min-height: 300px; }
+ min-height: 300px;
+ width: 100%; }
div.profile-wrapper section.course-info > ol {
border-top: 1px solid #e3e3e3;
list-style: none;
@@ -4643,10 +4754,15 @@ section.wiki-body div#wiki_article center {
div#wiki_panel {
overflow: auto; }
div#wiki_panel h2 {
- padding: 11.326px 22.652px;
font-size: 18px;
- margin: 0; }
+ margin: 0;
+ padding: 11.326px 22.652px; }
div#wiki_panel input[type="button"] {
+ color: #4d4d4d;
+ font-size: 14px;
+ margin: 0 !important;
+ padding: 7px 22.652px;
+ text-align: left;
-webkit-transition-property: all;
-moz-transition-property: all;
-ms-transition-property: all;
@@ -4667,11 +4783,6 @@ div#wiki_panel input[type="button"] {
-ms-transition-delay: 0;
-o-transition-delay: 0;
transition-delay: 0;
- color: #4d4d4d;
- font-size: 14px;
- margin: 0 !important;
- padding: 7px 22.652px;
- text-align: left;
width: 100%; }
div#wiki_panel input[type="button"]:hover {
-webkit-box-shadow: 0 1px 0 white;
@@ -4679,26 +4790,26 @@ div#wiki_panel input[type="button"]:hover {
box-shadow: 0 1px 0 white;
background: #efefef; }
div#wiki_panel ul li.search {
+ border-bottom: 1px solid #d3d3d3;
-webkit-box-shadow: 0 1px 0 #eeeeee;
-moz-box-shadow: 0 1px 0 #eeeeee;
box-shadow: 0 1px 0 #eeeeee;
- border-bottom: 1px solid #d3d3d3;
padding: 7px 22.652px; }
div#wiki_panel ul li.search label {
display: none; }
div#wiki_panel ul li.create-article h3 a, div#wiki_panel ul li.create-article input[type="button"] a {
padding: 7px 22.652px; }
div#wiki_panel div#wiki_create_form {
- padding: 15px;
background: #d6d6d6;
- border-bottom: 1px solid #bbb; }
+ border-bottom: 1px solid #bbb;
+ padding: 15px; }
div#wiki_panel div#wiki_create_form input[type="text"] {
- margin-bottom: 6px;
- display: block;
- width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
- box-sizing: border-box; }
+ box-sizing: border-box;
+ display: block;
+ margin-bottom: 6px;
+ width: 100%; }
div#wiki_panel div#wiki_create_form ul {
list-style: none; }
div#wiki_panel div#wiki_create_form ul li {
@@ -4709,8 +4820,8 @@ div#wiki_panel div#wiki_create_form ul li#cancel {
form#wiki_revision {
float: left;
- width: 65.761%;
- margin-right: 2.717%; }
+ margin-right: 2.717%;
+ width: 65.761%; }
form#wiki_revision label {
display: block;
margin-bottom: 7px; }
@@ -4734,34 +4845,34 @@ form#wiki_revision input[type="text"] {
display: block;
width: 50%; }
form#wiki_revision #submit_delete {
+ background: none;
+ border: none;
-webkit-box-shadow: none;
-moz-box-shadow: none;
box-shadow: none;
- background: none;
- border: none;
color: #999;
float: right;
- text-decoration: underline;
- font-weight: normal; }
+ font-weight: normal;
+ text-decoration: underline; }
form#wiki_revision input[type="submit"] {
margin-top: 20px; }
#wiki_edit_instructions {
+ color: #666;
float: left;
- width: 31.522%;
margin-top: 22.652px;
- color: #666; }
+ width: 31.522%; }
#wiki_edit_instructions:hover {
color: #333; }
#wiki_edit_instructions .markdown-example {
background-color: #e3e3e3;
- text-shadow: 0 1px 0 #fff;
+ line-height: 1.0;
+ margin: 5px 0 7px;
padding-top: 5px;
padding-right: 2px;
padding-bottom: 5px;
padding-left: 5px;
- margin: 5px 0 7px;
- line-height: 1.0; }
+ text-shadow: 0 1px 0 #fff; }
div.wiki-wrapper {
display: table;
@@ -4769,18 +4880,18 @@ div.wiki-wrapper {
div.wiki-wrapper section.wiki-body {
position: relative; }
div.wiki-wrapper section.wiki-body header {
- height: 46px;
-webkit-box-shadow: inset 0 1px 0 white;
-moz-box-shadow: inset 0 1px 0 white;
- box-shadow: inset 0 1px 0 white; }
+ box-shadow: inset 0 1px 0 white;
+ height: 46px; }
div.wiki-wrapper section.wiki-body header:empty {
- display: none !important;
- border-bottom: 0; }
+ border-bottom: 0;
+ display: none !important; }
div.wiki-wrapper section.wiki-body header p {
- float: left;
- margin-bottom: 0;
color: #937b1f;
+ float: left;
line-height: 46px;
+ margin-bottom: 0;
padding-left: 22.652px; }
div.wiki-wrapper section.wiki-body header ul {
float: right;
@@ -4803,8 +4914,8 @@ div.wiki-wrapper section.wiki-body header ul li input[type="button"] {
box-shadow: inset 1px 0 0 #faf7e9;
color: #292309;
display: block;
- font-weight: normal;
font-size: 12px;
+ font-weight: normal;
letter-spacing: 1px;
line-height: 46px;
margin: 0;
@@ -4852,22 +4963,22 @@ div.wiki-wrapper section.wiki-body h2.wiki-title {
width: 25.815%; }
@media screen and (max-width:900px) {
div.wiki-wrapper section.wiki-body h2.wiki-title {
+ border-right: 0;
display: block;
- width: auto;
- border-right: 0; } }
+ width: auto; } }
@media print {
div.wiki-wrapper section.wiki-body h2.wiki-title {
+ border-right: 0;
display: block;
- width: auto;
- border-right: 0; } }
+ width: auto; } }
div.wiki-wrapper section.wiki-body p {
line-height: 1.6em; }
div.wiki-wrapper section.wiki-body section.results {
+ border-left: 1px dashed #ddd;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
display: inline-block;
- border-left: 1px dashed #ddd;
float: left;
padding-left: 10px;
width: 71.467%; }
@@ -4881,8 +4992,8 @@ div.wiki-wrapper section.wiki-body section.results {
@media print {
div.wiki-wrapper section.wiki-body section.results {
display: block;
- width: auto;
- padding: 0; }
+ padding: 0;
+ width: auto; }
div.wiki-wrapper section.wiki-body section.results canvas, div.wiki-wrapper section.wiki-body section.results img {
page-break-inside: avoid; } }
div.wiki-wrapper section.wiki-body section.results ul.article-list {
@@ -4892,10 +5003,10 @@ div.wiki-wrapper section.wiki-body section.results ul.article-list {
div.wiki-wrapper section.wiki-body section.results ul.article-list {
margin-left: 0px; } }
div.wiki-wrapper section.wiki-body section.results ul.article-list li {
+ border-bottom: 1px solid #eee;
list-style: none;
margin: 0;
- padding: 10px 0;
- border-bottom: 1px solid #eee; }
+ padding: 10px 0; }
div.wiki-wrapper section.wiki-body section.results ul.article-list li:last-child {
border-bottom: 0; }
div.wiki-wrapper section.wiki-body section.results ul.article-list li h3, div.wiki-wrapper section.wiki-body section.results ul.article-list li div#wiki_panel input[type="button"], div#wiki_panel div.wiki-wrapper section.wiki-body section.results ul.article-list li input[type="button"] {
@@ -4928,18 +5039,18 @@ div.history-controls {
section.help.main-content, html body section.help.outside-app {
padding: 22.652px; }
section.help.main-content h1, html body section.help.outside-app h1 {
- margin-top: 0;
+ border-bottom: 1px solid #ddd;
margin-bottom: 22.652px;
- padding-bottom: 22.652px;
- border-bottom: 1px solid #ddd; }
+ margin-top: 0;
+ padding-bottom: 22.652px; }
section.help.main-content p, html body section.help.outside-app p {
max-width: 700px; }
section.help.main-content h2, html body section.help.outside-app h2 {
margin-top: 0; }
section.help.main-content section.self-help, html body section.help.outside-app section.self-help {
+ float: left;
margin-bottom: 22.652px;
margin-right: 2.024%;
- float: left;
width: 48.988%; }
section.help.main-content section.self-help ul, html body section.help.outside-app section.self-help ul {
margin-left: 4.132%; }
@@ -4949,14 +5060,14 @@ section.help.main-content section.help-email, html body section.help.outside-app
float: left;
width: 48.988%; }
section.help.main-content section.help-email dl, html body section.help.outside-app section.help-email dl {
- margin-bottom: 22.652px;
- display: block; }
+ display: block;
+ margin-bottom: 22.652px; }
section.help.main-content section.help-email dl dd, html body section.help.outside-app section.help-email dl dd {
margin-bottom: 22.652px; }
section.help.main-content section.help-email dl dt, html body section.help.outside-app section.help-email dl dt {
- font-weight: bold;
- float: left;
clear: left;
+ float: left;
+ font-weight: bold;
width: 30.579%; }
.badge-context-toggle.active, div.header-wrapper header nav.courseware li.courseware a.badge-context-toggle, div.header-wrapper header nav.book li.book a.badge-context-toggle, div.header-wrapper header nav.info li.info a.badge-context-toggle, div.header-wrapper header nav.discussion li.discussion a.badge-context-toggle, div.header-wrapper header nav.wiki li.wiki a.badge-context-toggle, div.header-wrapper header nav.profile li.profile a.badge-context-toggle, section.course-index div#accordion h3.badge-context-toggle.ui-accordion-header.ui-state-active, section.course-index div#accordion div#wiki_panel input.badge-context-toggle.ui-accordion-header.ui-state-active[type="button"], div#wiki_panel section.course-index div#accordion input.badge-context-toggle.ui-accordion-header.ui-state-active[type="button"], nav.sequence-nav ol li a.badge-context-toggle.seq_video_active, nav.sequence-nav ol li a.badge-context-toggle.seq_other_active, nav.sequence-nav ol li a.badge-context-toggle.seq_vertical_active, nav.sequence-nav ol li a.badge-context-toggle.seq_problem_active {
diff --git a/static/css/marketing.css b/static/css/marketing.css
index 221a7582a0..9a59931e02 100644
--- a/static/css/marketing.css
+++ b/static/css/marketing.css
@@ -735,14 +735,14 @@ section.index-content section.staff h1 {
margin-top: 25.888px; }
#lean_overlay {
- position: fixed;
- z-index: 100;
- top: 0px;
- left: 0px;
- height: 100%;
- width: 100%;
background: #000;
- display: none; }
+ display: none;
+ height: 100%;
+ left: 0px;
+ position: fixed;
+ top: 0px;
+ width: 100%;
+ z-index: 100; }
div.leanModal_box {
background: #fff;
@@ -772,8 +772,8 @@ div.leanModal_box a.modal_close {
width: 14px;
z-index: 2; }
div.leanModal_box a.modal_close:hover {
- text-decoration: none;
- color: #993333; }
+ color: #993333;
+ text-decoration: none; }
div.leanModal_box h1 {
border-bottom: 1px solid #eee;
font-size: 24px;
@@ -786,8 +786,8 @@ div.leanModal_box#enroll {
div.leanModal_box#enroll ol {
padding-top: 25.888px; }
div.leanModal_box#enroll ol li.terms, div.leanModal_box#enroll ol li.honor-code {
- width: auto;
- float: none; }
+ float: none;
+ width: auto; }
div.leanModal_box#enroll ol li div.tip {
display: none; }
div.leanModal_box#enroll ol li:hover div.tip {
@@ -828,16 +828,16 @@ div.leanModal_box form ol li.terms, div.leanModal_box form ol li.remember {
padding-top: 25.888px;
width: auto; }
div.leanModal_box form ol li.honor-code {
- width: auto;
- float: none; }
+ float: none;
+ width: auto; }
div.leanModal_box form ol li label {
display: block;
font-weight: bold; }
div.leanModal_box form ol li input[type="email"], div.leanModal_box form ol li input[type="number"], div.leanModal_box form ol li input[type="password"], div.leanModal_box form ol li input[type="search"], div.leanModal_box form ol li input[type="tel"], div.leanModal_box form ol li input[type="text"], div.leanModal_box form ol li input[type="url"], div.leanModal_box form ol li input[type="color"], div.leanModal_box form ol li input[type="date"], div.leanModal_box form ol li input[type="datetime"], div.leanModal_box form ol li input[type="datetime-local"], div.leanModal_box form ol li input[type="month"], div.leanModal_box form ol li input[type="time"], div.leanModal_box form ol li input[type="week"], div.leanModal_box form ol li textarea {
- width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
- box-sizing: border-box; }
+ box-sizing: border-box;
+ width: 100%; }
div.leanModal_box form ol li input[type="checkbox"] {
margin-right: 10px; }
div.leanModal_box form ol li ul {
@@ -904,12 +904,12 @@ div#login header h1 {
padding-bottom: 0;
margin-bottom: 6.472px; }
div#login ol li {
- width: auto;
- float: none; }
+ float: none;
+ width: auto; }
div.lost-password {
- text-align: left;
- margin-top: 25.888px; }
+ margin-top: 25.888px;
+ text-align: left; }
div.lost-password a {
color: #999; }
div.lost-password a:hover {
@@ -927,11 +927,11 @@ div#apply_name_change ul, div#change_email ul, div#unenroll ul, div#deactivate-a
div#apply_name_change ul li, div#change_email ul li, div#unenroll ul li, div#deactivate-account ul li {
margin-bottom: 12.944px; }
div#apply_name_change ul li textarea, div#apply_name_change ul li input[type="email"], div#apply_name_change ul li input[type="number"], div#apply_name_change ul li input[type="password"], div#apply_name_change ul li input[type="search"], div#apply_name_change ul li input[type="tel"], div#apply_name_change ul li input[type="text"], div#apply_name_change ul li input[type="url"], div#apply_name_change ul li input[type="color"], div#apply_name_change ul li input[type="date"], div#apply_name_change ul li input[type="datetime"], div#apply_name_change ul li input[type="datetime-local"], div#apply_name_change ul li input[type="month"], div#apply_name_change ul li input[type="time"], div#apply_name_change ul li input[type="week"], div#change_email ul li textarea, div#change_email ul li input[type="email"], div#change_email ul li input[type="number"], div#change_email ul li input[type="password"], div#change_email ul li input[type="search"], div#change_email ul li input[type="tel"], div#change_email ul li input[type="text"], div#change_email ul li input[type="url"], div#change_email ul li input[type="color"], div#change_email ul li input[type="date"], div#change_email ul li input[type="datetime"], div#change_email ul li input[type="datetime-local"], div#change_email ul li input[type="month"], div#change_email ul li input[type="time"], div#change_email ul li input[type="week"], div#unenroll ul li textarea, div#unenroll ul li input[type="email"], div#unenroll ul li input[type="number"], div#unenroll ul li input[type="password"], div#unenroll ul li input[type="search"], div#unenroll ul li input[type="tel"], div#unenroll ul li input[type="text"], div#unenroll ul li input[type="url"], div#unenroll ul li input[type="color"], div#unenroll ul li input[type="date"], div#unenroll ul li input[type="datetime"], div#unenroll ul li input[type="datetime-local"], div#unenroll ul li input[type="month"], div#unenroll ul li input[type="time"], div#unenroll ul li input[type="week"], div#deactivate-account ul li textarea, div#deactivate-account ul li input[type="email"], div#deactivate-account ul li input[type="number"], div#deactivate-account ul li input[type="password"], div#deactivate-account ul li input[type="search"], div#deactivate-account ul li input[type="tel"], div#deactivate-account ul li input[type="text"], div#deactivate-account ul li input[type="url"], div#deactivate-account ul li input[type="color"], div#deactivate-account ul li input[type="date"], div#deactivate-account ul li input[type="datetime"], div#deactivate-account ul li input[type="datetime-local"], div#deactivate-account ul li input[type="month"], div#deactivate-account ul li input[type="time"], div#deactivate-account ul li input[type="week"] {
- display: block;
- width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
- box-sizing: border-box; }
+ box-sizing: border-box;
+ display: block;
+ width: 100%; }
div#apply_name_change ul li textarea, div#change_email ul li textarea, div#unenroll ul li textarea, div#deactivate-account ul li textarea {
height: 60px; }
div#apply_name_change ul li input[type="submit"], div#change_email ul li input[type="submit"], div#unenroll ul li input[type="submit"], div#deactivate-account ul li input[type="submit"] {
diff --git a/templates/courseware.html b/templates/courseware.html
index 547c43e221..050172626a 100644
--- a/templates/courseware.html
+++ b/templates/courseware.html
@@ -12,10 +12,6 @@
%block>
diff --git a/templates/quickedit.html b/templates/quickedit.html
new file mode 100644
index 0000000000..c08c5e3f51
--- /dev/null
+++ b/templates/quickedit.html
@@ -0,0 +1,95 @@
+
+
+
+
+
+
+
+
+
+<%include file="mathjax_include.html" />
+
+
+
+
+
+
+
+
+
+
+## -----------------------------------------------------------------------------
+## information and i4x PSL code
+
+
+