Skip to content

Instantly share code, notes, and snippets.

@e0da
Created April 13, 2012 17:54
Show Gist options
  • Save e0da/2378803 to your computer and use it in GitHub Desktop.
Save e0da/2378803 to your computer and use it in GitHub Desktop.
The Gevirtz School Faculty Listing Bio
/*!
* Faculty Listing Bio
* http://education.ucsb.edu/Faculty-Research/Faculty-Listing/
*
* Copyright (c) 2011 Justin Force and the UC Regents
* Licensed under the BSD 3-Clause License
*/
/*jslint browser: true, indent: 2 */
/*global jQuery, muster */
(function ($) {
'use strict';
var person, query, queries,
$window = $(window),
VITAE_PATH = 'http://education.ucsb.edu/Faculty-Research/vitae/%s.pdf',
IMG = '<img src="http://education.ucsb.edu/Faculty-Research/images/members/%s.jpg" alt="%s %s %s"/>',
args = {};
// add trim method to String prototype if it doesn't already exist (IE<9)
//
if (!String.prototype.trim) {
String.prototype.trim = function () {
return this.replace(/^\s+/, '').replace(/\s+$/, '');
};
}
// Parse arguments. URL key=value pairs populate `args` with args[key] = value.
//
// `http://.../?first=Bob&last=Foo` yields `args = { first: 'Bob', last: 'Foo' }`
//
// N.B. does not handle multiple arguments with the same name. The last
// argument to appear is the one used. So `?first=Foo&first=Bar` will
// yield `args.first == 'Bar'`
//
//
$.each(location.href.split('?')[1].split('&'), function () {
var arg = this.split('=');
args[arg[0]] = window.unescape(arg[1]);
});
/////////////////////////////////////////////////////////////////////////////
// helper functions
/////////////////////////////////////////////////////////////////////////////
/*
* return a link to uri with text as label as a jQuery object
*/
function link(uri, text) {
if (uri && text) {
return $('<a href="%s">%s</a>'.replace('%s', uri).replace('%s', text));
} else {
return null;
}
}
/*
* return a set of 9 digits as a (123) 456-7890 phone number
*/
function phone(num) {
if (num) {
// (Tell JSLint to look away. /[^\d]/g really is the simplest and clearest
// way to say "everything but numbers")
//
/*jslint regexp: true */
var ret = num.replace(/[^\d]/g, '').replace(/(\d\d\d)(\d\d\d)(\d\d\d\d)/, '($1) $2-$3');
/*jslint regexp: false */
return ret;
} else {
return null;
}
}
/*
* return the appropriate link for the given department as a jQuery object
*/
function departmentLink(dept) {
var depts = {
'Department of Education':
'/Graduate-Studies/Education/home.htm',
'Department of Counseling, Clinical & School Psychology':
'/Graduate-Studies/CCSP/CCSP-home.html',
'Teacher Education Program':
'/Grduate-Studies/Teacher-Education-Program/home.htm'
};
if (!depts[dept]) {
return;
} else {
return link(depts[dept], dept);
}
}
/* Add a definition to `dl` defined as an array `def` of the form
*
* [
* 'Text for Term'
* 'text, jQuery element or array of text and/or elements for definition'
* ]
*/
function addDefinition(dl, def) {
var label = def[0],
value = def[1];
// just return if value appears to be blank
if (!value) {
return;
}
// if value isn't an array, put it in an array
if (!(value instanceof Array)) {
value = [value];
}
// prune empty values
value = $.grep(value, function (e) { return e; });
// if the value array is empty, just return
if (value.length === 0) {
return;
}
// if we made it this far, there is data to be displayed so set the dt
dl.append($('<dt>').text(label));
$.each(value, function () {
if (this) {
if (this instanceof String || typeof this === 'string') {
// XXX Have to handle strings separately because IE is awful. Can't
// use $('<dd>').text(this) because IE is really, really awful.
//
dl.append($('<dd>' + this + '</dd>'));
} else {
dl.append($('<dd>').append(this));
}
}
});
}
/*
* return the list of publications as an array of html strings, each
* representing one publication
*/
function publications(pubs) {
var ret = [];
function publication(pub) {
var text = [];
if (pub.authors) {
text.push(pub.authors.trim().replace(/\.$/, ''));
}
if (pub.title) {
text.push('"' + pub.title.trim() + '"');
}
if (pub.publisher) {
text.push('<em>' + pub.publisher.trim() + '</em>');
}
if (pub.year) {
text.push(pub.year.trim());
}
if (pub.category) {
text.push('[' + pub.category.trim() + ']');
}
return text.join('. ');
}
$.each(pubs, function () {
if (this) {
ret.push(publication(this));
}
});
if (ret.length === 0) {
return null;
} else {
return ret;
}
}
/*
* return the list of awards as an array of html strings, each representing
* one award
*/
function awards(aws) {
var ret = [];
function award(aw) {
var text = aw.award.trim();
if (aw.year_awarded) {
text += ', ' + aw.year_awarded.trim();
}
return text;
}
$.each(aws, function () {
if (this) {
ret.push(award(this));
}
});
if (ret.length === 0) {
return null;
} else {
return ret;
}
}
function populatePage(person) {
// These variables can be reused for each column
var column, dl, pic;
column = $('<div>');
dl = $('<dl>');
column.append(dl);
$.each([
[
'Department' + (person.department2 ? 's' : ''),
[departmentLink(person.department1), departmentLink(person.department2)]
],
[
'Links',
[
link(person.personal_website, 'Personal Website'),
link(person.group_research_website, 'Group Research Website'),
link(person.vitae, 'Vitae')
]
],
[
'Office Number',
person.office_room_number
],
[
'Phone Number',
phone(person.phone)
],
[
'Fax',
phone(person.fax)
],
[
'Email',
link('mailto:' + person.email, person.email)
]
], function () {
addDefinition(dl, this);
});
// Insert the column content when the page loads
$(function () {
$('#musterLeftContent').append(column.children());
});
// Populate center column
//
column = $('<div>');
dl = $('<dl>');
column
.append($('<h1 class=header></h1>').text(person.first_name + ' ' + person.last_name))
.append($('<h2 class=Paltino14pxBlackBold></h2>').text(person.title + ', ' + person.education))
.append(dl);
$.each([
[
'Emphasis:',
person.emphases
],
[
'Research Interests:',
person.research_interests
],
[
'Biography:',
person.biography
],
[
'Selected Publications:',
person.publications
],
[
'Awards and Honors:',
person.awards
],
[
'Affiliations:',
person.affiliations
]
], function () {
addDefinition(dl, this);
});
// Insert the column content when the page loads
$(function () {
$('#musterCenterContent').append(column.children());
});
// Populate right column
//
column = $('<div>');
// Tell JSLint to look away. /[^a-z]/g really is the simplest and
// clearest way to say "letters only."
//
/*jslint regexp: true */
pic = $(IMG
.replace('%s', (person.first_name + person.last_name).toLowerCase().replace(/[^a-z]/g, ''))
.replace('%s', person.title)
.replace('%s', person.first_name)
.replace('%s', person.last_name));
/*jslint regexp: false */
// Show a place holder if the image doesn't exist
pic.bind('error', function () {
this.src = 'http://education.ucsb.edu/Faculty-Research/images/faculty-placeholder.gif';
});
column.append(pic);
// Insert the column content when the page loads
$(function () {
$('#musterRightContent').append(column.children());
});
}
/////////////////////////////////////////////////////////////////////////////
// Event handling matrix
/////////////////////////////////////////////////////////////////////////////
// The page depends on the results of several JSONP queries. Some depend upon
// others. These events will enable each query to notify its dependent
// actions when it's finished, so everything can do its own thing
// asynchronously and we can assemble the results when all of the queries
// have finished.
/////////////////////////////////////////////////////////////////////////////
//
queries = {
researchInterests: false,
department1: false,
department2: false,
emphasis: false,
publications: false,
awards_and_honors: false,
affiliations: false,
education: false
};
function queryFinished(query) {
return function () {
queries[query] = true;
$window.trigger('query_finished');
};
}
for (query in queries) {
if (queries.hasOwnProperty(query)) {
$window.bind(query, queryFinished(query));
}
}
$window.bind('query_finished', function () {
var query;
for (query in queries) {
if (queries.hasOwnProperty(query)) {
if (!queries[query]) {
return;
}
}
}
$window.trigger('all_finished');
});
$window.bind('all_finished', function () {
populatePage(person);
// XXX If the adjustLayout function exists in the global scope, it means
// that we're on one of the pages using the old, stupid 3 column layout
// script. After a filter, we have to adjust the layout.
//
if (window.adjustLayout) {
window.adjustLayout();
}
});
//////////////////////////////////////////////////////////////////////////////
// Primary Query
//////////////////////////////////////////////////////////////////////////////
// The primary query for the profile. This gets the person and then
// performies each of the additional queries as needed. Each subsequent query
// is labeled with the event that it calls upon completion.
//////////////////////////////////////////////////////////////////////////////
muster('ggsedb').query({
select: '*',
from: 'profile',
where: "active = 'yes' and first_name = '%s' and last_name = '%s'".replace(/%s/, args.first).replace(/%s/, args.last)
}, function () {
person = this.results[0];
// If nobody with this name was found, notify the user and redirect back to the faculty listing
//
if (!person) {
$(function () {
$('#musterCenterContent').html([
'Could not find bio for <strong>',
args.first,
args.last,
'</strong>. Redirecting back to Faculty Listing...'
].join(' '));
setTimeout(function () {
location.href = 'index.html';
}, 1000);
});
return;
}
// set vitae path. This isn't stored in the database and must be calculated.
//
/*jslint regexp: true */
person.vitae = VITAE_PATH
.replace('%s', (person.first_name + person.last_name)
.toLowerCase()
.replace(/[^a-z]/g, ''));
/*jslint regexp: false */
if (!person.vitae_available) {
person.vitae = undefined;
}
// education
//
muster('ggsedb').query({
select: 'degree,institution',
from: 'education',
where: 'profile_id = ' + person.id,
order: '"year" desc',
limit: '1'
}, function () {
var ed = this.results[0];
person.education = '%d (%i)'.replace(/%d/, ed.degree).replace(/%i/, ed.institution);
$window.trigger('education');
});
// departments
//
// Since there's no join table, we have to run a query per department. to
// simplify this, use an array [1,2], but the "finished" events are still
// department1 and department2.
//
$.each([1, 2], function () {
var n = this,
dept_id = person['department' + n + '_id'];
if (!dept_id) {
$window.trigger('department' + n);
return;
}
muster('ggsedb').query({
select: 'department_%d.name'.replace(/%d/, n),
from: 'department_%d'.replace(/%d/, n),
where: 'department_%d.id = %s'.replace(/%d/, n).replace(/%s/, dept_id)
}, function () {
person['department' + n] = (this.results[0] ? this.results[0].name : void 0);
$window.trigger('department' + n);
});
});
// emphasis
//
muster('ggsedb').query({
select: [
'emphasis_type_1.name as emphasis1',
'emphasis_type_2.name as emphasis2',
'emphasis_type_3.name as emphasis3'
].join(','),
from: [
'emphasis',
'emphasis_type_1 on emphasis.emphasis_type_id_1 = emphasis_type_1.id',
'emphasis_type_2 on emphasis.emphasis_type_id_2 = emphasis_type_2.id',
'emphasis_type_3 on emphasis.emphasis_type_id_3 = emphasis_type_3.id'
].join(' left join '),
where: 'emphasis.profile_id = ' + person.id
}, function () {
var emphasis = this.results[0];
if (emphasis) {
person.emphasis = $.grep([
emphasis.emphasis1,
emphasis.emphasis2,
emphasis.emphasis3
], function (e) { return e; }).join(', ');
}
$window.trigger('emphasis');
});
// researchInterests
//
muster('ggsedb').query({
select: 'interest',
from: 'research_interests',
where: 'profile_id = ' + person.id
}, function () {
var interests = [];
$.each(this.results, function () {
if (this.interest) {
interests.push(this.interest);
}
});
person.research_interests = $.grep(interests, function (e) { return e; }).join('; ');
$window.trigger('researchInterests');
});
// publications
//
// We try to get the publications that have been selected for display by
// the faculty. If none are found, we just show the 5 most recent
// publications.
//
muster('ggsedb').query({
select: 'authors,title,publisher,"year",category',
from: 'publications',
where: "faculty_webpage = '1' and status = 'Published' and publications.profile_id = " + person.id,
order: '"year" desc,publication_id desc'
}, function () {
if (this.results.length > 0) {
person.publications = publications(this.results);
$window.trigger('publications');
} else {
muster('ggsedb').query({
select: 'authors,title,publisher,"year",category',
from: 'publications',
where: "status = 'Published' and profile_id = " + person.id,
order: '"year" desc,publication_id desc',
limit: '5'
}, function () {
person.publications = publications(this.results);
$window.trigger('publications');
});
}
});
// awards and honors
//
muster('ggsedb').query({
select: 'award,year_awarded',
from: 'awards_and_honors',
where: [
'(year_awarded is null or year_awarded >= ',
(new Date()).getFullYear() - 5,
') and profile_id = ',
person.id
].join(''),
order: 'year_awarded desc'
}, function () {
person.awards = awards(this.results);
$window.trigger('awards_and_honors');
});
// affiliations
//
muster('ggsedb').query({
select: 'professional_affiliations',
from: 'professional_organizations_affiliations',
where: 'profile_id = ' + person.id
}, function () {
var affiliations = [];
$.each(this.results, function () {
if (this.professional_affiliations) {
affiliations.push(this.professional_affiliations.trim());
}
});
if (affiliations.length === 0) {
affiliations = null;
}
person.affiliations = affiliations;
$window.trigger('affiliations');
});
});
}(jQuery));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment