From 8df8b18fc03ec14c6934f8cfd3ca5208e6154cfd Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Fri, 31 Oct 2014 19:59:55 -0400 Subject: [PATCH 01/12] =?UTF-8?q?Can=20delete=20jobs=20from=20r=C3=A9sum?= =?UTF-8?q?=C3=A9=20show=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add form to job partial for sending delete request - New utility CSS class for floating right --- README.md | 2 +- linkedout.rb | 11 +++++++++++ public/css/main.css | 5 +++++ views/partials/job.erb | 5 +++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ccdf2bd..ebbb5a7 100644 --- a/README.md +++ b/README.md @@ -97,7 +97,7 @@ This is the first release with JavaScript and jQuery included. As a reference, h ### v[1.2.0] Asynchronously edit and delete jobs - [ ] User can edit jobs on the résumé show page -- [ ] User can delete jobs on the résumé show page +- [X] User can delete jobs on the résumé show page - [ ] Editing and deleting jobs occurs asynchronously - [ ] Edited jobs are updated on the page without refresh - [ ] Deleted jobs are removed from the page without refresh diff --git a/linkedout.rb b/linkedout.rb index b00e531..1162db9 100644 --- a/linkedout.rb +++ b/linkedout.rb @@ -65,6 +65,17 @@ def default_user redirect "/" end +delete "/jobs" do + job_attrs = params[:job] + + job_id = job_attrs.delete("id") + + job = Job.get(job_id) + job.destroy + + redirect "/" +end + post "/skills" do skill_attrs = params[:skill] skill_attrs.merge!({ :user => default_user }) diff --git a/public/css/main.css b/public/css/main.css index f57fce3..e11c8ab 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -108,6 +108,11 @@ form.mini input[type="submit"] { float: right; } padding: 0; } +.float_right { + float: right; + padding-left: 1em; +} + /* * SECTION STYLING diff --git a/views/partials/job.erb b/views/partials/job.erb index 0db8394..b57e187 100644 --- a/views/partials/job.erb +++ b/views/partials/job.erb @@ -1,4 +1,9 @@
  • +
    + + + +

    <%= job.job_title %> at <%= job.company_name %>

    <%= job.job_description %>

  • From a5fe5e08ca6ed5a650f49d3b11a057fbf60f9445 Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Fri, 31 Oct 2014 20:16:31 -0400 Subject: [PATCH 02/12] Asynchronously delete jobs - Clicking delete will send AJAX DELETE request to /jobs - Show completed requirements on README --- README.md | 5 +++-- linkedout.rb | 6 +++++- public/js/main.js | 26 +++++++++++++++++++++++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ebbb5a7..22bdd6e 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,10 @@ This is the first release with JavaScript and jQuery included. As a reference, h - [ ] User can edit jobs on the résumé show page - [X] User can delete jobs on the résumé show page -- [ ] Editing and deleting jobs occurs asynchronously +- [ ] Editing jobs occurs asynchronously +- [X] Deleting jobs occurs asynchronously - [ ] Edited jobs are updated on the page without refresh -- [ ] Deleted jobs are removed from the page without refresh +- [X] Deleted jobs are removed from the page without refresh ### v[1.4.0] Asynchronously edit and delete skills diff --git a/linkedout.rb b/linkedout.rb index 1162db9..0dc7899 100644 --- a/linkedout.rb +++ b/linkedout.rb @@ -73,7 +73,11 @@ def default_user job = Job.get(job_id) job.destroy - redirect "/" + if request.xhr? + job_id + else + redirect "/" + end end post "/skills" do diff --git a/public/js/main.js b/public/js/main.js index 7392d33..004437b 100644 --- a/public/js/main.js +++ b/public/js/main.js @@ -47,7 +47,6 @@ var insertNewSkillIntoDOM = function(newSkillHTML) { $newSkillForm.get(0).reset(); }; - var createNewJobsOnSubmit = function() { var $newJobForm = getNewJobForm(); @@ -72,10 +71,35 @@ var insertNewJobIntoDOM = function(newJobHTML) { $newJobForm.get(0).reset(); }; +var deleteJobOnSubmit = function() { + var $deleteJobForm = $('form[name="delete_job"]'); + + $deleteJobForm.submit(function (evt) { + evt.preventDefault(); + + var jobFormData = $(this).serialize(); + + // Grab the parent
  • element so that we can remove + // it when the delete request completes + var $parentLiElement = $(this).parent('li'); + + // Sending a DELETE request requires using the jQuery + // .ajax() function and configuring the url, type, + // data, and complete options + $.ajax({ + url: '/jobs', + type: 'DELETE', + data: jobFormData, + complete: function() { $parentLiElement.remove(); } + }); + }); +}; + // Wait to execute all code until the document is ready // (i.e. all of the DOM nodes have been loaded) $(document).ready(function() { createNewSkillsOnSubmit(); createNewJobsOnSubmit(); + deleteJobOnSubmit(); }); From c9c3821c569de3cf1ea7e7bece7ad61c08eb646a Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Fri, 31 Oct 2014 20:19:34 -0400 Subject: [PATCH 03/12] Separate JS into two files: jobs.js and skills.js That main.js file was getting much too large. Time to split it into smaller scripts that manage jobs and skills, respectively. --- public/js/jobs.js | 52 ++++++++++++++++++++++++++++++++ public/js/{main.js => skills.js} | 51 ------------------------------- views/layout.erb | 3 +- 3 files changed, 54 insertions(+), 52 deletions(-) create mode 100644 public/js/jobs.js rename public/js/{main.js => skills.js} (61%) diff --git a/public/js/jobs.js b/public/js/jobs.js new file mode 100644 index 0000000..e7ec4dc --- /dev/null +++ b/public/js/jobs.js @@ -0,0 +1,52 @@ +var createNewJobsOnSubmit = function() { + var $newJobForm = getNewJobForm(); + + $newJobForm.submit(function (evt) { + evt.preventDefault(); + + var jobFormData = $(this).serialize(); + + $.post("/jobs", jobFormData, insertNewJobIntoDOM); + }); +}; + +var getNewJobForm = function() { + return $('form[name="new_job"]'); +}; + +var insertNewJobIntoDOM = function(newJobHTML) { + var $newJobForm = getNewJobForm(); + + $newJobForm.parent('li').before(newJobHTML); + + $newJobForm.get(0).reset(); +}; + +var deleteJobOnSubmit = function() { + var $deleteJobForm = $('form[name="delete_job"]'); + + $deleteJobForm.submit(function (evt) { + evt.preventDefault(); + + var jobFormData = $(this).serialize(); + + // Grab the parent
  • element so that we can remove + // it when the delete request completes + var $parentLiElement = $(this).parent('li'); + + // Sending a DELETE request requires using the jQuery + // .ajax() function and configuring the url, type, + // data, and complete options + $.ajax({ + url: '/jobs', + type: 'DELETE', + data: jobFormData, + complete: function() { $parentLiElement.remove(); } + }); + }); +}; + +$(document).ready(function() { + createNewJobsOnSubmit(); + deleteJobOnSubmit(); +}); diff --git a/public/js/main.js b/public/js/skills.js similarity index 61% rename from public/js/main.js rename to public/js/skills.js index 004437b..e388e05 100644 --- a/public/js/main.js +++ b/public/js/skills.js @@ -47,59 +47,8 @@ var insertNewSkillIntoDOM = function(newSkillHTML) { $newSkillForm.get(0).reset(); }; -var createNewJobsOnSubmit = function() { - var $newJobForm = getNewJobForm(); - - $newJobForm.submit(function (evt) { - evt.preventDefault(); - - var jobFormData = $(this).serialize(); - - $.post("/jobs", jobFormData, insertNewJobIntoDOM); - }); -}; - -var getNewJobForm = function() { - return $('form[name="new_job"]'); -}; - -var insertNewJobIntoDOM = function(newJobHTML) { - var $newJobForm = getNewJobForm(); - - $newJobForm.parent('li').before(newJobHTML); - - $newJobForm.get(0).reset(); -}; - -var deleteJobOnSubmit = function() { - var $deleteJobForm = $('form[name="delete_job"]'); - - $deleteJobForm.submit(function (evt) { - evt.preventDefault(); - - var jobFormData = $(this).serialize(); - - // Grab the parent
  • element so that we can remove - // it when the delete request completes - var $parentLiElement = $(this).parent('li'); - - // Sending a DELETE request requires using the jQuery - // .ajax() function and configuring the url, type, - // data, and complete options - $.ajax({ - url: '/jobs', - type: 'DELETE', - data: jobFormData, - complete: function() { $parentLiElement.remove(); } - }); - }); -}; - - // Wait to execute all code until the document is ready // (i.e. all of the DOM nodes have been loaded) $(document).ready(function() { createNewSkillsOnSubmit(); - createNewJobsOnSubmit(); - deleteJobOnSubmit(); }); diff --git a/views/layout.erb b/views/layout.erb index 45dff07..4b24587 100644 --- a/views/layout.erb +++ b/views/layout.erb @@ -21,6 +21,7 @@ - + + From 763edbd33ce462e21a1154d22e0b4c82254bfa8f Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Fri, 31 Oct 2014 20:53:26 -0400 Subject: [PATCH 04/12] =?UTF-8?q?Edit=20button=20shows=20job=20edit=20form?= =?UTF-8?q?=20on=20r=C3=A9sum=C3=A9=20show=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When a user clicks the "edit" button next to a job, an edit form will show up to allow them to edit the job information. This is accomplished by rendering the edit forms in the page but ensuring that they are hidden by default. This way, the JS linked to the edit button just hides the job information and shows the form. Currently not asynchronous. --- README.md | 2 +- public/css/main.css | 5 +++++ public/js/jobs.js | 15 +++++++++++++++ views/partials/job.erb | 1 + views/partials/job_edit.erb | 10 ++++------ views/resumes/edit.erb | 4 +++- views/resumes/show.erb | 5 ++++- 7 files changed, 33 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 22bdd6e..0c8bbd5 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ This is the first release with JavaScript and jQuery included. As a reference, h ### v[1.2.0] Asynchronously edit and delete jobs -- [ ] User can edit jobs on the résumé show page +- [X] User can edit jobs on the résumé show page - [X] User can delete jobs on the résumé show page - [ ] Editing jobs occurs asynchronously - [X] Deleting jobs occurs asynchronously diff --git a/public/css/main.css b/public/css/main.css index e11c8ab..3513f39 100644 --- a/public/css/main.css +++ b/public/css/main.css @@ -113,6 +113,11 @@ form.mini input[type="submit"] { float: right; } padding-left: 1em; } +.hidden { + display: none; + visibility: hidden; +} + /* * SECTION STYLING diff --git a/public/js/jobs.js b/public/js/jobs.js index e7ec4dc..8e23209 100644 --- a/public/js/jobs.js +++ b/public/js/jobs.js @@ -22,6 +22,18 @@ var insertNewJobIntoDOM = function(newJobHTML) { $newJobForm.get(0).reset(); }; +var showJobEditFormOnClick = function() { + $('.js_edit_job').click(function(evt) { + evt.preventDefault(); + + var $jobListItem = $(this).parent('li'); + var $jobEditForm = $jobListItem.next('li'); + + $jobListItem.addClass('hidden'); + $jobEditForm.removeClass('hidden'); + }); +}; + var deleteJobOnSubmit = function() { var $deleteJobForm = $('form[name="delete_job"]'); @@ -48,5 +60,8 @@ var deleteJobOnSubmit = function() { $(document).ready(function() { createNewJobsOnSubmit(); + + showJobEditFormOnClick(); + deleteJobOnSubmit(); }); diff --git a/views/partials/job.erb b/views/partials/job.erb index b57e187..eb21ca8 100644 --- a/views/partials/job.erb +++ b/views/partials/job.erb @@ -4,6 +4,7 @@ + Edit

    <%= job.job_title %> at <%= job.company_name %>

    <%= job.job_description %>

  • diff --git a/views/partials/job_edit.erb b/views/partials/job_edit.erb index 57bb66a..f1412b2 100644 --- a/views/partials/job_edit.erb +++ b/views/partials/job_edit.erb @@ -1,10 +1,8 @@ -<% - # When rendering a partial, the collection item takes the name - # of the file for the item, so the job object is assigned to - # the local variable `job_form` - job = job_edit -%> +<% if hidden %> +
  • +<% end %>
    diff --git a/views/resumes/edit.erb b/views/resumes/edit.erb index 83b0c37..4590b2a 100644 --- a/views/resumes/edit.erb +++ b/views/resumes/edit.erb @@ -10,7 +10,9 @@

    Jobs

      - <%= partial :'partials/job_edit', collection: @jobs %> + <% @jobs.each do |job| %> + <%= partial :'partials/job_edit', :locals => { :job => job, :hidden => false } %> + <% end %>
    diff --git a/views/resumes/show.erb b/views/resumes/show.erb index e98509a..909c824 100644 --- a/views/resumes/show.erb +++ b/views/resumes/show.erb @@ -10,7 +10,10 @@

    Jobs

      - <%= partial :'partials/job', collection: @jobs %> + <% @jobs.each do |job| %> + <%= partial :'partials/job', :locals => { :job => job } %> + <%= partial :'partials/job_edit', :locals => { :job => job, :hidden => true } %> + <% end %> <%= partial :'partials/job_new' %>
    From d548b480fa1ee6f8e6065ef3a101e3efa999178c Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Sat, 1 Nov 2014 13:48:50 -0400 Subject: [PATCH 05/12] =?UTF-8?q?Asynchronous=20updates=20on=20jobs=20from?= =?UTF-8?q?=20r=C3=A9sum=C3=A9=20show=20page?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Editing jobs now sends an AJAX request and will update the DOM with the updated job data - Modified the event listener on the "edit" button to use [event delegation](http://learn.jquery.com/events/event-delegation/) so that it will still function on elements added after the initial page load - Server route /jobs/edit responds to async requests with the job partial HTML --- linkedout.rb | 6 +++++- public/js/jobs.js | 37 ++++++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 2 deletions(-) diff --git a/linkedout.rb b/linkedout.rb index 0dc7899..c01894c 100644 --- a/linkedout.rb +++ b/linkedout.rb @@ -62,7 +62,11 @@ def default_user job = Job.get(job_id) job.update(job_attrs) - redirect "/" + if request.xhr? + partial :'partials/job', :locals => { :job => job } + else + redirect "/" + end end delete "/jobs" do diff --git a/public/js/jobs.js b/public/js/jobs.js index 8e23209..2060ccb 100644 --- a/public/js/jobs.js +++ b/public/js/jobs.js @@ -23,7 +23,7 @@ var insertNewJobIntoDOM = function(newJobHTML) { }; var showJobEditFormOnClick = function() { - $('.js_edit_job').click(function(evt) { + $('.jobs').on('click', '.js_edit_job', function(evt) { evt.preventDefault(); var $jobListItem = $(this).parent('li'); @@ -34,6 +34,40 @@ var showJobEditFormOnClick = function() { }); }; +var updateJobOnSubmit = function() { + var $editJobForm = $('form[name="edit_job"]'); + + $editJobForm.submit(function(evt) { + evt.preventDefault(); + + var jobFormData = $(this).serialize(); + + var $jobEditForm = $(this).parent('li'); + // The job item to update is the previous
  • element + // before the current
  • containing the form + var $jobListItem = $jobEditForm.prev('li'); + + // Send async PUT request to /jobs/edit + $.ajax({ + url: '/jobs/edit', + type: 'PUT', + data: jobFormData + }).done(function(responseData) { + // This function will execute when the response comes + // back from the server + // + // We expect to receive the updated job HTML + // (as a
  • element with job info inside) + var newJobHTML = responseData; + + $jobListItem.removeClass('hidden'); + $jobEditForm.addClass('hidden'); + + $jobListItem.replaceWith(newJobHTML); + }); + }); +}; + var deleteJobOnSubmit = function() { var $deleteJobForm = $('form[name="delete_job"]'); @@ -62,6 +96,7 @@ $(document).ready(function() { createNewJobsOnSubmit(); showJobEditFormOnClick(); + updateJobOnSubmit(); deleteJobOnSubmit(); }); From 80a189b5342b28a45b445898a363481e20543585 Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Sat, 1 Nov 2014 14:12:27 -0400 Subject: [PATCH 06/12] Alter HTML structure of job listings Makes more sense for the job info and the edit form to both be inside the same
  • tag, since they will never be displayed at the same time and thus act like a single list item. This also makes it easier to associate the form with its corresponding job info element from the JavaScript. --- public/js/jobs.js | 20 ++++++++++---------- views/partials/job.erb | 4 ++-- views/partials/job_edit.erb | 26 ++++++++++++-------------- views/partials/job_new.erb | 20 +++++++++----------- views/resumes/edit.erb | 4 +++- views/resumes/show.erb | 10 +++++++--- 6 files changed, 43 insertions(+), 41 deletions(-) diff --git a/public/js/jobs.js b/public/js/jobs.js index 2060ccb..51b8e1e 100644 --- a/public/js/jobs.js +++ b/public/js/jobs.js @@ -26,10 +26,10 @@ var showJobEditFormOnClick = function() { $('.jobs').on('click', '.js_edit_job', function(evt) { evt.preventDefault(); - var $jobListItem = $(this).parent('li'); - var $jobEditForm = $jobListItem.next('li'); + var $jobElem = $(this).parent('.job'); + var $jobEditForm = $jobElem.siblings('form[name="edit_job"]'); - $jobListItem.addClass('hidden'); + $jobElem.addClass('hidden'); $jobEditForm.removeClass('hidden'); }); }; @@ -42,10 +42,10 @@ var updateJobOnSubmit = function() { var jobFormData = $(this).serialize(); - var $jobEditForm = $(this).parent('li'); - // The job item to update is the previous
  • element - // before the current
  • containing the form - var $jobListItem = $jobEditForm.prev('li'); + var $jobEditForm = $(this); + // The job item to update is the the element of class + // 'job' in the same containing element (in this case,
  • ) + var $jobListItem = $jobEditForm.siblings('.job'); // Send async PUT request to /jobs/edit $.ajax({ @@ -57,7 +57,7 @@ var updateJobOnSubmit = function() { // back from the server // // We expect to receive the updated job HTML - // (as a
  • element with job info inside) + // (as a
    element with job info inside) var newJobHTML = responseData; $jobListItem.removeClass('hidden'); @@ -76,9 +76,9 @@ var deleteJobOnSubmit = function() { var jobFormData = $(this).serialize(); - // Grab the parent
  • element so that we can remove + // Grab the containing
  • element so that we can remove // it when the delete request completes - var $parentLiElement = $(this).parent('li'); + var $parentLiElement = $(this).closest('li'); // Sending a DELETE request requires using the jQuery // .ajax() function and configuring the url, type, diff --git a/views/partials/job.erb b/views/partials/job.erb index eb21ca8..8e2ecd4 100644 --- a/views/partials/job.erb +++ b/views/partials/job.erb @@ -1,4 +1,4 @@ -
  • +
    @@ -7,4 +7,4 @@ Edit

    <%= job.job_title %> at <%= job.company_name %>

    <%= job.job_description %>

    -
  • + diff --git a/views/partials/job_edit.erb b/views/partials/job_edit.erb index f1412b2..9b2ecd4 100644 --- a/views/partials/job_edit.erb +++ b/views/partials/job_edit.erb @@ -1,21 +1,19 @@ <% if hidden %> -
  • + <% end %> - - + - + - at - -
    + at + +
    -
    - -
    +
    + +
    - -
  • -
  • + + diff --git a/views/partials/job_new.erb b/views/partials/job_new.erb index 8d9a6a9..db2e235 100644 --- a/views/partials/job_new.erb +++ b/views/partials/job_new.erb @@ -1,13 +1,11 @@ -
  • -
    - at - -
    + + at + +
    -
    - -
    +
    + +
    - -
    -
  • + + diff --git a/views/resumes/edit.erb b/views/resumes/edit.erb index 4590b2a..d94594c 100644 --- a/views/resumes/edit.erb +++ b/views/resumes/edit.erb @@ -11,7 +11,9 @@

    Jobs

    diff --git a/views/resumes/show.erb b/views/resumes/show.erb index 909c824..7daf827 100644 --- a/views/resumes/show.erb +++ b/views/resumes/show.erb @@ -11,11 +11,15 @@

    Jobs

    From 038e91507c1d527e6794f3bc137f1e4c5a2861c6 Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Sat, 1 Nov 2014 14:17:20 -0400 Subject: [PATCH 07/12] Use event delegation for all job form event listeners Because the page is updating so frequently, it is better to use delegation to ensure that events on newly created elements will trigger the appropriate functions. --- public/js/jobs.js | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/public/js/jobs.js b/public/js/jobs.js index 51b8e1e..bec3ea0 100644 --- a/public/js/jobs.js +++ b/public/js/jobs.js @@ -1,7 +1,5 @@ var createNewJobsOnSubmit = function() { - var $newJobForm = getNewJobForm(); - - $newJobForm.submit(function (evt) { + $('.jobs').on('submit', 'form[name="new_job"]',function(evt) { evt.preventDefault(); var jobFormData = $(this).serialize(); @@ -35,9 +33,7 @@ var showJobEditFormOnClick = function() { }; var updateJobOnSubmit = function() { - var $editJobForm = $('form[name="edit_job"]'); - - $editJobForm.submit(function(evt) { + $('.jobs').on('submit', 'form[name="edit_job"]', function(evt) { evt.preventDefault(); var jobFormData = $(this).serialize(); @@ -69,9 +65,7 @@ var updateJobOnSubmit = function() { }; var deleteJobOnSubmit = function() { - var $deleteJobForm = $('form[name="delete_job"]'); - - $deleteJobForm.submit(function (evt) { + $('.jobs').on('submit', 'form[name="delete_job"]', function(evt) { evt.preventDefault(); var jobFormData = $(this).serialize(); From 24315984e09f2d73252367b89b13e0e718311738 Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Sat, 1 Nov 2014 14:27:22 -0400 Subject: [PATCH 08/12] Fix bug in create job response Wasn't returning the edit job form along with the job itself, so newly created jobs weren't able to be edited. --- linkedout.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/linkedout.rb b/linkedout.rb index c01894c..83027ab 100644 --- a/linkedout.rb +++ b/linkedout.rb @@ -48,7 +48,11 @@ def default_user job.save if request.xhr? - partial :'partials/job', :locals => { :job => job } + html = "
  • " + html += partial :'partials/job', :locals => { :job => job } + html += partial :'partials/job_edit', :locals => { :job => job, :hidden => true } + html += "
  • " + html else redirect "/" end From a333e26144322532b2febe03bef8bdaa004cff37 Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Sat, 1 Nov 2014 14:37:33 -0400 Subject: [PATCH 09/12] Refactor jobs.js for consistency and clarity - Make naming more conventional - Remove smaller functions - Standardize format of functions --- public/js/jobs.js | 59 ++++++++++++++++++++++------------------------- 1 file changed, 27 insertions(+), 32 deletions(-) diff --git a/public/js/jobs.js b/public/js/jobs.js index bec3ea0..3a1331c 100644 --- a/public/js/jobs.js +++ b/public/js/jobs.js @@ -1,34 +1,27 @@ -var createNewJobsOnSubmit = function() { - $('.jobs').on('submit', 'form[name="new_job"]',function(evt) { +var createJobOnSubmit = function() { + $('.jobs').on('submit', 'form[name="new_job"]', function(evt) { evt.preventDefault(); - var jobFormData = $(this).serialize(); + var $newJobForm = $(this); + var newJobFormData = $(this).serialize(); - $.post("/jobs", jobFormData, insertNewJobIntoDOM); - }); -}; - -var getNewJobForm = function() { - return $('form[name="new_job"]'); -}; + $.post("/jobs", newJobFormData, function(jobHTML) { + $newJobForm.parent('li').before(jobHTML); -var insertNewJobIntoDOM = function(newJobHTML) { - var $newJobForm = getNewJobForm(); - - $newJobForm.parent('li').before(newJobHTML); - - $newJobForm.get(0).reset(); + $newJobForm.get(0).reset(); + }); + }); }; -var showJobEditFormOnClick = function() { +var showEditJobFormOnClick = function() { $('.jobs').on('click', '.js_edit_job', function(evt) { evt.preventDefault(); var $jobElem = $(this).parent('.job'); - var $jobEditForm = $jobElem.siblings('form[name="edit_job"]'); + var $editJobForm = $jobElem.siblings('form[name="edit_job"]'); $jobElem.addClass('hidden'); - $jobEditForm.removeClass('hidden'); + $editJobForm.removeClass('hidden'); }); }; @@ -36,18 +29,18 @@ var updateJobOnSubmit = function() { $('.jobs').on('submit', 'form[name="edit_job"]', function(evt) { evt.preventDefault(); - var jobFormData = $(this).serialize(); + var $editJobForm = $(this); + var editJobFormData = $editJobForm.serialize(); - var $jobEditForm = $(this); // The job item to update is the the element of class // 'job' in the same containing element (in this case,
  • ) - var $jobListItem = $jobEditForm.siblings('.job'); + var $jobElem = $editJobForm.siblings('.job'); // Send async PUT request to /jobs/edit $.ajax({ url: '/jobs/edit', type: 'PUT', - data: jobFormData + data: editJobFormData }).done(function(responseData) { // This function will execute when the response comes // back from the server @@ -56,10 +49,10 @@ var updateJobOnSubmit = function() { // (as a
    element with job info inside) var newJobHTML = responseData; - $jobListItem.removeClass('hidden'); - $jobEditForm.addClass('hidden'); + $jobElem.removeClass('hidden'); + $editJobForm.addClass('hidden'); - $jobListItem.replaceWith(newJobHTML); + $jobElem.replaceWith(newJobHTML); }); }); }; @@ -68,11 +61,12 @@ var deleteJobOnSubmit = function() { $('.jobs').on('submit', 'form[name="delete_job"]', function(evt) { evt.preventDefault(); - var jobFormData = $(this).serialize(); + var $deleteJobForm = $(this); + var deleteJobFormData = $deleteJobForm.serialize(); // Grab the containing
  • element so that we can remove // it when the delete request completes - var $parentLiElement = $(this).closest('li'); + var $jobContainerElem = $(this).closest('li'); // Sending a DELETE request requires using the jQuery // .ajax() function and configuring the url, type, @@ -80,16 +74,17 @@ var deleteJobOnSubmit = function() { $.ajax({ url: '/jobs', type: 'DELETE', - data: jobFormData, - complete: function() { $parentLiElement.remove(); } + data: deleteJobFormData + }).done(function() { + $jobContainerElem.remove(); }); }); }; $(document).ready(function() { - createNewJobsOnSubmit(); + createJobOnSubmit(); - showJobEditFormOnClick(); + showEditJobFormOnClick(); updateJobOnSubmit(); deleteJobOnSubmit(); From eada8f920805cb02ee17b87bcf7b3acabd4d3a57 Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Sat, 1 Nov 2014 14:39:48 -0400 Subject: [PATCH 10/12] Mark requirements as complete on release in README --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0c8bbd5..f0747d6 100644 --- a/README.md +++ b/README.md @@ -98,9 +98,9 @@ This is the first release with JavaScript and jQuery included. As a reference, h - [X] User can edit jobs on the résumé show page - [X] User can delete jobs on the résumé show page -- [ ] Editing jobs occurs asynchronously +- [X] Editing jobs occurs asynchronously - [X] Deleting jobs occurs asynchronously -- [ ] Edited jobs are updated on the page without refresh +- [X] Edited jobs are updated on the page without refresh - [X] Deleted jobs are removed from the page without refresh ### v[1.4.0] Asynchronously edit and delete skills From c0516c9b55457106a38243644d8996f6400a4ebb Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Sat, 1 Nov 2014 14:44:22 -0400 Subject: [PATCH 11/12] Update file list in README --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f0747d6..19bc05f 100644 --- a/README.md +++ b/README.md @@ -36,7 +36,8 @@ Once you have SQLite3 working, you can set up your development environment with │   │   ├── main.css # our custom CSS │   │   └── normalize.css # a commonly used CSS library to aid in cross-browser compatibility │   └── js # folder to hold JavaScript script files -│   └── main.js # our main JavaScript script file, all the JS stuff goes here +│   └── jobs.js # script to manage behavior relating to job resources +│   └── skills.js # script to manage behavior relating to skills resources └── views # a folder to hold the HTML templates for our pages ├── layout.erb # this is the main template for our site ├── partials # a folder containing a bunch of partials (not listed, because there are a bunch of them) From 6b47f9f088d8527b37c9f4f7a3d71d865314c8c4 Mon Sep 17 00:00:00 2001 From: Tanner Welsh Date: Sat, 1 Nov 2014 15:16:46 -0400 Subject: [PATCH 12/12] Add logging to jobs.js If you want to see what JavaScript is doing, simply open your browser console. As you click around to create, edit, and delete jobs, logging information will render to the JavaScript console. --- public/js/jobs.js | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/public/js/jobs.js b/public/js/jobs.js index 3a1331c..ed3ed93 100644 --- a/public/js/jobs.js +++ b/public/js/jobs.js @@ -1,11 +1,24 @@ +// A utility function to log information to the console +var log = function(message) { + var timestamp = (new Date()).toTimeString(); + console.log('[' + timestamp + '] ' + message); +}; + var createJobOnSubmit = function() { $('.jobs').on('submit', 'form[name="new_job"]', function(evt) { + log("New job form submitted"); + evt.preventDefault(); var $newJobForm = $(this); var newJobFormData = $(this).serialize(); + log("Sending POST request to /jobs"); + $.post("/jobs", newJobFormData, function(jobHTML) { + log("Received response from POST request to /jobs"); + + log("Adding new job element to list"); $newJobForm.parent('li').before(jobHTML); $newJobForm.get(0).reset(); @@ -15,11 +28,14 @@ var createJobOnSubmit = function() { var showEditJobFormOnClick = function() { $('.jobs').on('click', '.js_edit_job', function(evt) { + log("Show edit job form link clicked"); + evt.preventDefault(); var $jobElem = $(this).parent('.job'); var $editJobForm = $jobElem.siblings('form[name="edit_job"]'); + log("Hiding job element and showing job form"); $jobElem.addClass('hidden'); $editJobForm.removeClass('hidden'); }); @@ -27,6 +43,8 @@ var showEditJobFormOnClick = function() { var updateJobOnSubmit = function() { $('.jobs').on('submit', 'form[name="edit_job"]', function(evt) { + log("Edit job form submitted"); + evt.preventDefault(); var $editJobForm = $(this); @@ -36,12 +54,15 @@ var updateJobOnSubmit = function() { // 'job' in the same containing element (in this case,
  • ) var $jobElem = $editJobForm.siblings('.job'); + log("Sending PUT request to /jobs/edit"); + // Send async PUT request to /jobs/edit $.ajax({ url: '/jobs/edit', type: 'PUT', data: editJobFormData }).done(function(responseData) { + log("Received response from PUT request to /jobs/edit"); // This function will execute when the response comes // back from the server // @@ -49,9 +70,11 @@ var updateJobOnSubmit = function() { // (as a
    element with job info inside) var newJobHTML = responseData; + log("Hiding job form and showing job element"); $jobElem.removeClass('hidden'); $editJobForm.addClass('hidden'); + log("Replacing old job info with updated info"); $jobElem.replaceWith(newJobHTML); }); }); @@ -59,6 +82,8 @@ var updateJobOnSubmit = function() { var deleteJobOnSubmit = function() { $('.jobs').on('submit', 'form[name="delete_job"]', function(evt) { + log("Edit job form submitted"); + evt.preventDefault(); var $deleteJobForm = $(this); @@ -68,6 +93,8 @@ var deleteJobOnSubmit = function() { // it when the delete request completes var $jobContainerElem = $(this).closest('li'); + log("Sending DELETE request to /jobs"); + // Sending a DELETE request requires using the jQuery // .ajax() function and configuring the url, type, // data, and complete options @@ -76,6 +103,9 @@ var deleteJobOnSubmit = function() { type: 'DELETE', data: deleteJobFormData }).done(function() { + log("Received response from DELETE request to /jobs"); + + log("Removing deleted job element"); $jobContainerElem.remove(); }); });