nitdoc: Add an action on "Commit" button
[nit.git] / share / nitdoc / scripts / js-facilities.js
1 // User
2 var userB64 = null;
3 var sessionStarted = false;
4 var editComment = 0;
5 var currentfileContent = '';
6
7 // SHA GitHub
8 var shaLastCommit = "";
9 var shaBaseTree;
10 var shaNewTree;
11 var shaNewCommit;
12 var shaBlob;
13 var shaMaster;
14
15 /*
16 * JQuery Case Insensitive :icontains selector
17 */
18 $.expr[':'].icontains = function(obj, index, meta, stack){
19 return (obj.textContent.replace(/\[[0-9]+\]/g, "") || obj.innerText.replace(/\[[0-9]+\]/g, "") || jQuery(obj).text().replace(/\[[0-9]+\]/g, "") || '').toLowerCase().indexOf(meta[3].toLowerCase()) >= 0;
20 };
21
22 /*
23 * Quick Search global vars
24 */
25
26 // Current search results preview table
27 var currentTable = null;
28
29 //Hightlighted index in search result preview table
30 var currentIndex = -1;
31
32
33 /*
34 * Add folding and filtering facilities to class description page.
35 */
36 $(document).ready(function() {
37
38 // Hide edit tags
39 $('textarea').hide();
40 $('a[id=commitBtn]').hide();
41 $('a[id=cancelBtn]').hide();
42 // Hide Authenfication form
43 $(".popover").hide();
44 // Update display
45 updateDisplaying();
46
47 /*
48 * Highlight the spoted element
49 */
50 highlightBlock(currentAnchor());
51
52 /*
53 * Nav block folding
54 */
55
56 // Menu nav folding
57 $(".menu nav h3")
58 .prepend(
59 $(document.createElement("a"))
60 .html("-")
61 .addClass("fold")
62 )
63 .css("cursor", "pointer")
64 .click( function() {
65 if($(this).find("a.fold").html() == "+") {
66 $(this).find("a.fold").html("-");
67 } else {
68 $(this).find("a.fold").html("+");
69 }
70 $(this).nextAll().toggle();
71 })
72
73 // Insert search field
74 $("nav.main ul")
75 .append(
76 $(document.createElement("li"))
77 .append(
78 $(document.createElement("form"))
79 .append(
80 $(document.createElement("input"))
81 .attr({
82 id: "search",
83 type: "text",
84 autocomplete: "off",
85 value: "quick search..."
86 })
87 .addClass("notUsed")
88
89 // Key management
90 .keyup(function(e) {
91 switch(e.keyCode) {
92
93 // Select previous result on "Up"
94 case 38:
95 // If already on first result, focus search input
96 if(currentIndex == 0) {
97 $("#search").val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
98 $("#search").focus();
99 // Else select previous result
100 } else if(currentIndex > 0) {
101 $(currentTable.find("tr")[currentIndex]).removeClass("activeSearchResult");
102 currentIndex--;
103 $(currentTable.find("tr")[currentIndex]).addClass("activeSearchResult");
104 $("#search").val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
105 $("#search").focus();
106 }
107 break;
108
109 // Select next result on "Down"
110 case 40:
111 if(currentIndex < currentTable.find("tr").length - 1) {
112 $(currentTable.find("tr")[currentIndex]).removeClass("activeSearchResult");
113 currentIndex++;
114 $(currentTable.find("tr")[currentIndex]).addClass("activeSearchResult");
115 $("#search").val($(currentTable.find("tr")[currentIndex]).data("searchDetails").name);
116 $("#search").focus();
117 }
118 break;
119 // Go to url on "Enter"
120 case 13:
121 if(currentIndex > -1) {
122 window.location = $(currentTable.find("tr")[currentIndex]).data("searchDetails").url;
123 return false;
124 }
125 if($("#search").val().length == 0)
126 return false
127
128 window.location = "full-index.html#q=" + $("#search").val();
129 if(window.location.href.indexOf("full-index.html") > -1) {
130 location.reload();
131 }
132 return false;
133 break;
134
135 // Hide results preview on "Escape"
136 case 27:
137 $(this).blur();
138 if(currentTable != null) {
139 currentTable.remove();
140 currentTable = null;
141 }
142 break;
143
144 default:
145 if($("#search").val().length == 0) {
146 return false;
147 }
148
149 // Remove previous table
150 if(currentTable != null) {
151 currentTable.remove();
152 }
153
154 // Build results table
155 currentIndex = -1;
156 currentTable = $(document.createElement("table"));
157
158 // Escape regexp related characters in query
159 var query = $("#search").val();
160 query = query.replace(/\[/gi, "\\[");
161 query = query.replace(/\|/gi, "\\|");
162 query = query.replace(/\*/gi, "\\*");
163 query = query.replace(/\+/gi, "\\+");
164 query = query.replace(/\\/gi, "\\\\");
165 query = query.replace(/\?/gi, "\\?");
166 query = query.replace(/\(/gi, "\\(");
167 query = query.replace(/\)/gi, "\\)");
168
169 var index = 0;
170 var regexp = new RegExp("^" + query, "i");
171 for(var entry in entries) {
172 if(index > 10) {
173 break;
174 }
175 var result = entry.match(regexp);
176 if(result != null && result.toString().toUpperCase() == $("#search").val().toUpperCase()) {
177 for(var i = 0; i < entries[entry].length; i++) {
178 if(index > 10) {
179 break;
180 }
181 currentTable.append(
182 $(document.createElement("tr"))
183 .data("searchDetails", {name: entry, url: entries[entry][i]["url"]})
184 .data("index", index)
185 .append($(document.createElement("td")).html(entry))
186 .append(
187 $(document.createElement("td"))
188 .addClass("entryInfo")
189 .html(entries[entry][i]["txt"] + "&nbsp;&raquo;"))
190 .mouseover( function() {
191 $(currentTable.find("tr")[currentIndex]).removeClass("activeSearchResult");
192 $(this).addClass("activeSearchResult");
193 currentIndex = $(this).data("index");
194 })
195 .mouseout( function() {
196 $(this).removeClass("activeSearchResult");
197 })
198 .click( function() {
199 window.location = $(this).data("searchDetails")["url"];
200 })
201 );
202 index++;
203 }
204 }
205 }
206
207 // Initialize table properties
208 currentTable.attr("id", "searchTable");
209 currentTable.css("position", "absolute");
210 currentTable.width($("#search").outerWidth());
211 $("header").append(currentTable);
212 currentTable.offset({left: $("#search").offset().left + ($("#search").outerWidth() - currentTable.outerWidth()), top: $("#search").offset().top + $("#search").outerHeight()});
213
214 // Preselect first entry
215 if(currentTable.find("tr").length > 0) {
216 currentIndex = 0;
217 $(currentTable.find("tr")[currentIndex]).addClass("activeSearchResult");
218 $("#search").focus();
219 }
220 break;
221 }
222 })
223 .focusout(function() {
224 if($(this).val() == "") {
225 $(this).addClass("notUsed");
226 $(this).val("quick search...");
227 }
228 })
229 .focusin(function() {
230 if($(this).val() == "quick search...") {
231 $(this).removeClass("notUsed");
232 $(this).val("");
233 }
234 })
235 )
236 .submit( function() {
237 return false;
238 })
239 )
240 );
241
242 // Close quicksearch list on click
243 $(document).click(function(e) {
244 if(e.target != $("#search")[0] && e.target != $("#searchTable")[0]) {
245 if(currentTable != null) {
246 currentTable.remove();
247 currentTable = null;
248 }
249 }
250 });
251
252 // Insert filter field
253 $("article.filterable h2, nav.filterable h3")
254 .after(
255 $(document.createElement("div"))
256 .addClass("filter")
257 .append(
258 $(document.createElement("input"))
259 .attr({
260 type: "text",
261 value: "filter..."
262 })
263 .addClass("notUsed")
264 .keyup(function() {
265 $(this).parent().parent().find("ul li:not(:icontains('" + $(this).val() + "'))").addClass("hide");
266 $(this).parent().parent().find("ul li:icontains('" + $(this).val() + "')").removeClass("hide");
267 })
268 .focusout(function() {
269 if($(this).val() == "") {
270 $(this).addClass("notUsed");
271 $(this).val("filter...");
272 }
273 })
274 .focusin(function() {
275 if($(this).val() == "filter...") {
276 $(this).removeClass("notUsed");
277 $(this).val("");
278 }
279 })
280 )
281 );
282
283 // Filter toggle between H I R in nav porperties list
284 $("nav.properties.filterable .filter")
285 .append(
286 $(document.createElement("a"))
287 .html("H")
288 .attr({
289 title: "hide inherited properties"
290 })
291 .click( function() {
292 if($(this).hasClass("hidden")) {
293 $(this).parent().parent().find("li.inherit").show();
294 } else {
295 $(this).parent().parent().find("li.inherit").hide();
296 }
297
298 $(this).toggleClass("hidden");
299 })
300 )
301 .append(
302 $(document.createElement("a"))
303 .html("R")
304 .attr({
305 title: "hide redefined properties"
306 })
307 .click( function() {
308 if($(this).hasClass("hidden")) {
309 $(this).parent().parent().find("li.redef").show();
310 } else {
311 $(this).parent().parent().find("li.redef").hide();
312 }
313
314 $(this).toggleClass("hidden");
315 })
316 )
317 .append(
318 $(document.createElement("a"))
319 .html("I")
320 .attr({
321 title: "hide introduced properties"
322 })
323 .click( function() {
324 if($(this).hasClass("hidden")) {
325 $(this).parent().parent().find("li.intro").show();
326 } else {
327 $(this).parent().parent().find("li.intro").hide();
328 }
329
330 $(this).toggleClass("hidden");
331 })
332 );
333
334 // Filter toggle between I R in
335 $("article.properties.filterable .filter, article.classes.filterable .filter")
336 .append(
337 $(document.createElement("a"))
338 .html("I")
339 .attr({
340 title: "hide introduced properties"
341 })
342 .click( function() {
343 if($(this).hasClass("hidden")) {
344 $(this).parent().parent().find("li.intro").show();
345 } else {
346 $(this).parent().parent().find("li.intro").hide();
347 }
348
349 $(this).toggleClass("hidden");
350 })
351 )
352 .append(
353 $(document.createElement("a"))
354 .html("R")
355 .attr({
356 title: "hide redefined properties"
357 })
358 .click( function() {
359 if($(this).hasClass("hidden")) {
360 $(this).parent().parent().find("li.redef").show();
361 } else {
362 $(this).parent().parent().find("li.redef").hide();
363 }
364
365 $(this).toggleClass("hidden");
366 })
367 );
368
369 /*
370 * Anchors jumps
371 */
372 $("a[href*='#']").click( function() {
373 highlightBlock($(this).attr("href").split(/#/)[1]);
374 });
375
376 //Preload filter fields with query string
377 preloadFilters();
378 // Hide Authenfication form
379 $(".popover").hide();
380 // Display Login modal
381 $("#logGitHub").click(function(){ displayLogginModal(); });
382 // Update display
383 updateDisplaying();
384 // If cookie existing the session is opened
385 if(sessionStarted){ userB64 = "Basic " + getUserPass("logginNitdoc"); }
386
387 // Sign In an github user or Log out him
388 $("#signIn").click(function(){
389 if(!sessionStarted){
390 if($('#loginGit').val() == "" || $('#passwordGit').val() == ""){ displayMessage('The comment field is empty!', 40, 45); }
391 else
392 {
393 userName = $('#loginGit').val();
394 password = $('#passwordGit').val();
395 repoName = $('#repositoryGit').val();
396 branchName = $('#branchGit').val();
397 userB64 = "Basic " + base64.encode(userName+':'+password);
398 setCookie("logginNitdoc", base64.encode(userName+':'+password+':'+repoName+':'+branchName), 1);
399 $('#loginGit').val("");
400 $('#passwordGit').val("");
401 }
402 }
403 else
404 {
405 // Delete cookie and reset settings
406 del_cookie("logginNitdoc");
407 }
408 displayLogginModal();
409 });
410
411 // Activate edit mode
412 $('pre[class=text_label]').click(function(){
413 // the customer is loggued ?
414 if(!sessionStarted || userName == ""){
415 // No => nothing happen
416 return;
417 }
418 else{
419 var arrayNew = $(this).text().split('\n');
420 var lNew = arrayNew.length - 1;
421 var adapt = "";
422
423 for (var i = 0; i < lNew; i++) {
424 adapt += arrayNew[i];
425 if(i < lNew-1){ adapt += "\n"; }
426 }
427 editComment += 1;
428 // hide comment
429 $(this).hide();
430 // Show edit box
431 $(this).next().show();
432 // Show cancel button
433 $(this).next().next().show();
434 // Show commit button
435 $(this).next().next().next().show();
436 // Add text in edit box
437 if($(this).next().val() == ""){ $(this).next().val(adapt); }
438 // Resize edit box
439 $(this).next().height($(this).next().prop("scrollHeight"));
440 // Select it
441 $(this).next().select();
442 preElement = $(this);
443 }
444 });
445
446 // Disable the edit mode
447 $('a[id=cancelBtn]').click(function(){
448 if(editComment > 0){ editComment -= 1; }
449 // Hide itself
450 $(this).hide();
451 // Hide commitBtn
452 $(this).next().hide();
453 // Hide Textarea
454 $(this).prev().hide();
455 // Show comment
456 $(this).prev().prev().show();
457 });
458
459 // Display commit form
460 $('a[id=commitBtn]').click(function(){
461 updateComment = $(this).prev().prev().val();
462 commentType = $(this).prev().prev().prev().attr('type');
463
464 if(updateComment == ""){ displayMessage('The comment field is empty!', 40, 45); }
465 else{
466 if(!sessionStarted){
467 displayMessage("You need to be loggued before commit something", 45, 40);
468 displayLogginModal();
469 return;
470 }
471 $('#commitMessage').val('New commit');
472 pathFile = $(this).prev().prev().prev().attr('tag');
473 $('#modal').show().prepend('<a class="close"><img src="resources/icons/close.png" class="btn_close" title="Close" alt="Close" /></a>');
474 $('body').append('<div id="fade"></div>');
475 $('#fade').css({'filter' : 'alpha(opacity=80)'}).fadeIn();
476 }
477 });
478
479 // Close commit form
480 $('.btn_close').click(function(){
481 $(this).hide();
482 $(this).next().hide();
483 if(editComment > 0){ editComment -= 1; }
484 });
485
486 //Close Popups and Fade Layer
487 $('body').on('click', 'a.close, #fade', function() {
488 if(editComment > 0){ editComment -= 1; }
489 $('#fade , #modal').fadeOut(function() {
490 $('#fade, a.close').remove();
491 });
492 $('#modalQuestion').hide();
493 });
494
495 $('#loginAction').click(function(){
496 var text;
497 var url;
498 var line;
499 // Look if the customer is logged
500 if(!sessionStarted){
501 displayMessage("You need to be loggued before commit something", 100, 40);
502 $('.popover').show();
503 return;
504 }
505 else{ userB64 = "Basic " + getUserPass("logginNitdoc"); }
506 githubRepo = repoName;
507 editComment -= 1;
508 commitMessage = $('#commitMessage').val();
509 if(commitMessage == ""){ commitMessage = "New commit";}
510 if(sessionStarted){
511 if ($.trim(updateComment) == ''){ this.value = (this.defaultValue ? this.defaultValue : ''); }
512 else{ startCommitProcess(); }
513 }
514 $('#modal, #modalQuestion').fadeOut(function() {
515 $('#login').val("");
516 $('#password').val("");
517 $('textarea').hide();
518 $('textarea').prev().show();
519 });
520 $('a[id=cancelBtn]').hide();
521 $('a[id=commitBtn]').hide();
522 });
523 });
524
525 /* Parse current URL and return anchor name */
526 function currentAnchor() {
527 var index = document.location.hash.indexOf("#");
528 if (index >= 0) {
529 return document.location.hash.substring(index + 1);
530 }
531 return null;
532 }
533
534 /* Prealod filters field using search query */
535 function preloadFilters() {
536 // Parse URL and get query string
537 var search = currentAnchor();
538
539 if(search == null || search.indexOf("q=") == -1)
540 return;
541
542 search = search.substring(2, search.length);
543
544 if(search == "" || search == "undefined")
545 return;
546
547 $(":text").val(search);
548 $(".filter :text")
549 .removeClass("notUsed")
550 .trigger("keyup");
551
552 }
553
554 /* Hightlight the spoted block */
555 function highlightBlock(a) {
556 if(a == undefined) {
557 return;
558 }
559
560 $(".highlighted").removeClass("highlighted");
561
562 var target = $("#" + a);
563
564 if(target.is("article")) {
565 target.parent().addClass("highlighted");
566 }
567
568 target.addClass("highlighted");
569 target.show();
570 }
571
572 // Init process to commit the new comment
573 function startCommitProcess()
574 {
575 var numL = preElement.attr("title");
576 commentLineStart = numL.split('-')[0] - 1;
577 commentLineEnd = (commentLineStart + preElement.text().split('\n').length) - 1;
578 state = true;
579 replaceComment(updateComment, currentfileContent);
580 getLastCommit();
581 getBaseTree();
582 editComment = false;
583 }
584
585 function displayLogginModal(){
586 if ($('.popover').is(':hidden')) { $('.popover').show(); }
587 else { $('.popover').hide(); }
588 updateDisplaying();
589 }
590
591 function updateDisplaying(){
592 if (checkCookie())
593 {
594 $('#loginGit').hide();
595 $('#passwordGit').hide();
596 $('#lbpasswordGit').hide();
597 $('#lbloginGit').hide();
598 $('#repositoryGit').hide();
599 $('#lbrepositoryGit').hide();
600 $('#lbbranchGit').hide();
601 $('#branchGit').hide();
602 $("#liGitHub").attr("class", "current");
603 $("#imgGitHub").attr("src", "resources/icons/github-icon-w.png");
604 $('#nickName').text(userName);
605 $('#githubAccount').attr("href", "https://github.com/"+userName);
606 $('#logginMessage').css({'display' : 'block'});
607 $('#logginMessage').css({'text-align' : 'center'});
608 $('.popover').css({'height' : '80px'});
609 $('#signIn').text("Sign out");
610 sessionStarted = true;
611 }
612 else
613 {
614 sessionStarted = false;
615 $('#logginMessage').css({'display' : 'none'});
616 $("#liGitHub").attr("class", "");
617 $("#imgGitHub").attr("src", "resources/icons/github-icon.png");
618 $('#loginGit').val("");
619 $('#passwordGit').val("");
620 $('#nickName').text("");
621 $('.popover').css({'height' : '280px'});
622 $('#logginMessage').css({'display' : 'none'});
623 $('#repositoryGit').val($('#repoName').attr('name'));
624 $('#branchGit').val('wikidoc');
625 $('#signIn').text("Sign In");
626 $('#loginGit').show();
627 $('#passwordGit').show();
628 $('#lbpasswordGit').show();
629 $('#lbloginGit').show();
630 $('#repositoryGit').show();
631 $('#lbrepositoryGit').show();
632 $('#lbbranchGit').show();
633 $('#branchGit').show();
634 }
635 }
636
637 function setCookie(c_name, value, exdays)
638 {
639 var exdate=new Date();
640 exdate.setDate(exdate.getDate() + exdays);
641 var c_value=escape(value) + ((exdays==null) ? "" : "; expires="+exdate.toUTCString());
642 document.cookie=c_name + "=" + c_value;
643 }
644
645 function del_cookie(c_name)
646 {
647 document.cookie = c_name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
648 }
649
650 function getCookie(c_name)
651 {
652 var c_value = document.cookie;
653 var c_start = c_value.indexOf(" " + c_name + "=");
654 if (c_start == -1) { c_start = c_value.indexOf(c_name + "="); }
655 if (c_start == -1) { c_value = null; }
656 else
657 {
658 c_start = c_value.indexOf("=", c_start) + 1;
659 var c_end = c_value.indexOf(";", c_start);
660 if (c_end == -1) { c_end = c_value.length; }
661 c_value = unescape(c_value.substring(c_start,c_end));
662 }
663 return c_value;
664 }
665
666 function getUserPass(c_name){
667 var cookie = base64.decode(getCookie(c_name));
668 return base64.encode(cookie.split(':')[0] + ':' + cookie.split(':')[1]);
669 }
670
671 function checkCookie()
672 {
673 var cookie=getCookie("logginNitdoc");
674 if (cookie!=null && cookie!="")
675 {
676 cookie = base64.decode(cookie);
677 userName = cookie.split(':')[0];
678 repoName = cookie.split(':')[2];
679 branchName = cookie.split(':')[3];
680 return true;
681 }
682 else { return false; }
683 }
684
685
686 /*
687 * Base64
688 */
689 base64 = {};
690 base64.PADCHAR = '=';
691 base64.ALPHA = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
692 base64.getbyte64 = function(s,i) {
693 // This is oddly fast, except on Chrome/V8.
694 // Minimal or no improvement in performance by using a
695 // object with properties mapping chars to value (eg. 'A': 0)
696 var idx = base64.ALPHA.indexOf(s.charAt(i));
697 if (idx == -1) {
698 throw "Cannot decode base64";
699 }
700 return idx;
701 }
702
703 base64.decode = function(s) {
704 // convert to string
705 s = "" + s;
706 var getbyte64 = base64.getbyte64;
707 var pads, i, b10;
708 var imax = s.length
709 if (imax == 0) {
710 return s;
711 }
712
713 if (imax % 4 != 0) {
714 throw "Cannot decode base64";
715 }
716
717 pads = 0
718 if (s.charAt(imax -1) == base64.PADCHAR) {
719 pads = 1;
720 if (s.charAt(imax -2) == base64.PADCHAR) {
721 pads = 2;
722 }
723 // either way, we want to ignore this last block
724 imax -= 4;
725 }
726
727 var x = [];
728 for (i = 0; i < imax; i += 4) {
729 b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) |
730 (getbyte64(s,i+2) << 6) | getbyte64(s,i+3);
731 x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff, b10 & 0xff));
732 }
733
734 switch (pads) {
735 case 1:
736 b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12) | (getbyte64(s,i+2) << 6)
737 x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 0xff));
738 break;
739 case 2:
740 b10 = (getbyte64(s,i) << 18) | (getbyte64(s,i+1) << 12);
741 x.push(String.fromCharCode(b10 >> 16));
742 break;
743 }
744 return x.join('');
745 }
746
747 base64.getbyte = function(s,i) {
748 var x = s.charCodeAt(i);
749 if (x > 255) {
750 throw "INVALID_CHARACTER_ERR: DOM Exception 5";
751 }
752 return x;
753 }
754
755
756 base64.encode = function(s) {
757 if (arguments.length != 1) {
758 throw "SyntaxError: Not enough arguments";
759 }
760 var padchar = base64.PADCHAR;
761 var alpha = base64.ALPHA;
762 var getbyte = base64.getbyte;
763
764 var i, b10;
765 var x = [];
766
767 // convert to string
768 s = "" + s;
769
770 var imax = s.length - s.length % 3;
771
772 if (s.length == 0) {
773 return s;
774 }
775 for (i = 0; i < imax; i += 3) {
776 b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8) | getbyte(s,i+2);
777 x.push(alpha.charAt(b10 >> 18));
778 x.push(alpha.charAt((b10 >> 12) & 0x3F));
779 x.push(alpha.charAt((b10 >> 6) & 0x3f));
780 x.push(alpha.charAt(b10 & 0x3f));
781 }
782 switch (s.length - imax) {
783 case 1:
784 b10 = getbyte(s,i) << 16;
785 x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
786 padchar + padchar);
787 break;
788 case 2:
789 b10 = (getbyte(s,i) << 16) | (getbyte(s,i+1) << 8);
790 x.push(alpha.charAt(b10 >> 18) + alpha.charAt((b10 >> 12) & 0x3F) +
791 alpha.charAt((b10 >> 6) & 0x3f) + padchar);
792 break;
793 }
794 return x.join('');
795 }
796
797 $.fn.spin = function(opts) {
798 this.each(function() {
799 var $this = $(this),
800 data = $this.data();
801
802 if (data.spinner) {
803 data.spinner.stop();
804 delete data.spinner;
805 }
806 if (opts !== false) {
807 data.spinner = new Spinner($.extend({color: $this.css('color')}, opts)).spin(this);
808 }
809 });
810 return this;
811 };
812
813 function getLastCommit()
814 {
815 var urlHead = '';
816 if(sessionStarted){ urlHead = "https://api.github.com/repos/"+userName+"/"+githubRepo+"/git/refs/heads/"+branchName;}
817 else{
818 // TODO: get url of the original repo.
819 return;
820 }
821
822 $.ajax({
823 beforeSend: function (xhr) {
824 if (userB64 != ""){ xhr.setRequestHeader ("Authorization", userB64); }
825 },
826 type: "GET",
827 url: urlHead,
828 dataType:"json",
829 async: false,
830 success: function(success)
831 {
832 shaLastCommit = success.object.sha;
833 }
834 });
835 }
836
837 function getBaseTree()
838 {
839 $.ajax({
840 beforeSend: function (xhr) {
841 if (userB64 != ""){ xhr.setRequestHeader ("Authorization", userB64); }
842 },
843 type: "GET",
844 url: "https://api.github.com/repos/"+userName+"/"+githubRepo+"/git/commits/" + shaLastCommit,
845 dataType:"json",
846 async: false,
847 success: function(success)
848 {
849 shaBaseTree = success.tree.sha;
850 if (state){ setBlob(); }
851 else{ return; }
852 },
853 error: function(){
854 return;
855 }
856 });
857 }
858
859 function setNewTree()
860 {
861 $.ajax({
862 beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", userB64); },
863 type: "POST",
864 url: "https://api.github.com/repos/"+userName+"/"+githubRepo+"/git/trees",
865 async: false,
866 data:'{ "base_tree" : "'+shaBaseTree+'", '+
867 '"tree":[{ '+
868 '"path":"'+ pathFile +'",'+
869 '"mode":"100644",'+
870 '"type":"blob",'+
871 '"sha": "'+ shaBlob +'"'+
872 '}] '+
873 '}',
874 success: function(success)
875 { // si l'appel a bien fonctionné
876 shaNewTree = JSON.parse(success).sha;
877 setNewCommit();
878 },
879 error: function(){
880 return;
881 }
882 });
883 }
884
885 function setNewCommit()
886 {
887 $.ajax({
888 beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", userB64); },
889 type: "POST",
890 url: "https://api.github.com/repos/"+userName+"/"+githubRepo+"/git/commits",
891 async: false,
892 data:'{ "message" : "'+ commitMessage +'", '+
893 '"parents" :"'+shaLastCommit+'",'+
894 '"tree": "'+shaNewTree+'"'+
895 '}',
896 success: function(success)
897 {
898 shaNewCommit = JSON.parse(success).sha;
899 commit();
900 },
901 error: function(){
902 return;
903 }
904 });
905 }
906
907 //Create a commit
908 function commit()
909 {
910 $.ajax({
911 beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", userB64); },
912 type: "POST",
913 url: "https://api.github.com/repos/"+userName+"/"+githubRepo+"/git/refs/heads/"+branchName,
914 data:'{ "sha" : "'+shaNewCommit+'", '+
915 '"force" :"true"'+
916 '}',
917 success: function(success) { displayMessage('Commit created successfully', 40, 40); },
918 error:function(error){ displayMessage('Error ' + JSON.parse(error).object.message, 40, 40); }
919 });
920 }
921
922 // Create a blob
923 function setBlob()
924 {
925 $.ajax({
926 beforeSend: function (xhr) { xhr.setRequestHeader ("Authorization", userB64); },
927 type: "POST",
928 url: "https://api.github.com/repos/"+userName+"/"+githubRepo+"/git/blobs",
929 async: false,
930 data:'{ "content" : "'+text.replace(/\r?\n/g, '\\n').replace(/\t/g, '\\t').replace(/\"/g,'\\"')+'", '+
931 '"encoding" :"utf-8"'+
932 '}',
933 success: function(success)
934 {
935 shaBlob = JSON.parse(success).sha;
936 setNewTree();
937 },
938 error:function(error){
939 displayMessage('Error : Problem parsing JSON', 40, 40);
940 return;
941 }
942 });
943 }
944
945 // Display file content
946 function getFileContent(urlFile, newComment)
947 {
948 $.ajax({
949 beforeSend: function (xhr) {
950 xhr.setRequestHeader ("Accept", "application/vnd.github-blob.raw");
951 if (userB64 != ""){ xhr.setRequestHeader ("Authorization", userB64); }
952 },
953 type: "GET",
954 url: urlFile,
955 async:false,
956 success: function(success)
957 {
958 state = true;
959 replaceComment(newComment, success);
960 }
961 });
962 }
963
964 function replaceComment(newComment, fileContent){
965 var arrayNew = newComment.split('\n');
966 var lNew = arrayNew.length;
967 text = "";
968 var lines = fileContent.split("\n");
969 for (var i = 0; i < lines.length; i++) {
970 if(i == commentLineStart){
971 // We change the comment
972 for(var j = 0; j < lNew; j++){
973 if(commentType == 1){ text += "\t# " + arrayNew[j] + "\n"; }
974 else{
975 if(arrayNew[j] == ""){ text += "#"+"\n"; }
976 else{ text += "# " + arrayNew[j] + "\n"; }
977 }
978 }
979 }
980 else if(i < commentLineStart || i >= commentLineEnd){
981 if(i == lines.length-1){ text += lines[i]; }
982 else{ text += lines[i] + "\n"; }
983 }
984 }
985 }
986
987 function getCommentLastCommit(path){
988 var urlRaw;
989 getLastCommit();
990 if(shaLastCommit != ""){
991 if (checkCookie()) { urlRaw="https://rawgithub.com/"+ userName +"/"+ repoName +"/" + shaLastCommit + "/" + path; }
992 else{ urlRaw="https://rawgithub.com/StefanLage/"+ $('#repoName').attr('name') +"/" + shaLastCommit + "/" + path; }
993
994 $.ajax({
995 type: "GET",
996 url: urlRaw,
997 async: false,
998 success: function(success)
999 {
1000 currentfileContent = success;
1001 }
1002 });
1003 }
1004 }
1005
1006 function displayMessage(msg, widthDiv, margModal){
1007 $('#modal').hide();
1008 $('#btnCreateBranch').css('margin-left',widthDiv + '%');
1009 $('#txtQuestion').text(msg);
1010 $('#btnCreateBranch').text("Ok");
1011 $('#btnCancelBranch').hide();
1012 $('#modalQuestion').css({'left' : margModal + '%'})
1013 $('#modalQuestion').show();
1014 $('#modalQuestion').show().prepend('<a class="close"><img src="resources/icons/close.png" class="btnCloseQuestion" title="Close" alt="Close" /></a>');
1015 $('body').append('<div id="fade"></div>');
1016 $('#fade').css({'filter' : 'alpha(opacity=80)'}).fadeIn();
1017 }