From: chapel Date: Mon, 14 Nov 2011 23:42:39 +0000 (-0800) Subject: Recent changes and alternatives X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=81e7efee4cb644bfe5906c9019be9aa6d6370235;p=oweals%2Ffinalsclub.git Recent changes and alternatives --- diff --git a/app.js b/app.js index 2799c58..bda6793 100644 --- a/app.js +++ b/app.js @@ -1548,7 +1548,7 @@ app.post( '/profile', loadUser, loggedIn, function( req, res ) { function loadSubject( req, res, next ) { if( url.parse( req.url ).pathname.match(/subject/) ) { ArchivedSubject.findOne({id: req.params.id }, function(err, subject) { - if ( err ) { + if ( err || !subject) { sendJson(res, {status: 'error', message: 'Subject with this ID does not exist'} ) } else { req.subject = subject; @@ -1563,7 +1563,7 @@ function loadSubject( req, res, next ) { function loadOldCourse( req, res, next ) { if( url.parse( req.url ).pathname.match(/course/) ) { ArchivedCourse.findOne({id: req.params.id }, function(err, course) { - if ( err ) { + if ( err || !course ) { sendJson(res, {status: 'error', message: 'Course with this ID does not exist'} ) } else { req.course = course; @@ -1603,7 +1603,7 @@ app.get( '/learn/random', loadUser, function( req, res ) { app.get( '/archive', checkAjax, loadUser, function( req, res ) { ArchivedSubject.find({}).sort( 'name', '1' ).run( function( err, subjects ) { - if ( err ) { + if ( err || subjects.length === 0) { sendJson(res, {status: 'error', message: 'There was a problem gathering the archived courses, please try again later.'} ); } else { sendJson(res, { 'subjects' : subjects, 'user': req.user.sanitized } ); @@ -1613,7 +1613,7 @@ app.get( '/archive', checkAjax, loadUser, function( req, res ) { app.get( '/archive/subject/:id', checkAjax, loadUser, loadSubject, function( req, res ) { ArchivedCourse.find({subject_id: req.params.id}).sort('name', '1').run(function(err, courses) { - if ( err ) { + if ( err || courses.length === 0 ) { sendJson(res, {status: 'error', message: 'There are no archived courses'} ); } else { sendJson(res, { 'courses' : courses, 'subject': req.subject, 'user': req.user.sanitized } ); @@ -1623,21 +1623,22 @@ app.get( '/archive/subject/:id', checkAjax, loadUser, loadSubject, function( req app.get( '/archive/course/:id', checkAjax, loadUser, loadOldCourse, function( req, res ) { ArchivedNote.find({course_id: req.params.id}).sort('name', '1').run(function(err, notes) { - if ( err ) { + if ( err || notes.length === 0) { sendJson(res, {status: 'error', message: 'There are no notes in this course'} ); } else { - sendJson(res, { 'notes' : notes, 'course' : req.course, 'user': req.user.sanitized } ); + notes = notes.map(function(note) { return note.sanitized }); + sendJson(res, { 'notes': notes, 'course' : req.course, 'user': req.user.sanitized } ); } }) }) app.get( '/archive/note/:id', checkAjax, loadUser, function( req, res ) { ArchivedNote.findById(req.params.id, function(err, note) { - if ( err ) { + if ( err || !note ) { sendJson(res, {status: 'error', message: 'This is not a valid id for a note'} ); } else { ArchivedCourse.findOne({id: note.course_id}, function(err, course) { - if ( err ) { + if ( err || !course ) { sendJson(res, {status: 'error', message: 'There is no course for this note'} ) } else { sendJson(res, { 'layout' : 'notesLayout', 'note' : note, 'course': course, 'user': req.user.sanitized } ); diff --git a/models.js b/models.js index e05e4d1..31a4171 100644 --- a/models.js +++ b/models.js @@ -412,6 +412,14 @@ var ArchivedNote = new Schema({ text: String }) +ArchivedNote.virtual( 'sanitized' ).get(function() { + var note = { + _id: this._id, + topic: this.topic + } + return note; +}) + mongoose.model( 'ArchivedNote', ArchivedNote ) var ArchivedSubject = new Schema({ diff --git a/public/index2.html b/public/index2.html new file mode 100644 index 0000000..1a5f79a --- /dev/null +++ b/public/index2.html @@ -0,0 +1,411 @@ + + + + + FinalsClub.org + + + + + + + + + + + + + + + + + + + +
+
+
 
+
+ +
 
+
+ +
+ + + +
+ + + + + +
+
+
+

+ Welcome to FinalsClub.org, a 501(c)(3) non-profit + open education project dedicated to helping college + students collaborate, learn, and share their + knowledge freely online. +

+

+ Please create an account with your school email address + to try our tools or browse our course archive to learn + something new. + Thank you for helping us improve access to education, + one lecture at a time. +

+

+
Learn something >>
+

+ +
+
+ +
+ + + +
+

Universities

+
+
__name__
+
__description__
+
+
+ + + +
+

Courses for

+
+
__department__
+ +
+
+ + + +
+
+

Lectures for Course __number__ : __name__

+ Subject: __subject__
+ Department: __department__
+
+
+ Instructor: __name__ (__email__)
+
+
+
+ __name__
+ Created: __date__
+
+
+
+ + + +
+

Notepads

+
+
+ __name__ +
+
+
+ + + +
+

Archived Subjects

+

+ Please browse our archive of past courses + covered at Harvard from 2008 through 2010. +

+ + +
+ + + +
+

Archived Courses

+ + +
+ + + +
+

Archived Notes

+ +
+ + + +
+
+

__topic__

+
__text__
+
+
+ + + +
+

Create an Account

+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
+   +
+
+ +
+
+
+
+
+ + + +
+

Login

+
+
+
+
+ +
+
+ +
+
+
+
+ +
+
+ +
+
+
+
  +
+
+ + + Forgot password? + +
+
+
+
  +
+ +
+
+
+
+ + +
+
+

Code of Conduct

+

+ Keep it academic. +

+

+ This directive is deliberately vague to + accommodate creative humor, insight, and exploration.
+ Disruptive or irrelevant material, however, + will be subject to removal.
+ Just keep it academic, and we'll all be better off.
+

+
+
+ + + + +
+

FinalsClub in the Press

+
+ +

December 13, 2009

+

Plenty of Harvard graduates have traded on the fame and prestige of their alma mater, but few have done so the way Andrew Magliozzi has. The year he graduated, 2005, he started a tutoring company located steps from Harvard Yard, with a name, Veritas, that is the motto of his storied alma mater.

+

Then, two years ago, Magliozzi started up a side project called Finalsclub.org.

+

+ Read more ... +

+
+
+
+ +

Wednesday, February 18, 2009

+

A rapidly growing course preparatory Web site, FinalsClub.org, is moving forward with a plan to expand its site in spite of controversy over the legality of the venture.

+

The Web site, which allows students to share notes, create study groups, and blog about lectures and sections, recently hired 10 Harvard College students to serve as BETA testers for the site.

+

+ Read more ... +

+
+
+
+ +

September 27th, 2009

+

Computer Science professor and former Dean of Harvard, Harry Lewis, embraces FinalsClub's work and its guiding principle of open education. Even as Harvard University has not been wholly sympathetic to the FinalsClub mission, invoking the Copyright Act of 1976, assuming a similar position to other major institutions such as University of Texas, Lewis supports working towards the proverbial "temple of the free exchange of ideas." A course he taught in the Harvard Extension School was also shared freely online.

+

+ Read more ... +

+
+
+ + + + +
+

Page Not Found

+ Sorry, there is no content for this page. +
+ + + + +
+ + + + + +
+

+ This work is licensed under a + Creative Commons Attribution-ShareAlike 3.0 + United States License +

+

+ Creative Commons License + Real Time Web Analytics +

+
+ + + + + + diff --git a/public/javascripts/main2.js b/public/javascripts/main2.js new file mode 100644 index 0000000..41b9f0f --- /dev/null +++ b/public/javascripts/main2.js @@ -0,0 +1,376 @@ + +/* + +This is the core logic for the main page. +It implements most page transitions by showing and hiding DIV elements +in the page with javascript+jquery + +*/ + + +/* Convert a JSON string to an object, or null if unparseable */ +function j2o(json) { try { return JSON.parse(json); } catch(e) { return null; } } + +/* Convert an object to a JSON string (just easier to type than "JSON.stringify" */ +function o2j(obj) { return JSON.stringify(obj); } + + + +function showHome(cb) { + cb("home"); +} + + + +// go to the page that lists the schools +function showSchools(response, cb) { + + var path = window.location.pathname; + + ProtoDiv.reset("PROTO_school"); + + + var schools = [] + if(typeof response == 'object') { + schools = response.schools + } + + ProtoDiv.replicate("PROTO_school", schools); + + cb("schools"); + +} + + + +// go to the page that lists the courses for a specific school +function showCourses(response, cb) { + + var path = window.location.pathname; + + + ProtoDiv.reset("PROTO_course"); + + var courses = [] + if(typeof response == 'object') { + var school = response.school + $("#school_name").html(school.name); + courses = school.courses + } + + ProtoDiv.replicate("PROTO_course", courses); + + cb("courses") +} + + + + +// go to the page that lists the lectures for a specific course +function showLectures(response, cb) { + + var path = window.location.pathname; + + + ProtoDiv.reset("PROTO_lecture"); + + ProtoDiv.reset("PROTO_lectures_head") + ProtoDiv.reset("PROTO_lectures_instructor") + ProtoDiv.reset("PROTO_lecture") + + if(typeof response == 'object') { + + var course = response.course + if(course) + ProtoDiv.replicate("PROTO_lectures_head", [course]) + + var instructor = response.instructor + if(instructor) + ProtoDiv.replicate("PROTO_lectures_instructor", [instructor]) + + var lectures = response.lectures + if(lectures) + ProtoDiv.replicate("PROTO_lecture", lectures); + + } + + cb("lectures") +} + + + +// go to the page that lists the note taking sessions for a specific lecture +function showNotes(response, cb) { + + var path = window.location.pathname; + + + ProtoDiv.reset("PROTO_note"); + + if(typeof response == 'object') { + + var course = response.course + //if(course) + // ProtoDiv.replicate("PROTO_lectures_head", [course]) + + var instructor = response.instructor + //if(instructor) + // ProtoDiv.replicate("PROTO_lectures_instructor", [instructor]) + + var lecture = response.lecture + //if(lecture) + // ProtoDiv.replicate("PROTO_lecture", lectures); + + var notes = response.notes + if(notes) + ProtoDiv.replicate("PROTO_note", notes); + + } + + cb("notes") +} + + +// go to the page that lists the archived subject names +function showArchiveSubjects(response, cb) { + + var path = window.location.pathname; + + ProtoDiv.reset("PROTO_archive_subject") + + var subjects = response.subjects + + ProtoDiv.replicate("PROTO_archive_subject", subjects) + + cb("archive_subjects") +} + + + +function showArchiveCourses(response, cb) { + + var path = window.location.pathname; + + + ProtoDiv.reset("PROTO_archive_course") + + var courses = response.courses + + ProtoDiv.replicate("PROTO_archive_course", courses) + + cb("archive_courses") +} + + + +function showArchiveNotes(response, cb) { + + var path = window.location.pathname; + + + ProtoDiv.reset("PROTO_archive_note") + + var notes = response.notes + $.each(notes, function(i, note) { + if(!note.topic) + note.topic = note._id//note.text.substr(0, 15)+" ..." + }) + + ProtoDiv.replicate("PROTO_archive_note", notes) + + cb("archive_notes") +} + + + +function showArchiveNote(response, cb) { + + var path = window.location.pathname; + + + ProtoDiv.reset("PROTO_archive_note_display") + + var note = response.note +note = { text: "Hi Mom!", topic: "21st Century Greetings" } + if(!note.topic) + note.topic = note.text.substr(0, 15)+" ..." + + ProtoDiv.replicate("PROTO_archive_note_display", note) + + cb("archive_note_display") +} + + + +// go to the account registration page +function showRegister(response, cb) { + // xxx clear fields? + // xxx change FORM to use AJAX + cb("register"); +} + + +function showLogin(response, cb) { + cb("login"); +} + + + + +// go to the press articles page +function showPress(response, cb) { + cb("press"); +} + + +// go to the "code of conduct" page +function showConduct(response, cb) { + cb("conduct"); +} + + + + +var pageVectors = [ + { regex: /^\/(index.html)?$/, func: showHome }, + { regex: /^\/schools/, func: showSchools }, + { regex: /^\/school\/([a-f0-9]{24})/, func: showCourses }, + { regex: /^\/course\/([a-f0-9]{24})/, func: showLectures }, + { regex: /^\/lecture\/([a-f0-9]{24})/, func: showNotes }, + { regex: /^\/archive\/?$/, func: showArchiveSubjects }, + { regex: /^\/archive\/subject\/([0-9]+)/, func: showArchiveCourses }, + { regex: /^\/archive\/course\/([0-9]+)/, func: showArchiveNotes }, + { regex: /^\/archive\/note\/([0-9]+)/, func: showArchiveNote }, + { regex: /^\/login/, func: showLogin }, + { regex: /^\/register/, func: showRegister }, + { regex: /^\/press/, func: showPress }, + { regex: /^\/conduct/, func: showConduct }, +]; + +var testVectors = { + schools: showSchools, + school: showCourses, + course: showLectures, + lecture: showNotes, + archive: showArchiveSubjects, + archivesubject: showArchiveCourses, + archivecourse: showArchiveNotes, + archivenote: showArchiveNote, + login: showLogin, + press: showPress, + conduct: showConduct +} + +/* Do and show the appropriate thing, based on the pages current URL */ +function showPage(y) { + + var path = document.location.pathname + + var mainSlug = path.match(/((?:[a-z][a-z]+))/) ? path.match(/((?:[a-z][a-z]+))/)[1].toLowerCase() : ''; + if (mainSlug === 'archive') { + var archiveSlugs = path.match(/((?:[a-z][a-z]+))\/((?:[a-z][a-z0-9_]*))/); + if (archiveSlugs) { + mainSlug = mainSlug + archiveSlugs[2]; + } + } + + $(".page").hide(); //(100); // hide all pseudo pages + + if (testVectors[mainSlug]) { + return $.get(path, { cache: false }, function(response) { + if (response.status === 'error') { + console.log(response.message) + $("#pg_notfound").fadeIn(100); + window.scroll(0, 0) + return; + } + testVectors[mainSlug](response, function(pageId) { + $("#pg_"+pageId).fadeIn(100); + window.scroll(0, y) + }) + }); + } else if (path === '/') { + return showHome(function(pageId) { + $("#pg_"+pageId).fadeIn(100); + window.scroll(0, y) + }) + } + + $("#pg_notfound").fadeIn(100); + window.scroll(0, 0) + /* + for(var i = 0; i < pageVectors.length; i++) { + var vector = pageVectors[i] + var matches = path.match(vector.regex) + if(matches) { + vector.func(function(pageId) { + + $("#pg_"+pageId).fadeIn(100); + + window.scroll(0, y) + + }) + break + } + } + + + if(i == pageVectors.length) { + } + // scroll to top of page (as if we'd done a real page fetch) + /*$('html, body').animate({ + scrollTop: $("#topofcontent").offset().top + }, 100);*/ + +} + + + + +/* Simulates a page load. + 'path' is something like "/schools", etc. + A page fetch doesn't really happen. + Based on what path looks like, an appropriate DIV is shown, and action taken +*/ +var topQueue = [0] +function goPage(path) { + var y = 0 + window.pageYOffset + topQueue.push(y) + history.pushState({}, path, path); + showPage(0); +} + + +/* Simulates a "back" browser navigation. */ +function goBack(event) { + var y = topQueue.pop() + showPage( y ); +} + + + window.onpopstate = goBack + + $('a[href^=/]').live('click', function(e) { + var path = e.target.pathname || '/'; + var checkNote = path.match(/((?:[a-z][a-z]+))/); + if (checkNote && checkNote[1] == 'note') { + return true; + } else { + goPage(path) + return false; + } + }) +$(document).ready(function() { + + // This code executes after the page has been fully loaded + + + // xxx older FF browsers don't fire a page load/reload - deal with it somehow. + // showPage( 0 ); // needed for some older browsers, redundant for chrome + +}) + + + + +