6d37dfa81fe0d52258cc04289412c6c1cd8024bd
2 * This code is mostly from the old Etherpad. Please help us to comment this code.
3 * This helps other people to understand this code better and helps them to improve it.
4 * TL;DR COMMENTS ON THIS FILE ARE HIGHLY APPRECIATED
8 * Copyright 2009 Google Inc.
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * Unless required by applicable law or agreed to in writing, software
17 * distributed under the License is distributed on an "AS-IS" BASIS,
18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19 * See the License for the specific language governing permissions and
20 * limitations under the License.
23 var padutils
= require('/pad_utils').padutils
;
24 var paddocbar
= require('/pad_docbar').paddocbar
;
26 var padsavedrevs
= (function()
29 function reversedCopy(L
)
36 function makeRevisionBox(revisionInfo
, rnum
)
38 var box
= $('<div class="srouterbox">' + '<div class="srinnerbox">' + '<a href="javascript:void(0)" class="srname"><!-- --></a>' + '<div class="sractions"><a class="srview" href="javascript:void(0)" target="_blank">view</a> | <a class="srrestore" href="javascript:void(0)">restore</a></div>' + '<div class="srtime"><!-- --></div>' + '<div class="srauthor"><!-- --></div>' + '<img class="srtwirly" src="static/img/misc/status-ball.gif">' + '</div></div>');
39 setBoxLabel(box
, revisionInfo
.label
);
40 setBoxTimestamp(box
, revisionInfo
.timestamp
);
41 box
.find(".srauthor").html("by " + padutils
.escapeHtml(revisionInfo
.savedBy
));
42 var viewLink
= '/ep/pad/view/' + pad
.getPadId() + '/' + revisionInfo
.id
;
43 box
.find(".srview").attr('href', viewLink
);
44 var restoreLink
= 'javascript:void(require('+JSON
.stringify(module
.id
)+').padsavedrevs.restoreRevision(' + JSON
.stringify(rnum
) + ');';
45 box
.find(".srrestore").attr('href', restoreLink
);
46 box
.find(".srname").click(function(evt
)
48 editRevisionLabel(rnum
, box
);
53 function setBoxLabel(box
, label
)
55 box
.find(".srname").html(padutils
.escapeHtml(label
)).attr('title', label
);
58 function setBoxTimestamp(box
, timestamp
)
60 box
.find(".srtime").html(padutils
.escapeHtml(
61 padutils
.timediff(new Date(timestamp
))));
66 return $("#savedrevisions .srouterbox").eq(n
);
69 function editRevisionLabel(rnum
, box
)
71 var input
= $('<input type="text" class="srnameedit"/>');
72 box
.find(".srnameedit").remove(); // just in case
73 var label
= box
.find(".srname");
74 input
.width(label
.width());
75 input
.height(label
.height());
76 input
.css('top', label
.position().top
);
77 input
.css('left', label
.position().left
);
79 label
.css('opacity', 0);
84 label
.css('opacity', 1);
86 var rev
= currentRevisionList
[rnum
];
87 var oldLabel
= rev
.label
;
90 var newLabel
= input
.val();
91 if (newLabel
&& newLabel
!= oldLabel
)
93 relabelRevision(rnum
, newLabel
);
97 input
.val(rev
.label
).focus().select();
98 padutils
.bindEnterAndEscape(input
, function onEnter()
101 }, function onEscape()
103 input
.val('').blur();
107 function relabelRevision(rnum
, newLabel
)
109 var rev
= currentRevisionList
[rnum
];
113 url
: '/ep/pad/saverevisionlabel',
115 userId
: pad
.getUserId(),
116 padId
: pad
.getPadId(),
124 function success(text
)
126 var newRevisionList
= JSON
.parse(text
);
127 self
.newRevisionList(newRevisionList
);
128 pad
.sendClientMessage(
130 type
: 'revisionLabel',
131 revisionList
: reversedCopy(currentRevisionList
),
132 savedBy
: pad
.getUserName(),
139 alert("Oops! There was an error saving that revision label. Please try again later.");
143 var currentRevisionList
= [];
145 function setRevisionList(newRevisionList
, noAnimation
)
147 // deals with changed labels and new added revisions
148 for (var i
= 0; i
< currentRevisionList
.length
; i
++)
150 var a
= currentRevisionList
[i
];
151 var b
= newRevisionList
[i
];
152 if (b
.label
!= a
.label
)
154 setBoxLabel(getNthBox(i
), b
.label
);
157 for (var j
= currentRevisionList
.length
; j
< newRevisionList
.length
; j
++)
159 var newBox
= makeRevisionBox(newRevisionList
[j
], j
);
160 $("#savedrevs-scrollinner").append(newBox
);
161 newBox
.css('left', j
* REVISION_BOX_WIDTH
);
163 var newOnes
= (newRevisionList
.length
> currentRevisionList
.length
);
164 currentRevisionList
= newRevisionList
;
167 setDesiredScroll(getMaxScroll());
170 setScroll(desiredScroll
);
175 var nameOfLast
= currentRevisionList
[currentRevisionList
.length
- 1].label
;
176 displaySavedTip(nameOfLast
);
181 function refreshRevisionList()
183 for (var i
= 0; i
< currentRevisionList
.length
; i
++)
185 var r
= currentRevisionList
[i
];
186 var box
= getNthBox(i
);
187 setBoxTimestamp(box
, r
.timestamp
);
191 var savedTipAnimator
= padutils
.makeShowHideAnimator(function(state
)
195 $("#revision-notifier").css('opacity', 0).css('display', 'block');
199 $("#revision-notifier").css('opacity', 1);
203 $("#revision-notifier").css('opacity', 0).css('display', 'none');
207 $("#revision-notifier").css('opacity', 1);
211 $("#revision-notifier").css('opacity', 1 - state
);
215 function displaySavedTip(text
)
217 $("#revision-notifier .name").html(padutils
.escapeHtml(text
));
218 savedTipAnimator
.show();
219 padutils
.cancelActions("hide-revision-notifier");
220 var hideLater
= padutils
.getCancellableAction("hide-revision-notifier", function()
222 savedTipAnimator
.hide();
224 window
.setTimeout(hideLater
, 3000);
227 var REVISION_BOX_WIDTH
= 120;
228 var curScroll
= 0; // distance between left of revisions and right of view
229 var desiredScroll
= 0;
231 function getScrollWidth()
233 return REVISION_BOX_WIDTH
* currentRevisionList
.length
;
236 function getViewportWidth()
238 return $("#savedrevs-scrollouter").width();
241 function getMinScroll()
243 return Math
.min(getViewportWidth(), getScrollWidth());
246 function getMaxScroll()
248 return getScrollWidth();
251 function setScroll(newScroll
)
253 curScroll
= newScroll
;
254 $("#savedrevs-scrollinner").css('right', newScroll
);
255 updateScrollArrows();
258 function setDesiredScroll(newDesiredScroll
, dontUpdate
)
260 desiredScroll
= Math
.min(getMaxScroll(), Math
.max(getMinScroll(), newDesiredScroll
));
267 function updateScroll()
269 updateScrollArrows();
270 scrollAnimator
.scheduleAnimation();
273 function updateScrollArrows()
275 $("#savedrevs-scrollleft").toggleClass("disabledscrollleft", desiredScroll
<= getMinScroll());
276 $("#savedrevs-scrollright").toggleClass("disabledscrollright", desiredScroll
>= getMaxScroll());
278 var scrollAnimator
= padutils
.makeAnimationScheduler(function()
280 setDesiredScroll(desiredScroll
, true); // re-clamp
281 if (Math
.abs(desiredScroll
- curScroll
) < 1)
283 setScroll(desiredScroll
);
288 setScroll(curScroll
+ (desiredScroll
- curScroll
) * 0.5);
293 var isSaving
= false;
295 function setIsSaving(v
)
301 function haveReachedRevLimit()
303 var mv
= pad
.getPrivilege('maxRevisions');
304 return (!(mv
< 0 || mv
> currentRevisionList
.length
));
307 function rerenderButton()
309 if (isSaving
|| (!pad
.isFullyConnected()) || haveReachedRevLimit())
311 $("#savedrevs-savenow").css('opacity', 0.75);
315 $("#savedrevs-savenow").css('opacity', 1);
319 var scrollRepeatTimer
= null;
320 var scrollStartTime
= 0;
322 function setScrollRepeatTimer(dir
)
324 clearScrollRepeatTimer();
325 scrollStartTime
= +new Date
;
326 scrollRepeatTimer
= window
.setTimeout(function f()
328 if (!scrollRepeatTimer
)
333 var scrollTime
= (+new Date
) - scrollStartTime
;
334 var delay
= (scrollTime
> 2000 ? 50 : 300);
335 scrollRepeatTimer
= window
.setTimeout(f
, delay
);
337 $(document
).bind('mouseup', clearScrollRepeatTimer
);
340 function clearScrollRepeatTimer()
342 if (scrollRepeatTimer
)
344 window
.clearTimeout(scrollRepeatTimer
);
345 scrollRepeatTimer
= null;
347 $(document
).unbind('mouseup', clearScrollRepeatTimer
);
352 init: function(initialRevisions
, _pad
)
355 self
.newRevisionList(initialRevisions
, true);
357 $("#savedrevs-savenow").click(function()
361 $("#savedrevs-scrollleft").mousedown(function()
364 setScrollRepeatTimer('left');
366 $("#savedrevs-scrollright").mousedown(function()
368 self
.scroll('right');
369 setScrollRepeatTimer('right');
371 $("#savedrevs-close").click(function()
373 paddocbar
.setShownPanel(null);
376 // update "saved n minutes ago" times
377 window
.setInterval(function()
379 refreshRevisionList();
382 restoreRevision: function(rnum
)
384 var rev
= currentRevisionList
[rnum
];
385 var warning
= ("Restoring this revision will overwrite the current" + " text of the pad. " + "Are you sure you want to continue?");
386 var hidePanel
= paddocbar
.hideLaterIfNoOtherInteraction();
387 var box
= getNthBox(rnum
);
388 if (confirm(warning
))
390 box
.find(".srtwirly").show();
394 url
: '/ep/pad/getrevisionatext',
396 padId
: pad
.getPadId(),
404 function success(resultJson
)
407 var result
= JSON
.parse(resultJson
);
408 padeditor
.restoreRevisionText(result
);
409 window
.setTimeout(function()
418 alert("Oops! There was an error retreiving the text (revNum= " + rev
.revNum
+ "; padId=" + pad
.getPadId());
423 box
.find(".srtwirly").hide();
426 showReachedLimit: function()
428 alert("Sorry, you do not have privileges to save more than " + pad
.getPrivilege('maxRevisions') + " revisions.");
430 newRevisionList: function(lst
, noAnimation
)
432 // server gives us list with newest first;
433 // we want chronological order
434 var L
= reversedCopy(lst
);
435 setRevisionList(L
, noAnimation
);
444 if (!pad
.isFullyConnected())
448 if (haveReachedRevLimit())
450 self
.showReachedLimit();
454 var savedBy
= pad
.getUserName() || "unnamed";
455 pad
.callWhenNotCommitting(submitSave
);
457 function submitSave()
462 url
: '/ep/pad/saverevision',
464 padId
: pad
.getPadId(),
466 savedById
: pad
.getUserId(),
467 revNum
: pad
.getCollabRevisionNumber()
474 function success(text
)
477 var newRevisionList
= JSON
.parse(text
);
478 self
.newRevisionList(newRevisionList
);
479 pad
.sendClientMessage(
481 type
: 'newRevisionList',
482 revisionList
: newRevisionList
,
490 alert("Oops! The server failed to save the revision. Please try again later.");
493 handleResizePage: function()
495 updateScrollArrows();
497 handleIsFullyConnected: function(isConnected
)
501 scroll: function(dir
)
503 var minScroll
= getMinScroll();
504 var maxScroll
= getMaxScroll();
507 if (desiredScroll
> minScroll
)
509 var n
= Math
.floor((desiredScroll
- 1 - minScroll
) / REVISION_BOX_WIDTH
);
510 setDesiredScroll(Math
.max(0, n
) * REVISION_BOX_WIDTH
+ minScroll
);
513 else if (dir
== 'right')
515 if (desiredScroll
< maxScroll
)
517 var n
= Math
.floor((maxScroll
- desiredScroll
- 1) / REVISION_BOX_WIDTH
);
518 setDesiredScroll(maxScroll
- Math
.max(0, n
) * REVISION_BOX_WIDTH
);
526 exports
.padsavedrevs
= padsavedrevs
;