From a8037f03e5b65b06786a2470cfa8854b87ddff7d Mon Sep 17 00:00:00 2001 From: Piotr Mitros Date: Thu, 15 Dec 2011 07:51:07 -0500 Subject: [PATCH] Laying ground work for formula support. Adding Anant's content --- .hgignore | 4 ++ auth/models.py | 4 ++ auth/views.py | 16 +++++++ courseware/capa_module.py | 2 +- courseware/capa_problem.py | 20 ++++++--- .../circuits/superposition-ex-e2-fig.gif | Bin 0 -> 3275 bytes courseware/static/js/mathjax/MathJax.js | 30 +++++++++++++ courseware/static/js/video_player.js | 24 ++++++++++ courseware/views.py | 42 ++++++++++-------- courseware/x_module.py | 5 ++- urls.py | 1 + 11 files changed, 123 insertions(+), 25 deletions(-) create mode 100644 courseware/static/circuits/superposition-ex-e2-fig.gif create mode 100644 courseware/static/js/mathjax/MathJax.js diff --git a/.hgignore b/.hgignore index d65858b8d9..041a2a98b0 100644 --- a/.hgignore +++ b/.hgignore @@ -2,3 +2,7 @@ syntax: glob *.pyc *~ database.sqlite +courseware/static/js/mathjax/* + +syntax: regexp + diff --git a/auth/models.py b/auth/models.py index 44ab6b37bb..4695bef5cb 100644 --- a/auth/models.py +++ b/auth/models.py @@ -3,6 +3,10 @@ from django.contrib.auth.models import User import uuid class UserProfile(models.Model): + ## CRITICAL TODO/SECURITY + # Sanitize all fields. + # This is not visible to other users, but could introduce holes + # later user = models.ForeignKey(User, unique=True, db_index=True) name = models.TextField(blank=True) language = models.TextField(blank=True) diff --git a/auth/views.py b/auth/views.py index 9c9529314d..60f79a8af7 100644 --- a/auth/views.py +++ b/auth/views.py @@ -46,6 +46,22 @@ def logout_user(request): logout(request) return redirect('/') +def change_setting(request): + if not request.user.is_authenticated(): + return redirect('/') + up=UserProfile.objects.get(user=request.user) + if 'location' in request.GET: + print "loc" + up.location=request.GET['location'] + if 'language' in request.GET: + print "lang" + up.language=request.GET['language'] + up.save() + + return HttpResponse(json.dumps({'success':True, + 'language':up.language, + 'location':up.location,})) + def create_account(request): js={'success':False} # Confirm we have a properly formed request diff --git a/courseware/capa_module.py b/courseware/capa_module.py index 4ada2b489f..36d396d245 100644 --- a/courseware/capa_module.py +++ b/courseware/capa_module.py @@ -49,7 +49,7 @@ class LoncapaModule(XModule): html = '
'.format(id=self.item_id)+html+"
" return html - def get_js(self): + def get_init_js(self): return "" def __init__(self, xml, item_id, ajax_url=None, track_url=None, state=None): diff --git a/courseware/capa_problem.py b/courseware/capa_problem.py index 458370a84e..0c43b3bd28 100644 --- a/courseware/capa_problem.py +++ b/courseware/capa_problem.py @@ -37,7 +37,6 @@ class LoncapaProblem(): seed will provide the random seed. Alternatively, passing context will bypass all script execution, and use the given execution context. ''' - print "!!",filename, id if state!=None: state=json.loads(state) else: @@ -65,25 +64,36 @@ class LoncapaProblem(): g={'random':random,'numpy':numpy,'math':math,'scipy':scipy} + # Buffer stores HTML for problem buf=StringIO.StringIO() ot=False ## Are we in an outtext context? + # Loop through the nodes of the problem, and for e in dom.childNodes: + print e, ot + # if e.localName=='script': + print e.childNodes[0].data exec e.childNodes[0].data in g,self.context - if e.localName=='endouttext': + elif e.localName=='endouttext': ot=False - if ot: + elif ot: + print e, "::", e.toxml() e.writexml(buf) - if e.localName=='startouttext': + elif e.localName=='startouttext': ot=True - if e.localName in self.handlers: + elif e.localName in self.handlers: problem=self.handlers[e.localName](self,e) buf.write(problem) + elif e.localName==None: + pass + else: + raise Exception("ERROR: UNRECOGNIZED XML"+e.localName) self.text=buf.getvalue() self.text=self.contextualize_text(self.text) + print self.text self.filename=filename done=False diff --git a/courseware/static/circuits/superposition-ex-e2-fig.gif b/courseware/static/circuits/superposition-ex-e2-fig.gif new file mode 100644 index 0000000000000000000000000000000000000000..88f4c4deca021893d7796b010524573e16ec6e9d GIT binary patch literal 3275 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 Jn`lq~06PMse0l%? literal 0 HcmV?d00001 diff --git a/courseware/static/js/mathjax/MathJax.js b/courseware/static/js/mathjax/MathJax.js new file mode 100644 index 0000000000..f05132e9b4 --- /dev/null +++ b/courseware/static/js/mathjax/MathJax.js @@ -0,0 +1,30 @@ +/************************************************************* + * + * MathJax.js + * + * The main code for the MathJax math-typesetting library. See + * http://www.mathjax.org/ for details. + * + * --------------------------------------------------------------------- + * + * Copyright (c) 2009-2010 Design Science, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +if (!window.MathJax) {window.MathJax = {}} + +MathJax.isPacked = true; + +if(document.getElementById&&document.childNodes&&document.createElement){if(!window.MathJax){window.MathJax={}}if(!MathJax.Hub){MathJax.version="1.1a";MathJax.fileversion="1.1.7";(function(d){var b=window[d];if(!b){b=window[d]={}}var f=[];var c=function(g){var h=g.constructor;if(!h){h=new Function("")}for(var i in g){if(i!=="constructor"&&g.hasOwnProperty(i)){h[i]=g[i]}}return h};var a=function(){return new Function("return arguments.callee.Init.call(this,arguments)")};var e=a();e.prototype={bug_test:1};if(!e.prototype.bug_test){a=function(){return function(){return arguments.callee.Init.call(this,arguments)}}}b.Object=c({constructor:a(),Subclass:function(g,i){var h=a();h.SUPER=this;h.Init=this.Init;h.Subclass=this.Subclass;h.Augment=this.Augment;h.protoFunction=this.protoFunction;h.can=this.can;h.has=this.has;h.isa=this.isa;h.prototype=new this(f);h.prototype.constructor=h;h.Augment(g,i);return h},Init:function(g){var h=this;if(g.length===1&&g[0]===f){return h}if(!(h instanceof g.callee)){h=new g.callee(f)}return h.Init.apply(h,g)||h},Augment:function(g,h){var i;if(g!=null){for(i in g){if(g.hasOwnProperty(i)){this.protoFunction(i,g[i])}}if(g.toString!==this.prototype.toString&&g.toString!=={}.toString){this.protoFunction("toString",g.toString)}}if(h!=null){for(i in h){if(h.hasOwnProperty(i)){this[i]=h[i]}}}return this},protoFunction:function(h,g){this.prototype[h]=g;if(typeof g==="function"){g.SUPER=this.SUPER.prototype}},prototype:{Init:function(){},SUPER:function(g){return g.callee.SUPER},can:function(g){return typeof(this[g])==="function"},has:function(g){return typeof(this[g])!=="undefined"},isa:function(g){return(g instanceof Object)&&(this instanceof g)}},can:function(g){return this.prototype.can.call(this,g)},has:function(g){return this.prototype.has.call(this,g)},isa:function(h){var g=this;while(g){if(g===h){return true}else{g=g.SUPER}}return false},SimpleSUPER:c({constructor:function(g){return this.SimpleSUPER.define(g)},define:function(g){var i={};if(g!=null){for(var h in g){if(g.hasOwnProperty(h)){this.protoFunction(h,g[h])}}if(g.toString!==this.prototype.toString&&g.toString!=={}.toString){this.protoFunction("toString",g.toString)}}return i},wrap:function(i,h){if(typeof(h)==="function"&&h.toString().match(/\.\s*SUPER\s*\(/)){var g=new Function(this.wrapper);g.label=i;g.original=h;h=g;g.toString=this.stringify}return h},wrapper:function(){var h=arguments.callee;this.SUPER=h.SUPER[h.label];try{var g=h.original.apply(this,arguments)}catch(i){delete this.SUPER;throw i}delete this.SUPER;return g}.toString().replace(/^\s*function \(\)\s*\{\s*/i,"").replace(/\s*\}\s*$/i,""),toString:function(){return this.original.toString.apply(this.original,arguments)}})})})("MathJax");(function(BASENAME){var BASE=window[BASENAME];if(!BASE){BASE=window[BASENAME]={}}var CALLBACK=function(data){var cb=new Function("return arguments.callee.execute.apply(arguments.callee,arguments)");for(var id in CALLBACK.prototype){if(CALLBACK.prototype.hasOwnProperty(id)){if(typeof(data[id])!=="undefined"){cb[id]=data[id]}else{cb[id]=CALLBACK.prototype[id]}}}cb.toString=CALLBACK.prototype.toString;return cb};CALLBACK.prototype={isCallback:true,hook:function(){},data:[],object:window,execute:function(){if(!this.called||this.autoReset){this.called=!this.autoReset;return this.hook.apply(this.object,this.data.concat([].slice.call(arguments,0)))}},reset:function(){delete this.called},toString:function(){return this.hook.toString.apply(this.hook,arguments)}};var ISCALLBACK=function(f){return(typeof(f)==="function"&&f.isCallback)};var EVAL=function(code){return eval.call(window,code)};EVAL("var __TeSt_VaR__ = 1");if(window.__TeSt_VaR__){try{delete window.__TeSt_VaR__}catch(error){window.__TeSt_VaR__=null}}else{if(window.execScript){EVAL=function(code){BASE.__code=code;code="try {"+BASENAME+".__result = eval("+BASENAME+".__code)} catch(err) {"+BASENAME+".__result = err}";window.execScript(code);var result=BASE.__result;delete BASE.__result;delete BASE.__code;if(result instanceof Error){throw result}return result}}else{EVAL=function(code){BASE.__code=code;code="try {"+BASENAME+".__result = eval("+BASENAME+".__code)} catch(err) {"+BASENAME+".__result = err}";var head=(document.getElementsByTagName("head"))[0];if(!head){head=document.body}var script=document.createElement("script");script.appendChild(document.createTextNode(code));head.appendChild(script);head.removeChild(script);var result=BASE.__result;delete BASE.__result;delete BASE.__code;if(result instanceof Error){throw result}return result}}}var USING=function(args,i){if(arguments.length>1){if(arguments.length===2&&!(typeof arguments[0]==="function")&&arguments[0] instanceof Object&&typeof arguments[1]==="number"){args=[].slice.call(args,i)}else{args=[].slice.call(arguments,0)}}if(args instanceof Array&&args.length===1){args=args[0]}if(typeof args==="function"){if(args.execute===CALLBACK.prototype.execute){return args}return CALLBACK({hook:args})}else{if(args instanceof Array){if(typeof(args[0])==="string"&&args[1] instanceof Object&&typeof args[1][args[0]]==="function"){return CALLBACK({hook:args[1][args[0]],object:args[1],data:args.slice(2)})}else{if(typeof args[0]==="function"){return CALLBACK({hook:args[0],data:args.slice(1)})}else{if(typeof args[1]==="function"){return CALLBACK({hook:args[1],object:args[0],data:args.slice(2)})}}}}else{if(typeof(args)==="string"){return CALLBACK({hook:EVAL,data:[args]})}else{if(args instanceof Object){return CALLBACK(args)}else{if(typeof(args)==="undefined"){return CALLBACK({})}}}}}throw Error("Can't make callback from given data")};var DELAY=function(time,callback){callback=USING(callback);callback.timeout=setTimeout(callback,time);return callback};var WAITFOR=function(callback,signal){callback=USING(callback);if(!callback.called){WAITSIGNAL(callback,signal);signal.pending++}};var WAITEXECUTE=function(){var signals=this.signal;delete this.signal;this.execute=this.oldExecute;delete this.oldExecute;var result=this.execute.apply(this,arguments);if(ISCALLBACK(result)&&!result.called){WAITSIGNAL(result,signals)}else{for(var i=0,m=signals.length;if){f=document.styleSheets.length}if(!h){h=(document.getElementsByTagName("head"))[0];if(!h){h=document.body}}return h};var e=[];var b=function(){for(var j=0,h=e.length;j=this.timeout){h(this.STATUS.ERROR);return 1}return 0},file:function(i,h){if(h<0){a.Ajax.loadTimeout(i)}else{a.Ajax.loadComplete(i)}},execute:function(){this.hook.call(this.object,this,this.data[0],this.data[1])},checkSafari2:function(h,i,j){if(h.time(j)){return}if(document.styleSheets.length>i&&document.styleSheets[i].cssRules&&document.styleSheets[i].cssRules.length){j(h.STATUS.OK)}else{setTimeout(h,h.delay)}},checkLength:function(h,k,m){if(h.time(m)){return}var l=0;var i=(k.sheet||k.styleSheet);try{if((i.cssRules||i.rules||[]).length>0){l=1}}catch(j){if(j.message.match(/protected variable|restricted URI/)){l=1}else{if(j.message.match(/Security error/)){l=1}}}if(l){setTimeout(a.Callback([m,h.STATUS.OK]),0)}else{setTimeout(h,h.delay)}}},loadComplete:function(h){h=this.fileURL(h);var i=this.loading[h];if(i&&!i.preloaded){a.Message.Clear(i.message);clearTimeout(i.timeout);if(i.script){if(e.length===0){setTimeout(b,0)}e.push(i.script)}this.loaded[h]=i.status;delete this.loading[h];if(!this.loadHooks[h]){this.loadHooks[h]=[]}this.loadHooks[h].push(i.callback)}else{this.loaded[h]=this.STATUS.OK;i={status:this.STATUS.OK}}a.Callback.ExecuteHooks(this.loadHooks[h],i.status)},loadTimeout:function(h){if(this.loading[h].timeout){clearTimeout(this.loading[h].timeout)}this.loading[h].status=this.STATUS.ERROR;this.loadError(h);this.loadComplete(h)},loadError:function(h){a.Message.Set("File failed to load: "+h,null,2000)},Styles:function(j,k){var h=this.StyleString(j);if(h===""){k=a.Callback(k);k()}else{var i=document.createElement("style");i.type="text/css";this.head=g(this.head);this.head.appendChild(i);if(i.styleSheet&&typeof(i.styleSheet.cssText)!=="undefined"){i.styleSheet.cssText=h}else{i.appendChild(document.createTextNode(h))}k=this.timer.create.call(this,k,i)}return k},StyleString:function(m){if(typeof(m)==="string"){return m}var j="",n,l;for(n in m){if(m.hasOwnProperty(n)){if(typeof m[n]==="string"){j+=n+" {"+m[n]+"}\n"}else{if(m[n] instanceof Array){for(var k=0;k1?d[1]:""));g=null}if(f&&(!b.preJax||d)){c.nodeValue=c.nodeValue.replace(b.postJax,(f.length>1?f[1]:""))}if(g&&!g.nodeValue.match(/\S/)){g=g.previousSibling}}if(b.preRemoveClass&&g&&g.className==b.preRemoveClass){try{g.innerHTML=""}catch(e){}g.style.display="none"}if(a.MathJax){a.MathJax.checked=1}},processScripts:function(h,b,d){if(arguments.callee.disabled){return null}var q,o=MathJax.ElementJax.STATE;var p=this.config.inputJax,c=this.config.outputJax;try{if(!b){b=new Date().getTime()}var j=0,l,f;while(jthis.processUpdateTime&&j=0;o--){if(b[o].src.match(d)){q.script=b[o].innerHTML;if(RegExp.$2){var r=RegExp.$2.substr(1).split(/\&/);for(var n=0,h=r.length;n=parseInt(x[y])}}return true},Select:function(j){var i=j[c.Browser];if(i){return i(c.Browser)}return null}};var g=navigator.userAgent.replace(/^Mozilla\/(\d+\.)+\d+ /,"").replace(/[a-z][-a-z0-9._: ]+\/\d+[^ ]*-[^ ]*\.([a-z][a-z])?\d+ /i,"").replace(/Gentoo |Ubuntu\/(\d+\.)*\d+ (\([^)]*\) )?/,"");c.Browser=c.Insert(c.Insert(new String("Unknown"),{version:"0.0"}),a);for(var t in a){if(a.hasOwnProperty(t)){if(a[t]&&t.substr(0,2)==="is"){t=t.slice(2);if(t==="Mac"||t==="PC"){continue}c.Browser=c.Insert(new String(t),a);var p=new RegExp(".*(Version)/((?:\\d+\\.)+\\d+)|.*("+t+")"+(t=="MSIE"?" ":"/")+"((?:\\d+\\.)*\\d+)|(?:^|\\(| )([a-z][-a-z0-9._: ]+|(?:Apple)?WebKit)/((?:\\d+\\.)+\\d+)");var s=p.exec(g)||["","","","unknown","0.0"];c.Browser.name=(s[1]=="Version"?t:(s[3]||s[5]));c.Browser.version=s[2]||s[4]||s[6];break}}}c.Browser.Select({Safari:function(j){var i=parseInt((String(j.version).split("."))[0]);if(i>85){j.webkit=j.version}if(i>=533){j.version="5.0"}else{if(i>=526){j.version="4.0"}else{if(i>=525){j.version="3.1"}else{if(i>500){j.version="3.0"}else{if(i>400){j.version="2.0"}else{if(i>85){j.version="1.0"}}}}}}},Firefox:function(j){if(j.version==="0.0"&&navigator.product==="Gecko"&&navigator.productSub){var i=navigator.productSub.substr(0,8);if(i>="20090630"){j.version="3.5"}else{if(i>="20080617"){j.version="3.0"}else{if(i>="20061024"){j.version="2.0"}}}}},Opera:function(i){i.version=opera.version()},MSIE:function(i){i.isIE9=!!(document.documentMode&&(window.performance||window.msPerformance));MathJax.HTML.setScriptBug=!i.isIE9||document.documentMode<9}});c.Browser.Select(MathJax.Message.browsers);c.queue=f.Callback.Queue();c.queue.Push(["Post",q.signal,"Begin"],["Config",q],["Cookie",q],["Styles",q],["Message",q],function(){var i=f.Callback.Queue(q.Jax(),q.Extensions());return i.Push({})},["Menu",q],q.onLoad(),function(){MathJax.isReady=true},["Typeset",q],["Post",q.signal,"End"])})("MathJax")}}; + diff --git a/courseware/static/js/video_player.js b/courseware/static/js/video_player.js index 7c1da780ce..04a3552834 100644 --- a/courseware/static/js/video_player.js +++ b/courseware/static/js/video_player.js @@ -1,3 +1,18 @@ +// Things to abstract out to another file + +function postJSON(url, data, callback, csrf) { + $.ajax({ + url: url, + dataType: 'json', + data: data, + success: callback + }); +} + +var global=5; + +// Video player + var load_id = 0; function caption_at(index) { @@ -92,7 +107,16 @@ function onYouTubePlayerReady(playerId) { } +function videoDestroy() { + load_id = 0; + // TODO/BUG: Figure out why removeEventListener doesn't work + ytplayer.removeEventListener("onStateChange", "onytplayerStateChange"); + ytplayer.removeEventListener("onError", "onPlayerError"); + ytplayer = false; +} + function log_event(e) { + // CRITICAL TODO: Change to AJAX //$("#eventlog").append("
"); //$("#eventlog").append(JSON.stringify(e)); window['console'].log(JSON.stringify(e)); diff --git a/courseware/views.py b/courseware/views.py index a52e35e53f..3725ff2f73 100644 --- a/courseware/views.py +++ b/courseware/views.py @@ -95,7 +95,7 @@ def render_accordion(request,course,chapter,section): ['course_name',course], ['format_string',format_string]]+ \ template_imports.items()) - return {'js':render_to_string('accordion_init.js',context), + return {'init_js':render_to_string('accordion_init.js',context), 'content':render_to_string('accordion.html',context)} def video_mod(request, module): @@ -103,7 +103,7 @@ def video_mod(request, module): OBSOLETE. Remove once x_module version confirmed ''' id=module.getAttribute('youtube') - return {'js':render_to_string('video_init.js',{'id':id}), + return {'init_js':render_to_string('video_init.js',{'id':id}), 'content':render_to_string('video.html',{'id':id})} def html_module(request, module): @@ -118,9 +118,9 @@ def tab_module(request, module): contents=[(e.getAttribute("name"),render_module(request, e)) \ for e in module.childNodes \ if e.nodeType==1] - js="".join([e[1]['js'] for e in contents if 'js' in e[1]]) + js="".join([e[1]['init_js'] for e in contents if 'init_js' in e[1]]) - return {'js':render_to_string('tab_module.js',{'tabs':contents})+js, + return {'init_js':render_to_string('tab_module.js',{'tabs':contents})+js, 'content':render_to_string('tab_module.html',{'tabs':contents})} def vertical_module(request, module): @@ -129,9 +129,9 @@ def vertical_module(request, module): contents=[(e.getAttribute("name"),render_module(request, e)) \ for e in module.childNodes \ if e.nodeType==1] - js="".join([e[1]['js'] for e in contents if 'js' in e[1]]) + js="".join([e[1]['init_js'] for e in contents if 'init_js' in e[1]]) - return {'js':js, + return {'init_js':js, 'content':render_to_string('vert_module.html',{'items':contents})} def seq_module(request, module): @@ -141,22 +141,28 @@ def seq_module(request, module): # jsonify contents so it can be embedded in a js array # We also need to split tags so they don't break # mid-string - if 'js' not in m: m['js']="" + if 'init_js' not in m: m['init_js']="" content=json.dumps(m['content']) content=content.replace('', '<"+"/script>') - return {'content':content, 'js':m['js']} + return {'content':content, 'init_js':m['init_js']} contents=[(e.getAttribute("name"),j(render_module(request, e))) \ for e in module.childNodes \ if e.nodeType==1] - js="".join([e[1]['js'] for e in contents if 'js' in e[1]]) + js="".join([e[1]['init_js'] for e in contents if 'init_js' in e[1]]) iid=uuid.uuid1().hex - return {'js':js+render_to_string('seq_module.js',{'items':contents, - 'id':"seq"}), - 'content':render_to_string('seq_module.html',{'items':contents, - 'id':"seq"})} + params={'items':contents, + 'id':"seq"} + + print module.nodeName + if module.nodeName == 'sequential': + return {'init_js':js+render_to_string('seq_module.js',params), + 'content':render_to_string('seq_module.html',params)} + if module.nodeName == 'tab': + return {'init_js':js+render_to_string('tab_module.js',params), + 'content':render_to_string('tab_module.html',params)} modx_modules={'problem':capa_module.LoncapaModule, 'video':video_module.VideoModule} @@ -194,7 +200,7 @@ def render_x_module(request, xml_module): xml=instance.xml) # Grab content content = {'content':instance.get_html(), - 'js':instance.get_js()} + 'init_js':instance.get_init_js()} smod.save() # This may be optional (at least in the case of no instance in the dB) @@ -221,7 +227,7 @@ def modx_dispatch(request, module=None, dispatch=None, id=None): module_types={'video':render_x_module, 'html':html_module, - 'tab':tab_module, + 'tab':seq_module, 'vertical':vertical_module, 'sequential':seq_module, 'problem':render_x_module, @@ -265,10 +271,10 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti module=render_module(request, module) - if 'js' not in module: - module['js']='' + if 'init_js' not in module: + module['init_js']='' - context={'init':accordion['js']+module['js'], + context={'init':accordion['init_js']+module['init_js'], 'accordion':accordion['content'], 'content':module['content']} return render_to_response('courseware.html', context) diff --git a/courseware/x_module.py b/courseware/x_module.py index e881a3d8e3..73b98a658f 100644 --- a/courseware/x_module.py +++ b/courseware/x_module.py @@ -23,13 +23,16 @@ class XModule: def get_html(self): return "Unimplemented" - def get_js(self): + def get_init_js(self): ''' JavaScript code to be run when problem is shown. Be aware that this may happen several times on the same page (e.g. student switching tabs). Common functions should be put in the main course .js files for now. ''' return "" + def get_destroy_js(self): + return "" + def handle_ajax(self, dispatch, get): ''' dispatch is last part of the URL. get is a dictionary-like object ''' diff --git a/urls.py b/urls.py index d3d41c7db0..c7811cff44 100644 --- a/urls.py +++ b/urls.py @@ -13,6 +13,7 @@ urlpatterns = patterns('', url(r'^modx/(?P[^/]*)/(?P[^/]*)/(?P[^/]*)$', 'courseware.views.modx_dispatch'), #reset_problem'), url(r'^courseware/$', 'courseware.views.index'), url(r'^profile$', 'courseware.views.profile'), + url(r'^change_setting$', 'auth.views.change_setting'), # url(r'^admin/', include('django.contrib.admin.urls')), # url(r'^accounts/register/$', 'registration.views.register', {'success_url':'/accounts/register/complete'}), # url(r'^accounts/', include('registration.urls')),