4 This is the core logic for the main page.
5 It implements most page transitions by showing and hiding DIV elements
6 in the page with javascript+jquery
11 /* Convert a JSON string to an object, or null if unparseable */
12 function j2o(json) { try { return JSON.parse(json); } catch(e) { return null; } }
14 /* Convert an object to a JSON string (just easier to type than "JSON.stringify" */
15 function o2j(obj) { return JSON.stringify(obj); }
21 add: function(name, useAjax, cb) {
22 if (typeof useAjax === 'function') {
31 run: function(name, path) {
32 $('.nav').removeClass('active');
33 checkUser(function() {
34 if (router.routes[name].useAjax) {
35 $.get(path, {cache: false}, function(data) {
36 if (data.status === 'not_found' || (typeof data === 'string')) {
37 return router.run('404');
39 router.routes[name].fn(data, render);
42 router.routes[name].fn(render);
48 function render(pageId, response) {
50 $('.username').text("Hi, "+user.name+"!");
51 $("#login_status").show();
52 $('#login_link').text('Logout').attr('href', '/logout');
53 $('#register_link').hide();
54 $('#profile_link').show();
56 $('.username').text('Guest');
57 $("#login_status").hide();
58 $('#login_link').text('Login').attr('href', '/login');
59 $('#register_link').show();
60 $('#profile_link').hide();
63 if (response instanceof Array) {
64 $.each(response, function() {
65 ProtoDiv.reset("PROTO_" + this.id)
66 ProtoDiv.replicate("PROTO_" + this.id, this.data)
69 ProtoDiv.reset("PROTO_" + response.id)
70 ProtoDiv.replicate("PROTO_" + response.id, response.data)
73 $("#pg_" + pageId).fadeIn(100);
76 function message(type, msg) {
77 ProtoDiv.reset("PROTO_message");
78 ProtoDiv.replicate("PROTO_message", {type: type, msg: msg})
79 $("#messages").fadeIn(100);
82 function checkUser(cb) {
83 $.get('/checkuser', function(data) {
96 router.add('404', false, function() {
97 $("#pg_notfound").fadeIn(100);
101 router.add('home', false, function(cb) {
102 $('#learnsomething').unbind();
103 $('.nav').removeClass('active');
105 $('#signup').click(function(e) {
108 $('#learnsomething').click(function(e) {
109 $.get('/learn/random', function(data) {
110 if (data.status === 'ok') {
115 if ($('#vimeo-screencast').length === 0) {
116 $('.video-wrapper').html('<iframe id="vimeo-screencast" src="http://player.vimeo.com/video/30647271?title=0&byline=0&portrait=0&color=367da9" width="460" height="259" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe>');
122 // go to the page that lists the schools
123 router.add('schools', function(data, cb) {
124 $('#school_link').addClass('active');
130 cb("schools", response);
135 // go to the page that lists the courses for a specific school
136 router.add('school', function(data, cb) {
137 $('#school_link').addClass('active');
138 $('.sub_menu').hide();
139 //$('#new_course').unbind();
140 $('#form_course').hide().unbind();
143 data: data.school.courses
146 $("#school_name").html(data.school.name);
148 if (data.school.authorized) {
149 $('.sub_menu').show();
150 var form = $('#form_course');
154 form.submit(function(e) {
157 $.post(window.location.pathname, form.serialize(), function(data) {
158 if (data.status === 'error') {
159 message('error', data.message);
160 } else if (data.status === 'ok') {
162 goPage(window.location.pathname);
163 message('info', data.message);
168 cb("courses", response)
174 // go to the page that lists the lectures for a specific course
175 router.add('course', function(data, cb) {
176 $('#school_link').addClass('active');
177 $('.sub_menu').hide();
178 $('#new_lecture').unbind();
179 $('#form_lecture').hide().unbind();;
190 if (data.instructor) {
192 id: 'lectures_instructor',
193 data: data.instructor
200 data: data.lectures.map(function(lecture) {
201 var date = new Date(lecture.date);
202 lecture.date = date.toDateString();
207 cb('lectures', response);
209 if (!data.instructor.email) {
210 $('.instructor_email').hide();
212 $('.instructor_email').show();
215 if (data.course.authorized) {
216 $('.sub_menu').show();
217 $('#new_lecture').click(function(e) {
220 var form = $('#form_lecture');
224 form.submit(function(e) {
227 $.post(window.location.pathname, form.serialize(), function(data) {
228 if (data.status === 'error') {
229 message('error', data.message);
230 } else if (data.status === 'ok') {
232 goPage(window.location.pathname);
233 message('info', data.message);
244 // go to the page that lists the note taking sessions for a specific lecture
245 router.add('lecture', function(data, cb) {
246 $('#school_link').addClass('active');
247 $('.sub_menu').hide();
248 $('#new_note').unbind();
249 $('#form_note').hide().unbind();;
260 if (data.instructor) {
262 id: 'notes_instructor',
263 data: data.instructor
274 cb("notes", response);
276 if (!data.instructor.email) {
277 $('.instructor_email').hide();
279 $('.instructor_email').show();
282 if (data.lecture.authorized) {
283 $('.sub_menu').show();
284 $('#new_note').click(function(e) {
287 var form = $('#form_note');
291 form.submit(function(e) {
294 $.post(window.location.pathname, form.serialize(), function(data) {
295 if (data.status === 'error') {
296 message('error', data.message);
297 } else if (data.status === 'ok') {
299 goPage(window.location.pathname);
300 message('info', data.message);
309 // go to the page that lists the archived subject names
310 router.add('archive', function(data, cb) {
311 $('#archive_link').addClass('active');
314 id: 'archive_subject',
318 cb("archive_subjects", response)
323 router.add('archivesubject', function(data, cb) {
324 $('.nav').removeClass('active');
325 $('#archive_link').addClass('active');
328 id: 'archive_course',
332 cb("archive_courses", response)
337 router.add('archivecourse', function(data, cb) {
338 $('#archive_link').addClass('active');
345 cb("archive_notes", response)
350 router.add('archivenote', function(data, cb) {
351 $('#archive_link').addClass('active');
354 id: 'archive_note_display',
358 cb("archive_note_display", response)
363 // go to the account registration page
364 router.add('register', false, function(cb) {
365 $('#register_link').addClass('active');
366 $('#form_register').submit(function(e) {
371 $.post(window.location.pathname, form.serialize(), function(data) {
372 if (data.status === 'error') {
373 message('error', data.message);
375 } else if (data.status === 'ok') {
377 message('info', data.message);
384 router.add('activate', function(data, cb) {
386 message('info', data.message);
389 router.add('profile', false, function(cb) {
390 $('#profile_link').addClass('active');
391 var form = $('#form_profile');
392 $('input[type=password]','#form_profile').val('');
393 $('#affiliation').attr('value', user.affil);
394 $('#showName').attr('checked', user.showName)
395 form.find('.email').text(user.email);
396 form.find('input[name=name]').val(user.name);
397 form.submit(function(e) {
400 $.post(window.location.pathname, form.serialize(), function(data) {
401 if (data.status === 'error') {
402 message('error', data.message);
404 } else if (data.status === 'ok') {
406 message('info', data.message);
413 router.add('login', false, function(cb) {
414 $('input','#form_login').val('');
415 $('#form_login').submit(function(e) {
420 $.post(window.location.pathname, form.serialize(), function(data) {
421 if (data.status === 'error') {
422 message('error', data.message);
424 } else if (data.status === 'ok') {
426 message('info', 'Successfully logged in');
433 router.add('logout', function(data, cb) {
435 message('info', 'Successfully logged out');
438 router.add('resetpass', false, function(cb) {
439 $('input','#form_resetpass').val('');
440 $('#form_resetpass').submit(function(e) {
445 $.post(window.location.pathname, form.serialize(), function(data) {
446 if (data.status === 'error') {
447 message('error', data.message);
449 } else if (data.status === 'ok') {
451 message('info', data.message);
458 router.add('resetpw', false, function(cb) {
459 $('input','#form_resetpw').val('');
460 $('#form_resetpw').submit(function(e) {
465 $.post(window.location.pathname, form.serialize(), function(data) {
466 if (data.status === 'error') {
467 message('error', data.message);
469 } else if (data.status === 'ok') {
471 message('info', data.message);
478 // go to the press articles page
479 router.add('press', false, function(cb) {
480 $('#press_link').addClass('active');
485 // go to the "code of conduct" page
486 router.add('conduct', false, function(cb) {
492 /* Do and show the appropriate thing, based on the pages current URL */
493 function showPage(y) {
495 $(".page").hide(); //(100); // hide all pseudo pages
497 var path = document.location.pathname
498 var routes = router.routes;
500 var slugs = path.split('/');
504 mainSlug = slugs[0].toLowerCase() || 'home';
506 if (mainSlug === 'archive') {
508 mainSlug = mainSlug + slugs[1];
512 if (routes[mainSlug]) {
513 router.run(mainSlug, path)
523 /* Simulates a page load.
524 'path' is something like "/schools", etc.
525 A page fetch doesn't really happen.
526 Based on what path looks like, an appropriate DIV is shown, and action taken
529 function goPage(path) {
530 if (history.pushState !== undefined) {
531 topQueue.push(window.pageYOffset)
532 history.pushState({}, path, path);
535 document.location = path;
540 /* Simulates a "back" browser navigation. */
542 function goBack(event) {
544 console.timeEnd('pop')
545 showPage( topQueue.pop() );
549 console.time('no-pop')
550 window.onpopstate = goBack
552 $(document).ready(function() {
554 // This code executes after the page has been fully loaded
556 $('body').on('click', 'a[href^=/]', function(e) {
557 var path = e.target.pathname || '/';
558 var checkNote = path.match(/\/([a-zA-Z]+)/);
559 if (checkNote && checkNote[1] == 'note') {
561 } else if (!history.pushState) {
569 // xxx older FF browsers don't fire a page load/reload - deal with it somehow.
570 setTimeout(function() {
571 console.timeEnd('no-pop')
573 showPage( 0 ); // needed for some older browsers, redundant for chrome