"use strict"; var _; // underscore 1.8.3 http://underscorejs.org/ var info; // info.js var course; // course.js var window, document; // browser environment var module, require; // node environment var console; // debug course = course || {}; if( typeof module !== 'undefined' && module.exports ) { // support for calling from node, only needed for Jack _ = require('underscore'); info = require('./info.js'); document = require('./node_document.js'); module.exports = course; } function toggleClass(el, name, state) { "use strict"; var rex = new RegExp('(\\s|^)'+name+'(\\s|$)'); var cur = rex.test(el.className); if( state === undefined ) state = !cur; if( state == cur ) return; if( state ) el.className += (el.className ? ' ': '') + name; else el.className = el.className.replace( rex, ' ' ).replace(/(^[\s]*|[\s]*$)/g,''); } function myEach( a, b ) { "use strict"; if( a === undefined || a === null ) return; if( _.isArray( a ) ) return _.each( a, b ); return b(a); } function myNotEach( a, b ) { if( a === undefined || a === null || a.length === 0 ) return b(); else return ""; } function myHTML( a ) { "use strict"; var ret; if( a === undefined || a === null ) ret = ''; else if( _.isString( a.HTML ) ) ret = a.HTML; else if( _.isFunction( a.HTML ) ) ret = a.HTML(); else ret = a.toString(); return _.isString(ret)?ret:''; } function mustache( mustacheTemplate, mustacheTemplateSettings ) { "use strict"; var underscoreTemplate = mustacheTemplate. replace( /{{#([^}]+)\|([^}]+)}}/g, "{[ this.myEach( $1, function( $2 ) { ]}" ). replace( /{{\^([^}]+)}}/g, "{[ this.myNotEach( $1, function( ) { ]}" ). replace( /{{\/[^}]*}}/g, "{[ } ); ]}" ). replace( /{{{([^}]+)}}}/g, "{[ __p += this.myHTML( $1 ); ]}" ); var underscoreTemplateSettings = _.extend( { evaluate: /\{\[([\s\S]+?)\]\}/g, interpolate: /\{\{\{([\s\S]+?)\}\}\}/g, escape: /\{\{([^\{][\s\S]*?)\}\}/g, variable: "info" }, mustacheTemplateSettings ); var underscoreTemplateFunction = _.template( underscoreTemplate, underscoreTemplateSettings ); var setup = {myEach,myNotEach,myHTML}; return (input) => { return underscoreTemplateFunction.call( setup, input ); }; } /****************************************************************************** * Date parsing */ var Weekdays = [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ]; var Months = [ "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December" ]; function parseDate( string ) { "use strict"; var shift, re, year, month, date, weekdayOf, weekdayAfter, nth, orig; if( ( string instanceof Date ) || ( string === undefined ) ) return string; function shortCompare( that ) { "use strict"; return this.substring(0,3) === that.substring(0,3); } // Fix the year to the current semester year = info.variable.Year; nth = 1; shift = 0; // clean up white space string = string.replace(/[\s]+/g," ").replace(/^[\s]+/,"").replace(/[\s]+$/,""); orig = string; // handle plus or minus N days re = /^(.*) (plus|minus) ([0-9]+) days?$/.exec( string ); if( re ) { string = re[1]; shift = (re[2]=="plus"?1:-1) * parseInt( re[3] ); } // Handle "3rd week of class" usually as part of "3rd week of class plus 2 days" re = /^([\S]+) of ([01-9]*(?:1st|2nd|3rd|[01-9]th)) week of class(?:es)?$/.exec( string ); if( re ) { string = info.variable.FirstDayOfClasses; weekdayOf = _.findIndex( Weekdays, shortCompare, re[1] ); nth = parseInt( re[2].substring( 0, re[2].length - 2 ) ); } // Handle "3rd Monday of November" re = /^(1st|2nd|3rd|4th|5th) (.*) of (.*)$/.exec( string ); if( re ) { nth = parseInt( re[1].substring( 0, re[1].length - 2 ) ); weekdayAfter = _.findIndex( Weekdays, shortCompare, re[2] ); month = _.findIndex( Months, shortCompare, re[3] ); string = Months[month] + " 1"; } // Handle "Nov 3rd" re = /^(.*) ([01-9]*(?:1st|2nd|3rd|[01-9]th))$/.exec( string ); if( re ) { string = string.substring( 0, string.length - 2 ); } re = new Date( string + ", " + year ); if(!re) throw Error({string,year}); re.setHours(12); if( weekdayOf !== undefined ) re.setDate( re.getDate() + (weekdayOf-re.getDay()) ); if( weekdayAfter !== undefined ) re.setDate( re.getDate() + ((7+weekdayAfter-re.getDay())%7) ); re.setDate( re.getDate() + (nth-1)*7 + shift ); re.text = orig; re.HTML = info.mustaches.date(re); if( _.isNaN( re.getDate() ) ) { re = Object.create( { HTML: orig, toString: function(){return orig;} } ); } return re; } function checkit( a, b ) { "use strict"; var pa, pb; pa = parseDate( a ); pb = parseDate( b ); if( pa.getTime() != pb.getTime() ) { console.log( {a:a,b:b,pa:pa,pb:pb} ); } } Date.prototype.getWeekOfClass = function(FirstDayOfClasses) { "use strict"; if(FirstDayOfClasses===undefined) FirstDayOfClasses = info.variable.FirstDayOfClasses; FirstDayOfClasses = parseDate( FirstDayOfClasses ); FirstDayOfClasses.setDate( FirstDayOfClasses.getDate() -FirstDayOfClasses.getDay() + 1); return Math.floor( ((this.getTime() - FirstDayOfClasses.getTime())/(1000*60*60*24) + 0.1) / 7 ); }; function dateRangeToHTML( beg, end ) { return (end===undefined)?beg:(""+ beg.HTML+ " to " + end.HTML + ""); } function dateCheck() { "use strict"; return true; // For Spring 2016 checkit( "Wed of 1st week of class", "Jan 13" ); checkit( "1st Monday of September", "Sep 5" ); checkit( "4th Thursday of November", "Nov 24" ); checkit( "Thu of 12th week of class", "Nov 12" ); checkit( "Thu of 13th week of class", "Nov 19" ); checkit( "4th Thursday of November minus 1 day", "Nov 25" ); } /****************************************************************************** * End Date parsing */ /****************************************************************************** * Building parsing */ var Buildings = { //"TEB": { number: "0001", title:"Taylor Education Building" }, "BLH": { number: "0012", title:"Blazer Hall" }, // too new for list? //"DH": { number: "0017", title:"Dickey Hall" }, //"FA": { number: "0022", title:"Fine Arts Building" }, //"CB": { number: "0025", title:"White Hall Classroom Building" }, "Worsham": { number: "0026", title:"Worsham theater" }, // also known as "SCA" //"BH": { number: "0028", title:"Barker Hall" }, //"BE": { number: "0034", title:"Business and Economics Building" }, //"KAS": { number: "0044", title:"Kastle Hall" }, //"FB": { number: "0054", title:"Funkhouser Building" }, //"CP": { number: "0055", title:"Chemistry-Physics Building" }, //"TPC": { number: "0073", title:"Thomas Poe Cooper Building" }, //"LCLI": { number: "0224", title:"Lucille Caudill Little Fine Arts Library" }, //"BS": { number: "0225", title:"Thomas Hunt Morgan Biological Sciences Building" }, "NURS": { number: "0232", title:"Nursing Building" }, // also known as "CN"? "NUR": { number: "0232", title:"Nursing Building" }, // also known as "CN"? //"RGAN": { number: "0503", title:"Ralph G. Anderson Building" }, // from 2013, data was fairly dirty 'TEB': { number: '0001', title: 'Taylor Education Building'}, 'SSB': { number: '0002', title: 'Scott Street Building'}, 'JSR': { number: '0007', title: 'Jewell Hall'}, 'BOYD':{ number: '0008', title: 'Boyd Hall'}, 'PAHA':{ number: '0009', title: 'Patterson Hall'}, 'HH': { number: '0010', title: 'Hamilton House'}, 'DH': { number: '0017', title: 'Dickey Hall'}, 'MC': { number: '0019', title: 'Memorial Coliseum'}, 'ER': { number: '0021', title: 'Old Engineering Residence'}, 'FA': { number: '0022', title: 'Fine Arts Building'}, 'L': { number: '0024', title: 'Lafferty Hall'}, 'CB': { number: '0025', title: 'White Hall Classroom Building'}, 'SCA': { number: '0026', title: 'Student Center Addition'}, 'POT': { number: '0027', title: 'Patterson Office Tower'}, 'BH': { number: '0028', title: 'Barker Hall and Buell Armory'}, 'AG': { number: '0029', title: 'Alumni Gymnasium'}, 'SC': { number: '0030', title: 'Student Center'}, 'FH': { number: '0031', title: 'Frazee Hall'}, 'MAIN':{ number: '0032', title: 'Main Building'}, 'GB': { number: '0033', title: 'Ezra Gillis Building'}, 'BE': { number: '0034', title: 'Carol Martin Gatton Business and Economics Building'}, 'MH': { number: '0035', title: 'Miller Hall'}, 'AQ': { number: '0037', title: 'Anderson Hall Quadrangle'}, 'ML': { number: '0038', title: 'Mining Laboratory'}, 'KL': { number: '0039', title: 'Margaret I. King Library'}, 'PEN': { number: '0041', title: 'Pence Hall'}, 'EGJ': { number: '0042', title: 'Enoch Grehan Journalism Building'}, 'TRB': { number: '0043', title: 'S. J. "Sam" Whalen Building'}, 'KAS': { number: '0044', title: 'Kastle Hall'}, 'MCV': { number: '0045', title: 'McVey Hall'}, 'FPAT':{ number: '0046', title: 'F. Paul Anderson Tower'}, 'MAT': { number: '0047', title: 'Mathews Building'}, 'LAW': { number: '0048', title: 'Law Building'}, 'MEH': { number: '0049', title: 'Memorial Hall'}, 'EH': { number: '0050', title: 'Erikson Hall'}, 'MIIN':{ number: '0051', title: 'Mineral Industries Building'}, 'DVT': { number: '0052', title: 'Terrell Civil Engineering Building'}, 'SRB': { number: '0053', title: 'Slone Research Building'}, 'FB': { number: '0054', title: 'Funkhouser Building'}, 'CP': { number: '0055', title: 'Chemistry-Physics Building'}, 'BREC':{ number: '0056', title: 'Breckinridge Hall'}, 'KH': { number: '0057', title: 'Kinkead Hall'}, 'BRAD':{ number: '0058', title: 'Bradley Hall'}, 'BOW': { number: '0059', title: 'Bowman Hall'}, 'WASH':{ number: '0060', title: 'Nursery'}, 'AES': { number: '0064', title: 'Agricultural Experiment Station'}, 'WGRL':{ number: '0070', title: 'Wenner-Gren Research Laboratory'}, 'DON': { number: '0072', title: 'Donovan Hall'}, 'TPC': { number: '0073', title: 'Thomas Poe Cooper Building'}, 'AP': { number: '0076', title: 'Dimock Animal Pathology Building'}, 'MDS': { number: '0082', title: 'Multidisciplinary Science Building'}, 'MDC': { number: '0084', title: 'Medical Center'}, 'COMB':{ number: '0086', title: 'College of Medicine Office Building'}, 'AGN': { number: '0091', title: 'Agricultural Science Center North'}, 'RPCA':{ number: '0093', title: 'Roach Patient Care Building'}, 'CH': { number: '0094', title: 'Cooper House'}, 'CCRC':{ number: '0096', title: 'Dorothy Enslow Combs Cancer Research Facility'}, 'ESGB':{ number: '0097', title: 'E. S. Good Barn'}, 'MRIS':{ number: '0098', title: 'Davis-Mills MRI and Spectroscopy Center'}, 'GERC':{ number: '0099', title: 'Gluck Equine Research Center'}, 'MMRB':{ number: '0107', title: 'Mining and Mineral Research Building'}, 'RMB': { number: '0108', title: 'Center for Robotics and Manufacturing Systems'}, 'HAHL':{ number: '0111', title: 'Haggin Hall'}, 'SPC': { number: '0113', title: 'Shively Sports Center'}, 'ALH': { number: '0119', title: 'Helen King Alumni Building'}, 'CC': { number: '0147', title: 'Complex Commons Building'}, 'JSB': { number: '0174', title: 'Jacobs Science Building'}, 'CTW': { number: '0200', title: 'Charles T. Wethington, Jr. Building'}, 'MAB': { number: '0207', title: 'Metal Arts Building'}, 'LAC': { number: '0212', title: 'Lancaster Aquatic Center'}, 'GARR':{ number: '0215', title: 'Garrigus Building'}, 'SB': { number: '0219', title: 'Seaton Center'}, 'LCLI':{ number: '0224', title: 'Lucille C. Little Fine Arts Library'}, 'BS': { number: '0225', title: 'Thomas Hunt Morgan Biological Sciences Building'}, 'ADC': { number: '0229', title: 'Agriculture Distribution Center'}, 'SBCA':{ number: '0230', title: 'Sanders-Brown Center on Aging'}, 'CN': { number: '0232', title: 'College of Nursing Building'}, 'OB': { number: '0235', title: 'John W Oswald Building'}, 'SCFA':{ number: '0241', title: 'Singletary Center for the Arts'}, 'MB': { number: '0274', title: 'Moloney Building'}, 'CEBA':{ number: '0276', title: 'Charles E. Barnhart Building'}, 'NFTF':{ number: '0277', title: 'Nutter Football Training Facility'}, 'OHR': { number: '0281', title: 'Oliver H. Raymond Civil Engineering Building'}, 'ASTC':{ number: '0286', title: 'ASTeCC Building'}, 'UH': { number: '0293', title: 'Kentucky Children\'s Hospital'}, 'DSC': { number: '0297', title: 'Dental Science Building'}, 'MN': { number: '0298', title: 'William R. Willard Medical Education Building'}, 'HSRE':{ number: '0305', title: 'Peter P. Bosomworth Health Sciences Research Building'}, 'BDH': { number: '0343', title: 'Bingham-Davis House'}, 'GCH2':{ number: '0344', title: 'Raymond F. Betts House'}, 'MKH': { number: '0345', title: 'Max Kade House and Cultural Center'}, 'MAHO':{ number: '0346', title: 'Math House'}, 'MWC': { number: '0350', title: 'Center on Drug and Alcohol Research'}, 'GCH1':{ number: '0432', title: 'Gaines Center for the Humanities'}, 'WTYL':{ number: '0456', title: 'W. T. Young Library'}, 'AT': { number: '0481', title: 'Academic Technical Building'}, 'JWST':{ number: '0494', title: 'James W. Stuckert Career Center'}, 'RGAN':{ number: '0503', title: 'Ralph G. Anderson Building'}, 'SMHA':{ number: '0565', title: 'John T. Smith Residence Hall'}, 'BAHA':{ number: '0566', title: 'Dale E. Baldwin Residence Hall'}, 'INHA':{ number: '0567', title: 'Margaret Ingels Residence Hall'}, 'UHS': { number: '0582', title: 'University Health Service Building'}, 'BPC': { number: '0596', title: 'Biological-Pharmaceutical Building'}, 'VAMC':{ number: '2142', title: 'Veterans Affairs Medical Center'}, 'CHH': { number: '3118', title: 'Carnahan House'}, 'VDL': { number: '3186', title: 'Veterinary Diagnostic Laboratory'}, 'SPIN':{ number: '3358', title: 'Spindletop Hall'} }; function Room( room ) { "use strict"; var buildingInfo; if( typeof room == 'function' ) return room(); if( room.HTML && ( room.orig === undefined ) ) return room; if( room instanceof Room ) room = room.toString(); buildingInfo = (room===undefined)?undefined:Buildings[ room.match(/^([A-Za-z]*)(?:[\s-]*[A-Za-z0-9]*)?/)[1] ]; this.HTML = (buildingInfo === undefined)?room:info.mustaches.room( { buildingNumber: buildingInfo.number, orig: room } ); this.toJSON = this.toString = function() { return room; }; } var rooms = { // TA offices "POT 702": { phone: "(859) 257-6804" }, "POT 706": { phone: "(859) 257-6805" }, "POT 718": { phone: "(859) 257-6806" }, "POT 722": { phone: "(859) 257-6807" }, "POT 802": { phone: "(859) 257-6816" }, "POT 806": { phone: "(859) 257-6817" }, "POT 902": { phone: "(859) 257-7216" }, "POT 906": { phone: "(859) 257-7217" }, "MAHO": { phone: "(859) 257-2461" }, // PTI Offices "POT 705": { phone: "(859) 257-6821" }, "POT 725": { phone: "(859) 257-2354" }, "POT 805": { phone: "(859) 257-4874" }, "POT 829": { phone: "(859) 257-6812" }, }; function Email( email ) { "use strict"; this.HTML = info.mustaches.email( { address: email } ); this.toJSON = this.toString = function() { return email; }; } /***************************************************************************** * end room */ function makeNavbar() { "use strict"; var i,o,cur,lev, links, menu, ids; if( document.getElementById("navbar") ) return; cur = []; o = document.querySelectorAll("h1, h2, h3, h4, h5, h6"); links = ["