diff --git a/scripts/scheduleInput.js b/scripts/scheduleInput.js --- a/scripts/scheduleInput.js +++ b/scripts/scheduleInput.js @@ -22,8 +22,38 @@ //-------------------------------------------------- var classNum = 0; + +/** + * \brief + * The number of section entries for a given course. + * + * Key is course_i, value is the current number of sections. + */ var sectionsOfClass = new Array(); +/** + * \brief + * Help to generate a unique section identifier for each section + * added to a given course. + * + * Necessary to support PHP-style post array thingies, like + * classes[0][1][$x] would be all of the data for course_i=0, + * section_i=1, variable $x (ex. day of week, start time, end time, + * teacher). We can't have two sections for a given course using the + * same section_i because those values would override eachother. + */ +var last_section_i = 0; + +/* + * \brief + * The course number which contains nothing. + * + * To avoid having a user need to click the ``Add course'' button, we + * keep a course added at the end of the list of courses. If this + * variable is -1, it indicates that no such free course exists. If it + * is zero or greater, that number is the class which is the free one. + */ +var slate_permutate_course_free = -1; //-------------------------------------------------- // Validation Functions @@ -94,7 +124,7 @@ jQuery.validator.addMethod('classRequire * to delete the class because of how * our numbering works. */ - if (!sectionsOfClass[cnum]) + if (!course_has_sections(cnum)) return true; return false; @@ -129,7 +159,7 @@ function genSectionHtml(cnum) /* @TODO: This should select & set items based on args, if the args != '' */ function genSectionHtml_n(cnum, name, synonym, stime, etime, days, prof, location, type) { - var snum = sectionsOfClass[cnum]; + var snum = last_section_i ++; var cssclasses = 'section class' + cnum; if(type == 'lab') { @@ -249,6 +279,9 @@ function add_section_n(cnum, name, synon jQuery('.pclass'+cnum).after(genSectionHtml_n(cnum, name, synonym, stime, etime, days, prof, location, type)); sectionsOfClass[cnum] ++; + /* store course_i in a place the newly added section will look for it */ + jQuery('.pclass' + cnum).next().data({course_i: cnum}); + /* unhide the saturday columns if it's used by autocomplete data */ if (days.s) jQuery('#jsrows col.saturday').removeClass('collapsed'); @@ -293,8 +326,15 @@ function add_sections(cnum, data) //-------------------------------------------------- function add_class_n(name) { + /* + * If we're adding a course entry form with preadded + * content, first remove the empty course. + */ + if (name.length && slate_permutate_course_free != -1) + course_remove(slate_permutate_course_free); + sectionsOfClass[classNum] = 0; // Initialize at 0 - jQuery('#jsrows').append('
'); + jQuery('#jsrows').append('
'); /* store classNum as course_i into the : */ jQuery('#tr-course-' + classNum).data({course_i: classNum}); @@ -350,11 +390,97 @@ function add_sections(cnum, data) return (classNum - 1); } + +/** + * \brief + * Ensure that there is an empty course entry and return its + * identifier. + */ function add_class() { - return add_class_n(''); + /* + * Don't add an empty new course entry if there already is + * one. Otherwise, set this new class to be the ``hot'' one. + */ + if (slate_permutate_course_free == -1) + slate_permutate_course_free = add_class_n(''); + return slate_permutate_course_free; +} + +/** + * \brief + * Remove a course entry. + * + * Ensures that slate_permutate_course_free is kept consistent. + * + * \param course_i + * The internal JS identifer for the course (not the course_id which + * the PHP cares about). + */ +function course_remove(course_i) +{ + jQuery('.class' + course_i).remove(); + + /* + * Check if the class intended for the user to + * enter information into has been removed. + */ + if (slate_permutate_course_free == course_i) + slate_permutate_course_free = -1; } +/** + * \brief + * Figure whether or not a given course entry has sections. + * + * \param course_i + * The internal javascript representation of a course entry. + * \return + * true or false. + */ +function course_has_sections(course_i) +{ + return sectionsOfClass[course_i] > 0; +} + +/** + * \brief + * Figure out whether or not an empty course entry has become filled + * or whether a full course has become emptied and react. + * + * This mainly ensures that there is always exactly one course entry + * spot, eliminating the need of an ``Add class'' button. + * + * \param that + * If this is not being called as a 'change' or 'keyup' event + * handler for a , then that may refer to + * a jQuery object representing the to + * inspect. + */ +function course_free_check(that) +{ + var me; + if (jQuery.type(that) == 'undefined') + me = that; + else + me = jQuery(this); + + var course_i = me.parent().parent().data('course_i'); + if (course_i == slate_permutate_course_free && (me.val().length || course_has_sections(course_i))) + { + /* I am no longer the empty course entry */ + slate_permutate_course_free = -1; + add_class(); + } + if (course_i != slate_permutate_course_free && !(me.val().length || course_has_sections(course_i))) + { + /* I am now an empty course entry */ + /* kill an other empty course entry if it exists... */ + if (slate_permutate_course_free != -1) + course_remove(slate_permutate_course_free); + slate_permutate_course_free = course_i; + } +} /** * \brief @@ -415,7 +541,7 @@ jQuery(document).ready(function() { //-------------------------------------------------- jQuery('.deleteClass').live('click', function() { if(confirm('Delete class and all sections of this class?')) { - jQuery('.class' + jQuery(this).parent().parent().data('course_i')).remove(); + course_remove(jQuery(this).parent().parent().data('course_i')); } }); @@ -424,8 +550,10 @@ jQuery(document).ready(function() { //-------------------------------------------------- jQuery('.deleteSection').live('click', function() { // Decreases the total number of classes - sectionsOfClass[jQuery(this).parent().parent().data('course_i')]--; - + var course_i = jQuery(this).parent().parent().data('course_i'); + sectionsOfClass[course_i]--; + course_free_check(jQuery('.pclass' + course_i + ' .className')); + // Find the ID cell of the row we're in var row = jQuery(this).parent().parent().find(".sectionIdentifier"); @@ -442,15 +570,16 @@ jQuery(document).ready(function() { jQuery(this).remove(); } }); + }); - }); + jQuery('.className').live('change', course_free_check).live('keyup', course_free_check); //-------------------------------------------------- // Bind the section-adding method //-------------------------------------------------- jQuery('.addSection').live('click', function() { var course_i = jQuery(this).parent().parent().data('course_i'); - add_section(course_i, sectionsOfClass[course_i]); + add_section(course_i); }); //--------------------------------------------------