diff --git a/djangoapps/courseware/views.py b/djangoapps/courseware/views.py index f7d1ba9293..cca9674c42 100644 --- a/djangoapps/courseware/views.py +++ b/djangoapps/courseware/views.py @@ -84,7 +84,7 @@ def render_accordion(request,course,chapter,section): parameter. Returns (initialization_javascript, content)''' if not course: course = "6.002 Spring 2012" - + toc=content_parser.toc_from_xml(content_parser.course_file(request.user), chapter, section) active_chapter=1 for i in range(len(toc)): @@ -96,8 +96,7 @@ def render_accordion(request,course,chapter,section): ['format_url_params',content_parser.format_url_params], ['csrf',csrf(request)['csrf_token']]] + \ template_imports.items()) - return {'init_js':render_to_string('accordion_init.js',context), - 'content':render_to_string('accordion.html',context)} + return render_to_string('accordion.html',context) @cache_control(no_cache=True, no_store=True, must_revalidate=True) def render_section(request, section): @@ -124,8 +123,8 @@ def render_section(request, section): if 'init_js' not in module: module['init_js']='' - context={'init':accordion['init_js']+module['init_js'], - 'accordion':accordion['content'], + context={'init':module['init_js'], + 'accordion':accordion, 'content':module['content'], 'csrf':csrf(request)['csrf_token']} @@ -179,8 +178,8 @@ def index(request, course="6.002 Spring 2012", chapter="Using the System", secti if 'init_js' not in module: module['init_js']='' - context={'init':accordion['init_js']+module['init_js'], - 'accordion':accordion['content'], + context={'init':module['init_js'], + 'accordion':accordion, 'content':module['content'], 'csrf':csrf(request)['csrf_token']} diff --git a/requirements.txt b/requirements.txt index 6e13b88463..8e701ce335 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,3 +15,4 @@ path.py django_debug_toolbar django-masquerade pyfilesystem +django-jasmine diff --git a/settings.py b/settings.py index f20f51ffb8..0828f75595 100644 --- a/settings.py +++ b/settings.py @@ -147,6 +147,7 @@ INSTALLED_APPS = ( 'perfstats', 'util', 'masquerade', + 'django_jasmine', # Uncomment the next line to enable the admin: # 'django.contrib.admin', # Uncomment the next line to enable admin documentation: @@ -347,6 +348,7 @@ PROJECT_ROOT = os.path.dirname(__file__) TEMPLATE_CONTEXT_PROCESSORS = ( 'django.core.context_processors.request', + 'django.core.context_processors.static', 'askbot.context.application_settings', #'django.core.context_processors.i18n', 'askbot.user_messages.context_processors.user_messages',#must be before auth @@ -683,3 +685,5 @@ if MAKO_MODULE_DIR == None: djcelery.setup_loader() +# Jasmine Settings +JASMINE_TEST_DIRECTORY = PROJECT_DIR+'/templates/coffee' diff --git a/static/js/application.js b/static/js/application.js new file mode 100644 index 0000000000..6a2e883917 --- /dev/null +++ b/static/js/application.js @@ -0,0 +1,120 @@ +// Generated by CoffeeScript 1.3.2-pre +(function() { + + window.Calculator = (function() { + + function Calculator() {} + + Calculator.bind = function() { + var calculator; + calculator = new Calculator; + $('.calc').click(calculator.toggle); + $('form#calculator').submit(calculator.calculate).submit(function(e) { + return e.preventDefault(); + }); + return $('div.help-wrapper a').hover(calculator.helpToggle).click(function(e) { + return e.preventDefault(); + }); + }; + + Calculator.prototype.toggle = function() { + $('li.calc-main').toggleClass('open'); + $('#calculator_wrapper #calculator_input').focus(); + return $('.calc').toggleClass('closed'); + }; + + Calculator.prototype.helpToggle = function() { + return $('.help').toggleClass('shown'); + }; + + Calculator.prototype.calculate = function() { + return $.getJSON('/calculate', { + equation: $('#calculator_input').val() + }, function(data) { + return $('#calculator_output').val(data.result); + }); + }; + + return Calculator; + + })(); + + window.Courseware = (function() { + + function Courseware() {} + + Courseware.bind = function() { + return this.Navigation.bind(); + }; + + Courseware.Navigation = (function() { + + function Navigation() {} + + Navigation.bind = function() { + var navigation; + if ($('#accordion').length) { + navigation = new Navigation; + $('#accordion').bind('accordionchange', navigation.log).accordion({ + active: $('#accordion ul:has(li.active)').index('#accordion ul'), + header: 'h3', + autoHeight: false + }); + return $('#open_close_accordion a').click(navigation.toggle); + } + }; + + Navigation.prototype.log = function(event, ui) { + return log_event('accordion', { + newheader: ui.newHeader.text(), + oldheader: ui.oldHeader.text() + }); + }; + + Navigation.prototype.toggle = function() { + return $('.course-wrapper').toggleClass('closed'); + }; + + return Navigation; + + })(); + + return Courseware; + + }).call(this); + + window.FeedbackForm = (function() { + + function FeedbackForm() {} + + FeedbackForm.bind = function() { + return $('#feedback_button').click(function() { + var data; + data = { + subject: $('#feedback_subject').val(), + message: $('#feedback_message').val(), + url: window.location.href + }; + return $.post('/send_feedback', data, function() { + return $('#feedback_div').html('Feedback submitted. Thank you'); + }, 'json'); + }); + }; + + return FeedbackForm; + + })(); + + $(function() { + $.ajaxSetup({ + headers: { + 'X-CSRFToken': $.cookie('csrftoken') + } + }); + Calculator.bind(); + Courseware.bind(); + FeedbackForm.bind(); + return $("a[rel*=leanModal]").leanModal(); + }); + +}).call(this); diff --git a/templates/accordion_init.js b/templates/accordion_init.js deleted file mode 100644 index 7c4ca2603c..0000000000 --- a/templates/accordion_init.js +++ /dev/null @@ -1,19 +0,0 @@ -$("#accordion").accordion({ - active: ${ active_chapter }, - header: 'h3', - autoHeight: false, -}); - -$("#open_close_accordion a").click(function(){ - if ($(".course-wrapper").hasClass("closed")){ - $(".course-wrapper").removeClass("closed"); - } else { - $(".course-wrapper").addClass("closed"); - } -}); - -$('.ui-accordion').bind('accordionchange', function(event, ui) { - var event_data = {'newheader':ui.newHeader.text(), - 'oldheader':ui.oldHeader.text()}; - log_event('accordion', event_data); -}); diff --git a/templates/coffee/README.md b/templates/coffee/README.md new file mode 100644 index 0000000000..6c26529a5b --- /dev/null +++ b/templates/coffee/README.md @@ -0,0 +1,59 @@ +CoffeeScript +============ + +This folder contains the CoffeeScript file that will be compiled to the static +directory. By default, we're compile and merge all the files ending `.coffee` +into `static/js/application.js`. + +Install the Compiler +-------------------- + +CoffeeScript compiler are written in JavaScript. You'll need to install Node and +npm (Node Package Manager) to be able to install the CoffeeScript compiler. + +### Mac OS X + +Install Node via Homebrew, then use npm: + + brew install node + curl http://npmjs.org/install.sh | sh + npm install -g git://github.com/jashkenas/coffee-script.git + +(Note that we're using the edge version of CoffeeScript for now, as there was +some issue with directory watching in 1.3.1.) + +Try to run `coffee` and make sure you get a coffee prompt. + +### Debian/Ubuntu + +Conveniently, you can install Node via `apt-get`, then use npm: + + sudo apt-get install nodejs npm && + sudo npm install -g git://github.com/jashkenas/coffee-script.git + +Compiling +--------- + +Run this command in the `mitx` directory to easily make the compiler watch for +changes in your file, and join the result into `application.js`: + + coffee -j static/js/application.js -cw templates/coffee/src + +Please note that the compiler will not be able to detect the file that get added +after you've ran the command, so you'll need to restart the compiler if there's +a new CoffeeScript file. + +Testing +======= + +We're also using Jasmine to unit-testing the JavaScript files. All the specs are +written in CoffeeScript for the consistency. Because of the limitation of +`django-jasmine` plugin, we'll need to also running another compiler to compile +the test file. + +Using this command to compile the test files: + + coffee -cw templates/coffee/spec/*.coffee + +Then start the server in debug mode, navigate to http://127.0.0.1:8000/_jasmine +to see the test result. diff --git a/templates/coffee/files.json b/templates/coffee/files.json new file mode 100644 index 0000000000..bfae4dfe87 --- /dev/null +++ b/templates/coffee/files.json @@ -0,0 +1,10 @@ +{ + "js_files": [ + "/static/js/jquery-1.6.2.min.js", + "/static/js/jquery-ui-1.8.16.custom.min.js", + "/static/js/jquery.leanModal.js" + ], + "static_files": [ + "js/application.js" + ] +} diff --git a/templates/coffee/fixtures/accordion.html b/templates/coffee/fixtures/accordion.html new file mode 100644 index 0000000000..148c245c8f --- /dev/null +++ b/templates/coffee/fixtures/accordion.html @@ -0,0 +1,6 @@ +
+
+ close +
+
+
diff --git a/templates/coffee/fixtures/calculator.html b/templates/coffee/fixtures/calculator.html new file mode 100644 index 0000000000..61c6f5e153 --- /dev/null +++ b/templates/coffee/fixtures/calculator.html @@ -0,0 +1,18 @@ + diff --git a/templates/coffee/fixtures/feedback_form.html b/templates/coffee/fixtures/feedback_form.html new file mode 100644 index 0000000000..672663fe10 --- /dev/null +++ b/templates/coffee/fixtures/feedback_form.html @@ -0,0 +1,7 @@ +
+
+ + + +
+
diff --git a/templates/coffee/spec/calculator_spec.coffee b/templates/coffee/spec/calculator_spec.coffee new file mode 100644 index 0000000000..5c3fde5e2d --- /dev/null +++ b/templates/coffee/spec/calculator_spec.coffee @@ -0,0 +1,68 @@ +describe 'Calculator', -> + beforeEach -> + loadFixtures 'calculator.html' + @calculator = new Calculator + + describe 'bind', -> + beforeEach -> + Calculator.bind() + + it 'bind the calculator button', -> + expect($('.calc')).toHandleWith 'click', @calculator.toggle + + it 'bind the help button', -> + # These events are bind by $.hover() + expect($('div.help-wrapper a')).toHandleWith 'mouseenter', @calculator.helpToggle + expect($('div.help-wrapper a')).toHandleWith 'mouseleave', @calculator.helpToggle + + it 'prevent default behavior on help button', -> + $('div.help-wrapper a').click (e) -> + expect(e.isDefaultPrevented()).toBeTruthy() + $('div.help-wrapper a').click() + + it 'bind the calculator submit', -> + expect($('form#calculator')).toHandleWith 'submit', @calculator.calculate + + it 'prevent default behavior on form submit', -> + $('form#calculator').submit (e) -> + expect(e.isDefaultPrevented()).toBeTruthy() + e.preventDefault() + $('form#calculator').submit() + + describe 'toggle', -> + it 'toggle the calculator and focus the input', -> + spyOn $.fn, 'focus' + @calculator.toggle() + + expect($('li.calc-main')).toHaveClass('open') + expect($('#calculator_wrapper #calculator_input').focus).toHaveBeenCalled() + + it 'toggle the close button on the calculator button', -> + @calculator.toggle() + expect($('.calc')).toHaveClass('closed') + + @calculator.toggle() + expect($('.calc')).not.toHaveClass('closed') + + describe 'helpToggle', -> + it 'toggle the help overlay', -> + @calculator.helpToggle() + expect($('.help')).toHaveClass('shown') + + @calculator.helpToggle() + expect($('.help')).not.toHaveClass('shown') + + describe 'calculate', -> + beforeEach -> + $('#calculator_input').val '1+2' + spyOn($, 'getJSON').andCallFake (url, data, callback) -> + callback({ result: 3 }) + @calculator.calculate() + + it 'send data to /calculate', -> + expect($.getJSON).toHaveBeenCalledWith '/calculate', + equation: '1+2' + , jasmine.any(Function) + + it 'update the calculator output', -> + expect($('#calculator_output').val()).toEqual('3') diff --git a/templates/coffee/spec/calculator_spec.js b/templates/coffee/spec/calculator_spec.js new file mode 100644 index 0000000000..6e0f8a0dab --- /dev/null +++ b/templates/coffee/spec/calculator_spec.js @@ -0,0 +1,80 @@ +// Generated by CoffeeScript 1.3.2-pre +(function() { + + describe('Calculator', function() { + beforeEach(function() { + loadFixtures('calculator.html'); + return this.calculator = new Calculator; + }); + describe('bind', function() { + beforeEach(function() { + return Calculator.bind(); + }); + it('bind the calculator button', function() { + return expect($('.calc')).toHandleWith('click', this.calculator.toggle); + }); + it('bind the help button', function() { + expect($('div.help-wrapper a')).toHandleWith('mouseenter', this.calculator.helpToggle); + return expect($('div.help-wrapper a')).toHandleWith('mouseleave', this.calculator.helpToggle); + }); + it('prevent default behavior on help button', function() { + $('div.help-wrapper a').click(function(e) { + return expect(e.isDefaultPrevented()).toBeTruthy(); + }); + return $('div.help-wrapper a').click(); + }); + it('bind the calculator submit', function() { + return expect($('form#calculator')).toHandleWith('submit', this.calculator.calculate); + }); + return it('prevent default behavior on form submit', function() { + $('form#calculator').submit(function(e) { + expect(e.isDefaultPrevented()).toBeTruthy(); + return e.preventDefault(); + }); + return $('form#calculator').submit(); + }); + }); + describe('toggle', function() { + it('toggle the calculator and focus the input', function() { + spyOn($.fn, 'focus'); + this.calculator.toggle(); + expect($('li.calc-main')).toHaveClass('open'); + return expect($('#calculator_wrapper #calculator_input').focus).toHaveBeenCalled(); + }); + return it('toggle the close button on the calculator button', function() { + this.calculator.toggle(); + expect($('.calc')).toHaveClass('closed'); + this.calculator.toggle(); + return expect($('.calc')).not.toHaveClass('closed'); + }); + }); + describe('helpToggle', function() { + return it('toggle the help overlay', function() { + this.calculator.helpToggle(); + expect($('.help')).toHaveClass('shown'); + this.calculator.helpToggle(); + return expect($('.help')).not.toHaveClass('shown'); + }); + }); + return describe('calculate', function() { + beforeEach(function() { + $('#calculator_input').val('1+2'); + spyOn($, 'getJSON').andCallFake(function(url, data, callback) { + return callback({ + result: 3 + }); + }); + return this.calculator.calculate(); + }); + it('send data to /calculate', function() { + return expect($.getJSON).toHaveBeenCalledWith('/calculate', { + equation: '1+2' + }, jasmine.any(Function)); + }); + return it('update the calculator output', function() { + return expect($('#calculator_output').val()).toEqual('3'); + }); + }); + }); + +}).call(this); diff --git a/templates/coffee/spec/courseware_spec.coffee b/templates/coffee/spec/courseware_spec.coffee new file mode 100644 index 0000000000..5a5cabac0e --- /dev/null +++ b/templates/coffee/spec/courseware_spec.coffee @@ -0,0 +1,66 @@ +describe 'Courseware', -> + describe 'bind', -> + it 'bind the navigation', -> + spyOn Courseware.Navigation, 'bind' + Courseware.bind() + expect(Courseware.Navigation.bind).toHaveBeenCalled() + + describe 'Navigation', -> + beforeEach -> + loadFixtures 'accordion.html' + @navigation = new Courseware.Navigation + + describe 'bind', -> + describe 'when the #accordion exists', -> + it 'activate the accordion with correct active section', -> + spyOn $.fn, 'accordion' + $('#accordion').append('') + Courseware.Navigation.bind() + expect($('#accordion').accordion).toHaveBeenCalledWith + active: 1 + header: 'h3' + autoHeight: false + + it 'binds the accordionchange event', -> + Courseware.Navigation.bind() + expect($('#accordion')).toHandleWith 'accordionchange', @navigation.log + + it 'bind the navigation toggle', -> + Courseware.Navigation.bind() + expect($('#open_close_accordion a')).toHandleWith 'click', @navigation.toggle + + describe 'when the #accordion does not exists', -> + beforeEach -> + $('#accordion').remove() + + it 'does not activate the accordion', -> + spyOn $.fn, 'accordion' + Courseware.Navigation.bind() + expect($('#accordion').accordion).wasNotCalled() + + describe 'toggle', -> + it 'toggle closed class on the wrapper', -> + $('.course-wrapper').removeClass('closed') + + @navigation.toggle() + expect($('.course-wrapper')).toHaveClass('closed') + + @navigation.toggle() + expect($('.course-wrapper')).not.toHaveClass('closed') + + describe 'log', -> + beforeEach -> + window.log_event = -> + spyOn window, 'log_event' + + it 'submit event log', -> + @navigation.log {}, { + newHeader: + text: -> "new" + oldHeader: + text: -> "old" + } + + expect(window.log_event).toHaveBeenCalledWith 'accordion', + newheader: 'new' + oldheader: 'old' diff --git a/templates/coffee/spec/courseware_spec.js b/templates/coffee/spec/courseware_spec.js new file mode 100644 index 0000000000..195ea7b73b --- /dev/null +++ b/templates/coffee/spec/courseware_spec.js @@ -0,0 +1,85 @@ +// Generated by CoffeeScript 1.3.2-pre +(function() { + + describe('Courseware', function() { + describe('bind', function() { + return it('bind the navigation', function() { + spyOn(Courseware.Navigation, 'bind'); + Courseware.bind(); + return expect(Courseware.Navigation.bind).toHaveBeenCalled(); + }); + }); + return describe('Navigation', function() { + beforeEach(function() { + loadFixtures('accordion.html'); + return this.navigation = new Courseware.Navigation; + }); + describe('bind', function() { + describe('when the #accordion exists', function() { + it('activate the accordion with correct active section', function() { + spyOn($.fn, 'accordion'); + $('#accordion').append(''); + Courseware.Navigation.bind(); + return expect($('#accordion').accordion).toHaveBeenCalledWith({ + active: 1, + header: 'h3', + autoHeight: false + }); + }); + it('binds the accordionchange event', function() { + Courseware.Navigation.bind(); + return expect($('#accordion')).toHandleWith('accordionchange', this.navigation.log); + }); + return it('bind the navigation toggle', function() { + Courseware.Navigation.bind(); + return expect($('#open_close_accordion a')).toHandleWith('click', this.navigation.toggle); + }); + }); + return describe('when the #accordion does not exists', function() { + beforeEach(function() { + return $('#accordion').remove(); + }); + return it('does not activate the accordion', function() { + spyOn($.fn, 'accordion'); + Courseware.Navigation.bind(); + return expect($('#accordion').accordion).wasNotCalled(); + }); + }); + }); + describe('toggle', function() { + return it('toggle closed class on the wrapper', function() { + $('.course-wrapper').removeClass('closed'); + this.navigation.toggle(); + expect($('.course-wrapper')).toHaveClass('closed'); + this.navigation.toggle(); + return expect($('.course-wrapper')).not.toHaveClass('closed'); + }); + }); + return describe('log', function() { + beforeEach(function() { + window.log_event = function() {}; + return spyOn(window, 'log_event'); + }); + return it('submit event log', function() { + this.navigation.log({}, { + newHeader: { + text: function() { + return "new"; + } + }, + oldHeader: { + text: function() { + return "old"; + } + } + }); + return expect(window.log_event).toHaveBeenCalledWith('accordion', { + newheader: 'new', + oldheader: 'old' + }); + }); + }); + }); + }); + +}).call(this); diff --git a/templates/coffee/spec/feedback_form_spec.coffee b/templates/coffee/spec/feedback_form_spec.coffee new file mode 100644 index 0000000000..191645b3d3 --- /dev/null +++ b/templates/coffee/spec/feedback_form_spec.coffee @@ -0,0 +1,28 @@ +describe 'FeedbackForm', -> + beforeEach -> + loadFixtures 'feedback_form.html' + + describe 'bind', -> + beforeEach -> + FeedbackForm.bind() + spyOn($, 'post').andCallFake (url, data, callback, format) -> + callback() + + it 'binds to the #feedback_button', -> + expect($('#feedback_button')).toHandle 'click' + + it 'post data to /send_feedback on click', -> + $('#feedback_subject').val 'Awesome!' + $('#feedback_message').val 'This site is really good.' + $('#feedback_button').click() + + expect($.post).toHaveBeenCalledWith '/send_feedback', { + subject: 'Awesome!' + message: 'This site is really good.' + url: window.location.href + }, jasmine.any(Function), 'json' + + it 'replace the form with a thank you message', -> + $('#feedback_button').click() + + expect($('#feedback_div').html()).toEqual 'Feedback submitted. Thank you' diff --git a/templates/coffee/spec/feedback_form_spec.js b/templates/coffee/spec/feedback_form_spec.js new file mode 100644 index 0000000000..2815cd73e5 --- /dev/null +++ b/templates/coffee/spec/feedback_form_spec.js @@ -0,0 +1,35 @@ +// Generated by CoffeeScript 1.3.2-pre +(function() { + + describe('FeedbackForm', function() { + beforeEach(function() { + return loadFixtures('feedback_form.html'); + }); + return describe('bind', function() { + beforeEach(function() { + FeedbackForm.bind(); + return spyOn($, 'post').andCallFake(function(url, data, callback, format) { + return callback(); + }); + }); + it('binds to the #feedback_button', function() { + return expect($('#feedback_button')).toHandle('click'); + }); + it('post data to /send_feedback on click', function() { + $('#feedback_subject').val('Awesome!'); + $('#feedback_message').val('This site is really good.'); + $('#feedback_button').click(); + return expect($.post).toHaveBeenCalledWith('/send_feedback', { + subject: 'Awesome!', + message: 'This site is really good.', + url: window.location.href + }, jasmine.any(Function), 'json'); + }); + return it('replace the form with a thank you message', function() { + $('#feedback_button').click(); + return expect($('#feedback_div').html()).toEqual('Feedback submitted. Thank you'); + }); + }); + }); + +}).call(this); diff --git a/templates/coffee/spec/helper.coffee b/templates/coffee/spec/helper.coffee new file mode 100644 index 0000000000..1f27e257c2 --- /dev/null +++ b/templates/coffee/spec/helper.coffee @@ -0,0 +1 @@ +jasmine.getFixtures().fixturesPath = "/_jasmine/fixtures/" diff --git a/templates/coffee/spec/helper.js b/templates/coffee/spec/helper.js new file mode 100644 index 0000000000..23b980d525 --- /dev/null +++ b/templates/coffee/spec/helper.js @@ -0,0 +1,6 @@ +// Generated by CoffeeScript 1.3.2-pre +(function() { + + jasmine.getFixtures().fixturesPath = "/_jasmine/fixtures/"; + +}).call(this); diff --git a/templates/coffee/src/calculator.coffee b/templates/coffee/src/calculator.coffee new file mode 100644 index 0000000000..7d62f5a794 --- /dev/null +++ b/templates/coffee/src/calculator.coffee @@ -0,0 +1,20 @@ +class window.Calculator + @bind: -> + calculator = new Calculator + $('.calc').click calculator.toggle + $('form#calculator').submit(calculator.calculate).submit (e) -> + e.preventDefault() + $('div.help-wrapper a').hover(calculator.helpToggle).click (e) -> + e.preventDefault() + + toggle: -> + $('li.calc-main').toggleClass 'open' + $('#calculator_wrapper #calculator_input').focus() + $('.calc').toggleClass 'closed' + + helpToggle: -> + $('.help').toggleClass 'shown' + + calculate: -> + $.getJSON '/calculate', { equation: $('#calculator_input').val() }, (data) -> + $('#calculator_output').val(data.result) diff --git a/templates/coffee/src/courseware.coffee b/templates/coffee/src/courseware.coffee new file mode 100644 index 0000000000..7772c1e533 --- /dev/null +++ b/templates/coffee/src/courseware.coffee @@ -0,0 +1,21 @@ +class window.Courseware + @bind: -> + @Navigation.bind() + + class @Navigation + @bind: -> + if $('#accordion').length + navigation = new Navigation + $('#accordion').bind('accordionchange', navigation.log).accordion + active: $('#accordion ul:has(li.active)').index('#accordion ul') + header: 'h3' + autoHeight: false + $('#open_close_accordion a').click navigation.toggle + + log: (event, ui) -> + log_event 'accordion', + newheader: ui.newHeader.text() + oldheader: ui.oldHeader.text() + + toggle: -> + $('.course-wrapper').toggleClass('closed') diff --git a/templates/coffee/src/feedback_form.coffee b/templates/coffee/src/feedback_form.coffee new file mode 100644 index 0000000000..bbb5c09365 --- /dev/null +++ b/templates/coffee/src/feedback_form.coffee @@ -0,0 +1,10 @@ +class window.FeedbackForm + @bind: -> + $('#feedback_button').click -> + data = + subject: $('#feedback_subject').val() + message: $('#feedback_message').val() + url: window.location.href + $.post '/send_feedback', data, -> + $('#feedback_div').html 'Feedback submitted. Thank you' + ,'json' diff --git a/templates/coffee/src/main.coffee b/templates/coffee/src/main.coffee new file mode 100644 index 0000000000..8a9a892f94 --- /dev/null +++ b/templates/coffee/src/main.coffee @@ -0,0 +1,8 @@ +$ -> + $.ajaxSetup + headers : { 'X-CSRFToken': $.cookie 'csrftoken' } + + Calculator.bind() + Courseware.bind() + FeedbackForm.bind() + $("a[rel*=leanModal]").leanModal() diff --git a/templates/main.html b/templates/main.html index 7078ed64d3..59a1ed7bd0 100644 --- a/templates/main.html +++ b/templates/main.html @@ -9,6 +9,7 @@ +