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); }
24 add: function(name, useAjax, cb) {
25 if (typeof useAjax === 'function') {
36 run: function(name, path) {
38 $('.nav').removeClass('active');
40 checkUser( function() {
42 if (router.routes[name].useAjax) {
49 if (data.status === 'not_found' || (typeof data === 'string')) {
50 return router.run('404');
52 router.routes[name].fn(data, render);
56 router.routes[name].fn(render);
62 function tmpl_render() {
64 $('.username').text(user.name).attr('href', '/profile');
65 $("#login_status").show();
66 $('#login_link').text('Logout').attr('href', '/logout');
67 $('#register_link').hide();
68 $('#sign_up-link').hide();
70 $('.username').text('Guest');
71 $("#login_status").hide();
72 $('#login_link').text('Login').attr('href', '/login');
73 $('#register_link').show();
74 $('#sign_up-link').show();
78 function render(pageId, response) {
81 $('.username').text(user.name).attr('href', '/profile');
82 $("#login_status").show();
83 $('#login_link').text('Logout').attr('href', '/logout');
84 $('#register_link').hide();
85 $('#sign_up-link').hide();
87 $('.username').text('Guest');
88 $("#login_status").hide();
89 $('#login_link').text('Login').attr('href', '/login');
90 $('#register_link').show();
91 $('#sign_up-link').show();
95 if (response instanceof Array) {
96 $.each(response, function() {
97 ProtoDiv.reset("PROTO_" + this.id)
98 ProtoDiv.replicate("PROTO_" + this.id, this.data)
101 ProtoDiv.reset("PROTO_" + response.id)
102 ProtoDiv.replicate("PROTO_" + response.id, response.data)
105 $("#pg_" + pageId).fadeIn(function() {
106 $("#g-footer").fadeIn(); // we don't want the footer jumping up and down
110 function message(type, msg) {
111 ProtoDiv.reset("PROTO_message");
112 ProtoDiv.replicate("PROTO_message", {type: type, msg: msg})
113 $("#messages").fadeIn(100);
116 function checkUser(cb) {
117 $.get('/checkuser', function(data) {
131 router.add('404', false, function() {
132 $("#pg_notfound").fadeIn(100);
137 router.add('legal', false, function() {
138 $("#pg_legal").fadeIn(100);
143 router.add('team', false, function() {
144 $("#pg_team").fadeIn(100);
149 router.add('contact', false, function() {
150 $("#pg_contact").fadeIn(100);
154 router.add('about', false, function() {
155 $("#pg_about").fadeIn(100);
158 router.add('home', false, function(cb) {
159 $('#learnsomething').unbind();
160 $('.nav').removeClass('active');
162 $('#signup').click(function(e) {
165 $('#learnsomething').click(function(e) {
166 $.get('/learn/random', function(data) {
167 if (data.status === 'ok') {
172 if ($('#vimeo-screencast').length === 0) {
173 $('.video-wrapper').html('<iframe id="vimeo-screencast" src="http://player.vimeo.com/video/30647271?title=0&byline=0&portrait=0&color=367da9" width="400" height="225" frameborder="0" webkitAllowFullScreen allowFullScreen></iframe>');
177 // go to the page that lists the schools
178 router.add('schools', function(data, cb) {
180 $('#school_link').addClass('active');
188 $('#pg_schools').fadeIn(function() {
189 $('#g-footer').fadeIn();
191 $('#schoolTmpl').tmpl( data.schools ).appendTo("#pg_schools #schools");
194 // go to the page that lists the courses for a specific school
195 router.add('school', function(data, cb) {
196 $('#school_link').addClass('active');
197 $('.sub_menu').hide();
198 //$('#new_course').unbind();
199 $('#form_course').hide().unbind();
203 data: data.school.courses
206 $('#pg_courses').fadeIn(function() {
207 $('#g-footer').fadeIn();
209 $("#school_name").html(data.school.name);
211 if (data.school.authorized) {
212 $('.sub_menu').show();
213 var form = $('#form_course');
217 form.submit(function(e) {
220 $.post(window.location.pathname, form.serialize(), function(data) {
221 if (data.status === 'error') {
222 message('error', data.message);
223 } else if (data.status === 'ok') {
225 goPage(window.location.pathname);
226 message('info', data.message);
232 $('#courseTmpl').tmpl( data.school.courses ).appendTo("#pg_courses #main-content");
235 // go to the page that lists the lectures for a specific course
236 router.add('course', function(data, cb) {
237 $('#school_link').addClass('active');
238 $('.sub_menu').hide();
239 $('#new_lecture').unbind();
250 if (data.instructor) {
252 id: 'lectures_instructor',
253 data: data.instructor
260 data: data.lectures.map(function(lecture) {
261 var date = new Date(lecture.date);
262 lecture.date = date.toDateString();
267 cb('lectures', response);
269 if (!data.instructor.email) {
270 $('.instructor_email').hide();
272 $('.instructor_email').show();
275 if (data.course.authorized) {
276 $('.sub_menu').show();
277 var form = $('#form_lecture');
281 form.submit(function(e) {
284 $.post(window.location.pathname, form.serialize(), function(data) {
285 if (data.status === 'error') {
286 message('error', data.message);
287 } else if (data.status === 'ok') {
289 goPage(window.location.pathname);
290 message('info', data.message);
299 // go to the page that lists the note taking sessions for a specific lecture
300 router.add('lecture', function(data, cb) {
301 $('#school_link').addClass('active');
302 $('.sub_menu').hide();
303 $('#new_note').unbind();
304 $('#form_note').hide().unbind();;
315 if (data.instructor) {
317 id: 'notes_instructor',
318 data: data.instructor
329 cb("notes", response);
331 if (!data.instructor.email) {
332 $('.instructor_email').hide();
334 $('.instructor_email').show();
337 if (data.lecture.authorized) {
339 var form = $('#form_note').show();
341 form.submit(function(e) {
344 $.post(window.location.pathname, form.serialize(), function(data) {
345 if (data.status === 'error') {
346 message('error', data.message);
347 } else if (data.status === 'ok') {
349 goPage(window.location.pathname);
350 message('info', data.message);
358 // go to the page that lists the archived subject names
359 router.add('archive', function(data, cb) {
360 $('#archive_link').addClass('active');
363 id: 'archive_subject',
367 cb("archive_subjects", response)
372 router.add('archivesubject', function(data, cb) {
373 $('.nav').removeClass('active');
374 $('#archive_link').addClass('active');
377 id: 'archive_course',
381 cb("archive_courses", response)
386 router.add('archivecourse', function(data, cb) {
387 $('#archive_link').addClass('active');
394 cb("archive_notes", response)
399 router.add('archivenote', function(data, cb) {
400 $('#archive_link').addClass('active');
403 id: 'archive_note_display',
407 cb("archive_note_display", response)
412 // go to the account registration page
413 router.add('register', false, function(cb) {
414 $('#register_link').addClass('active');
415 $('#form_register').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', data.message);
433 router.add('activate', function(data, cb) {
435 message('info', data.message);
438 router.add('profile', false, function(cb) {
439 $('#profile_link').addClass('active');
440 var form = $('#form_profile');
441 $('input[type=password]','#form_profile').val('');
442 $('#affiliation').attr('value', user.affil);
443 $('#showName').attr('checked', user.showName)
444 form.find('.email').text(user.email);
445 form.find('input[name=name]').val(user.name);
446 form.submit(function(e) {
449 $.post(window.location.pathname, form.serialize(), function(data) {
450 if (data.status === 'error') {
451 message('error', data.message);
453 } else if (data.status === 'ok') {
455 message('info', data.message);
462 router.add('login', false, function(cb) {
463 $('input','#form_login').val('');
464 $('#form_login').submit(function(e) {
469 $.post(window.location.pathname, form.serialize(), function(data) {
470 if (data.status === 'error') {
471 message('error', data.message);
473 } else if (data.status === 'ok') {
475 message('info', 'Successfully logged in');
482 router.add('logout', function(data, cb) {
484 message('info', 'Successfully logged out');
487 router.add('resetpass', false, function(cb) {
488 $('input','#form_resetpass').val('');
489 $('#form_resetpass').submit(function(e) {
494 $.post(window.location.pathname, form.serialize(), function(data) {
495 if (data.status === 'error') {
496 message('error', data.message);
498 } else if (data.status === 'ok') {
500 message('info', data.message);
507 router.add('resetpw', false, function(cb) {
508 $('input','#form_resetpw').val('');
509 $('#form_resetpw').submit(function(e) {
514 $.post(window.location.pathname, form.serialize(), function(data) {
515 if (data.status === 'error') {
516 message('error', data.message);
518 } else if (data.status === 'ok') {
520 message('info', data.message);
527 // go to the press articles page
528 router.add('press', false, function(cb) {
529 $('#press_link').addClass('active');
534 // go to the "code of conduct" page
535 router.add('conduct', false, function(cb) {
541 /* Do and show the appropriate thing, based on the pages current URL */
542 function showPage(y) {
544 $('.page').hide(); //(100);// hide all pseudo pages
545 $('#g-footer').hide();
548 path = document.location.pathname,
549 routes = router.routes,
550 slugs = path.split('/');
554 var mainSlug = slugs[0].toLowerCase() || 'home';
555 console.log(slugs[0].toLowerCase());
557 if (mainSlug === 'archive') {
559 mainSlug = mainSlug + slugs[1];
563 if (routes[mainSlug]) {
564 router.run(mainSlug, path)
573 /* Simulates a page load.
574 'path' is something like "/schools", etc.
575 A page fetch doesn't really happen.
576 Based on what path looks like, an appropriate DIV is shown, and action taken
579 function goPage(path) {
580 if (history.pushState !== undefined) {
581 topQueue.push(window.pageYOffset)
582 history.pushState({}, path, path);
585 document.location = path;
589 /* Simulates a "back" browser navigation. */
591 function goBack(event) {
593 console.timeEnd('pop')
594 showPage( topQueue.pop() );
598 console.time('no-pop')
599 window.onpopstate = goBack
601 $(document).ready(function() {
603 // This code executes after the page has been fully loaded
605 $('body').on('click', 'a[href^=/]', function(e) {
606 var path = e.target.pathname || '/';
607 var checkNote = path.match(/\/([a-zA-Z]+)/);
608 if (checkNote && checkNote[1] == 'note') {
610 } else if (!history.pushState) {
618 // xxx older FF browsers don't fire a page load/reload - deal with it somehow.
619 // I've increased the timeout, we need to avoid calling showPage twice. It causes page flicker.
620 setTimeout(function() {
621 console.timeEnd('no-pop')
623 showPage( 0 ); // needed for some older browsers, redundant for chrome