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