Enable clicking a comment to jump to the inline context.
[gitorious:yousource.git] / public / javascripts / merge_requests.js
1 /*
2 #--
3 #   Copyright (C) 2007-2009 Johan Sørensen <johan@johansorensen.com>
4 #   Copyright (C) 2009 Marius Mathiesen <marius.mathiesen@gmail.com>
5 #
6 #   This program is free software: you can redistribute it and/or modify
7 #   it under the terms of the GNU Affero General Public License as published by
8 #   the Free Software Foundation, either version 3 of the License, or
9 #   (at your option) any later version.
10 #
11 #   This program is distributed in the hope that it will be useful,
12 #   but WITHOUT ANY WARRANTY; without even the implied warranty of
13 #   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 #   GNU Affero General Public License for more details.
15 #
16 #   You should have received a copy of the GNU Affero General Public License
17 #   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 #-- 
19 */
20 var diffBrowserCompactCommitSelectable;
21 $(document).ready(function() {
22     $("body#merge_requests", function(){
23         var spec = Gitorious.ShaSpec.parseLocationHash(document.location.hash);
24         if (spec) {
25           Gitorious.MergeRequestController.getInstance().loadFromBookmark(spec);
26         }
27     });
28
29     // toggling of diffs in diff browsers
30     $('.file-diff .header').live("click", function(event) {
31         var hunksContainer = $(this).next();
32         if (hunksContainer.is(":visible")) {
33           $(this).removeClass("open").addClass("closed");
34           hunksContainer.slideUp();
35         } else {
36           $(this).removeClass("closed").addClass("open");
37           hunksContainer.slideDown();
38         }
39         event.preventDefault();
40     });
41     $(".file-diff-controls a#expand-all").live("click", function(e){
42         var container = $(this).parent().parent().parent();
43         var cookiePrefix = $(this).attr("gts:cookie-prefix") || 'generic';
44         container.find('.file-diff .header').removeClass("closed").addClass("open");
45         container.find('.diff-hunks:hidden').show();
46         $.cookie(cookiePrefix + "-diff-hunks-state", "expanded", { expires:365 });
47         e.preventDefault();
48     });
49     $(".file-diff-controls a#collapse-all").live("click", function(e){
50         var container = $(this).parent().parent().parent();
51         var cookiePrefix = $(this).attr("gts:cookie-prefix") || 'generic';
52         container.find('.file-diff .header').removeClass("open").addClass("closed");
53         container.find('.diff-hunks').hide();
54         $.cookie(cookiePrefix + "-diff-hunks-state", "collapsed", { expires:365 });
55         e.preventDefault();
56     });
57
58     // merge request diffing loading indimacator
59     Gitorious.MergeRequestDiffSpinner = $("#merge_request_diff_loading").html();
60     $("#merge_request_diff").html(Gitorious.MergeRequestDiffSpinner);
61
62     // Merge request selection of branches, compact mode
63     // wrapped in a function so we can reuse it when we load another version
64     diffBrowserCompactCommitSelectable = function() {
65       var selectingAndUnselecting = function() {
66         var commits = $("li.ui-selecting a");
67         if (!commits[0]) return true;
68         var first_commit_sha = $(commits[0]).attr("data-commit-sha");
69         var last_commit_sha = $(commits[commits.length - 1]).attr("data-commit-sha");
70         
71         var shaSpec = new Gitorious.ShaSpec();
72         shaSpec.addSha(first_commit_sha);
73         shaSpec.addSha(last_commit_sha); 
74
75         Gitorious.MergeRequestController.getInstance().isSelectingShas(shaSpec);
76       };
77       return jQuery("#merge_request_commit_selector.compact").selectable({
78         filter: "li.single_commit",
79         stop: function(e, ui) {
80           var sha_spec = new Gitorious.ShaSpec();
81           jQuery("li.ui-selected a", this).each(function() {
82             sha = jQuery(this).attr("data-commit-sha");
83             sha_spec.addSha(sha);
84           });
85           Gitorious.MergeRequestController.getInstance().didSelectShas(sha_spec);
86         },
87         start: function(e, ui) {
88           Gitorious.MergeRequestController.getInstance().willSelectShas();
89         },
90         selecting: function(e, ui) {
91           selectingAndUnselecting();
92         },
93         unselecting: function(e,ui) {
94           selectingAndUnselecting();
95         },
96         cancel: ".merge_base"
97       });
98     }
99     Gitorious.currentMRCompactSelectable = diffBrowserCompactCommitSelectable();
100
101     $("#merge_request_version").changableSelection({
102       onChange: function() {
103           var version = $(this).attr("data-mr-version-number");
104           Gitorious.MergeRequestController.getInstance().loadVersion(version);
105 //          Gitorious.MergeRequestController.getInstance().versionChanged(version);
106       }
107     });
108     
109     $("#merge_request_current_version ul.compact li.single_commit").hoverBubble();
110     
111     // Merge request selection of branches, monster mode
112     $("#large_commit_selector_toggler").live("click", function(event) {
113         $("#large_commit_selector").slideToggle();
114         event.preventDefault();
115     });
116
117     // Handle selection of multiple commits in the large merge-request commit diff browser
118     var previousSelectedCommitRowIndex;
119     $("#large_commit_selector table#commit_table tr input").live("click", function(event) {
120         var selectedTr = $(this).parents("tr");
121         var commitRows = selectedTr.parents("table").find("tr.commit_row");
122
123         if (commitRows.filter(".selected").length === 0) {
124             // mark initial selection
125             selectedTr.addClass("selected");
126             return;
127         }
128
129         var firstSelRowIndex = commitRows.indexOf(commitRows.filter(".selected:first")[0]);
130         var lastSelRowIndex = commitRows.indexOf(commitRows.filter(".selected:last")[0]);
131         var selectedRowIndex = commitRows.indexOf(selectedTr[0]);
132         var markRange = function(start, end) {
133             commitRows.slice(start, end + 1).addClass("selected");
134         };
135
136         // reset selections first
137         commitRows.filter(".selected").removeClass("selected");
138         if (selectedRowIndex === firstSelRowIndex || selectedRowIndex === lastSelRowIndex) {
139             selectedTr.addClass("selected");
140             return;
141         }
142
143         if (selectedRowIndex > firstSelRowIndex &&
144             selectedRowIndex < lastSelRowIndex) // in-between
145         {
146             if (previousSelectedCommitRowIndex === firstSelRowIndex) {
147                 markRange(selectedRowIndex, lastSelRowIndex);
148             } else {
149                 markRange(firstSelRowIndex, selectedRowIndex);
150             }
151         } else if (selectedRowIndex > firstSelRowIndex) { // downwards
152             markRange(firstSelRowIndex, selectedRowIndex);
153         } else { // upwards
154             markRange(selectedRowIndex, lastSelRowIndex);
155         }
156
157         previousSelectedCommitRowIndex = selectedRowIndex;
158     });
159
160     // Display a range of commits from the large merge-request commit diff browser
161     $("#show-large-diff-range").live("click", function(event) {
162         var selected = $("#large_commit_selector table#commit_table tr.commit_row.selected");
163         var spec = new Gitorious.ShaSpec();
164         var firstSHA = selected.filter(":first").find("input.merge_to").val();
165         var lastSHA = selected.filter(":last").find("input.merge_to").val();
166         spec.addSha(firstSHA);
167         if (firstSHA != lastSHA)
168           spec.addSha(lastSHA);
169         spec.summarizeHtml();
170         var diff_browser = new Gitorious.DiffBrowser(spec.shaSpec());
171         $("#large_commit_selector").hide();
172         event.preventDefault();
173     });
174
175     // Show a single commit in the large merge-request commit diff browser
176     $("#large_commit_selector #commit_table a.clickable_commit").live("click", function(e){
177         var spec = new Gitorious.ShaSpec();
178         spec.addSha($(this).attr("data-commit-sha"));
179         var diff_browser = new Gitorious.DiffBrowser(spec.shaSpec());
180         $("#large_commit_selector").hide();
181         e.preventDefault();
182     });
183     
184     jQuery("#current_shas").each(function(){
185         var sha_spec = jQuery(this).attr("data-merge-request-current-shas");
186         diff_browser = new Gitorious.DiffBrowser(sha_spec);
187       }
188     );
189
190     // Diff commenting
191     $("table tr td.inline_comments a.diff-comment-count").live("click", function(e) {
192         var lineOffsets = $(this).parents("tr").attr("data-line-num-tuple");
193         $("#diff-inline-comments-for-" + lineOffsets).slideToggle();
194         e.preventDefault();
195     });
196
197
198     // Clicking on a comment relating to an inline commit comment
199     $(".commentable.comments .inline_comment_link a").live("click", function (){
200         var comment = $(this).parents("div.comment.inline");
201         var path = $(comment).attr("data-diff-path");
202         var last_line_number = $(comment).attr("data-last-line-in-diff");
203         var href = $(this).attr("href");
204         var hunks = $(".file-diff[data-diff-path=" + path + "] .diff-hunks");
205         hunks.removeClass("closed").addClass("open");
206         hunks.slideDown();
207         var lastLine = $("#diff-inline-comments-for-" + last_line_number);
208         lastLine.slideToggle();
209         Gitorious.DiffBrowser.CommentHighlighter.add($(href));
210         $.scrollTo(href);
211         return true;
212     });
213     
214     // Clicking on a comment relating to a merge request 
215     // version displays the comment in context
216     $("#merge_request_comments .comment.inline .inline_comment_link a").live("click", function() {
217         var comment = $(this).parents("div.comment.inline");
218         var path = $(comment).attr("data-diff-path");
219         var last_line = $(comment).attr("data-last-line-in-diff");
220         var sha_range = $(comment).attr("data-sha-range");
221         var version = $(comment).attr("data-merge-request-version");
222
223         // Notify the controller of the current version and sha range
224         // Add self as listener when this has been completed
225         // When this has been completed, remove self as listener
226         var elementInDiff = function(s) {
227           return $(".file-diff[data-diff-path=" + path + "] " + s);
228         }
229         var href =  $(this).attr("href");
230         var commentSpinner = $("#loading_comment_" + href.split("_")[2]);
231         commentSpinner.show();
232         var jumpToComment = {
233             shaListingCurrent: function(newOrOld) {
234                 var c = Gitorious.MergeRequestController.getInstance();
235                 var spec = Gitorious.ShaSpec.parseShas(sha_range);
236                 c.simulateShaSelection(spec);
237                 c.replaceDiffContents(sha_range, this.displayComments, this);
238             },
239             displayComments: function(message) {                
240                 var lastLine = elementInDiff("#diff-inline-comments-for-" + last_line);
241                 var hunks = elementInDiff(".diff-hunks");
242                 hunks.removeClass("closed").addClass("open");
243                 hunks.slideDown();
244                 lastLine.slideToggle();
245                 Gitorious.DiffBrowser.CommentHighlighter.add($(href));                
246                 this.finish();
247                 $.scrollTo(href);
248             },
249             finish: function() {
250                 commentSpinner.hide();
251                 NotificationCenter.removeObserver("MergeRequestShaListingUpdated", this);
252             }
253         };
254         NotificationCenter.addObserver("MergeRequestShaListingUpdated",
255                                        jumpToComment.shaListingCurrent.bind(jumpToComment));
256         Gitorious.MergeRequestController.getInstance().versionChanged(version);
257         return true;
258     });
259
260     $("#toggle_inline_comments").live("change", function(){
261         if ($(this).is(":checked")) {
262           $(".comment.inline").show();
263         } else {
264           $(".comment.inline").hide();
265         }
266     });
267     if ($("#inline_comment_form.commit").length > 0) {
268         Gitorious.enableCommenting();
269     }
270 });
271
272
273 if (!Gitorious)
274   var Gitorious = {};
275