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