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