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