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