diff --git a/IPython/html/static/base/js/utils.js b/IPython/html/static/base/js/utils.js
index 044a045..714faba 100644
--- a/IPython/html/static/base/js/utils.js
+++ b/IPython/html/static/base/js/utils.js
@@ -5,9 +5,10 @@ define([
'base/js/namespace',
'jquery',
'codemirror/lib/codemirror',
+ 'moment',
// silently upgrades CodeMirror
'codemirror/mode/meta',
-], function(IPython, $, CodeMirror){
+], function(IPython, $, CodeMirror, moment){
"use strict";
IPython.load_extensions = function () {
@@ -784,7 +785,42 @@ define([
return MathJax.Hub.Queue(["Typeset", MathJax.Hub, this]);
});
};
-
+
+ var time = {};
+ time.milliseconds = {};
+ time.milliseconds.s = 1000;
+ time.milliseconds.m = 60 * time.milliseconds.s;
+ time.milliseconds.h = 60 * time.milliseconds.m;
+ time.milliseconds.d = 24 * time.milliseconds.h;
+
+ time.thresholds = {
+ // moment.js thresholds in milliseconds
+ s: moment.relativeTimeThreshold('s') * time.milliseconds.s,
+ m: moment.relativeTimeThreshold('m') * time.milliseconds.m,
+ h: moment.relativeTimeThreshold('h') * time.milliseconds.h,
+ d: moment.relativeTimeThreshold('d') * time.milliseconds.d,
+ };
+
+ time.timeout_from_dt = function (dt) {
+ /** compute a timeout based on dt
+
+ input and output both in milliseconds
+
+ use moment's relative time thresholds:
+
+ - 10 seconds if in 'seconds ago' territory
+ - 1 minute if in 'minutes ago'
+ - 1 hour otherwise
+ */
+ if (dt < time.thresholds.s) {
+ return 10 * time.milliseconds.s;
+ } else if (dt < time.thresholds.m) {
+ return time.milliseconds.m;
+ } else {
+ return time.milliseconds.h;
+ }
+ };
+
var utils = {
regex_split : regex_split,
uuid : uuid,
@@ -820,6 +856,7 @@ define([
resolve_promises_dict: resolve_promises_dict,
reject: reject,
typeset: typeset,
+ time: time,
};
// Backwards compatability.
diff --git a/IPython/html/static/components b/IPython/html/static/components
index 87ff70d..6b578bb 160000
--- a/IPython/html/static/components
+++ b/IPython/html/static/components
@@ -1 +1 @@
-Subproject commit 87ff70d96567bf055eb94161a41e7b3e6da31b23
+Subproject commit 6b578bb789708ded9b6611039d162c71135dfd68
diff --git a/IPython/html/static/edit/js/savewidget.js b/IPython/html/static/edit/js/savewidget.js
index 5688780..c71cafd 100644
--- a/IPython/html/static/edit/js/savewidget.js
+++ b/IPython/html/static/edit/js/savewidget.js
@@ -141,47 +141,22 @@ define([
var long_date = chkd.format('llll');
var human_date;
var tdelta = Math.ceil(new Date() - this._last_modified);
- if (tdelta < 24 * H){
+ if (tdelta < utils.time.milliseconds.d){
// less than 24 hours old, use relative date
human_date = chkd.fromNow();
} else {
- // otherwise show calendar
- // otherwise update every hour and show
+ // otherwise show calendar
// at hh,mm,ss
human_date = chkd.calendar();
}
el.text(human_date).attr('title', long_date);
};
-
-
- var S = 1000;
- var M = 60*S;
- var H = 60*M;
- var thresholds = {
- s: 45 * S,
- m: 45 * M,
- h: 22 * H
- };
- var _timeout_from_dt = function (ms) {
- /** compute a timeout to update the last-modified timeout
-
- based on the delta in milliseconds
- */
- if (ms < thresholds.s) {
- return 5 * S;
- } else if (ms < thresholds.m) {
- return M;
- } else {
- return 5 * M;
- }
- };
SaveWidget.prototype._schedule_render_last_modified = function () {
/** schedule the next update to relative date
periodically updated, so short values like 'a few seconds ago' don't get stale.
*/
- var that = this;
if (!this._last_modified) {
return;
}
@@ -189,12 +164,10 @@ define([
clearTimeout(this._last_modified_timeout);
}
var dt = Math.ceil(new Date() - this._last_modified);
- if (dt < 24 * H) {
- this._last_modified_timeout = setTimeout(
- $.proxy(this._render_last_modified, this),
- _timeout_from_dt(dt)
- );
- }
+ this._last_modified_timeout = setTimeout(
+ $.proxy(this._render_last_modified, this),
+ utils.time.timeout_from_dt(dt)
+ );
};
return {'SaveWidget': SaveWidget};
diff --git a/IPython/html/static/notebook/js/savewidget.js b/IPython/html/static/notebook/js/savewidget.js
index 6b9db96..d1c6f6e 100644
--- a/IPython/html/static/notebook/js/savewidget.js
+++ b/IPython/html/static/notebook/js/savewidget.js
@@ -155,93 +155,58 @@ define([
this.element.find('span.autosave_status').text(msg);
};
- SaveWidget.prototype._set_checkpoint_status = function (human_date, iso_date) {
- var el = this.element.find('span.checkpoint_status');
- if(human_date){
- el.text("Last Checkpoint: "+human_date).attr('title',iso_date);
+ SaveWidget.prototype._set_last_checkpoint = function (checkpoint) {
+ if (checkpoint) {
+ this._checkpoint_date = new Date(checkpoint.last_modified);
} else {
- el.text('').attr('title', 'no-checkpoint');
- }
- };
-
- // compute (roughly) the remaining time in millisecond until the next
- // moment.js relative time update of the string, which by default
- // happend at
- // (a few seconds ago)
- // - 45sec,
- // (a minute ago)
- // - 90sec,
- // ( x minutes ago)
- // - then every minutes until
- // - 45 min,
- // (an hour ago)
- // - 1h45,
- // (x hours ago )
- // - then every hours
- // - 22 hours ago
- var _next_timeago_update = function(deltatime_ms){
- var s = 1000;
- var m = 60*s;
- var h = 60*m;
-
- var mtt = moment.relativeTimeThreshold;
-
- if(deltatime_ms < mtt.s*s){
- return mtt.s*s-deltatime_ms;
- } else if (deltatime_ms < (mtt.s*s+m)) {
- return (mtt.s*s+m)-deltatime_ms;
- } else if (deltatime_ms < mtt.m*m){
- return m;
- } else if (deltatime_ms < (mtt.m*m+h)){
- return (mtt.m*m+h)-deltatime_ms;
- } else {
- return h;
+ this._checkpoint_date = null;
}
+ this._render_checkpoint();
};
-
- SaveWidget.prototype._regularly_update_checkpoint_date = function(){
- if (!this._checkpoint_date) {
- this._set_checkpoint_status(null);
- console.log('no checkpoint done');
+
+ SaveWidget.prototype._render_checkpoint = function () {
+ /** actually set the text in the element, from our _checkpoint value
+
+ called directly, and periodically in timeouts.
+ */
+ this._schedule_render_checkpoint();
+ var el = this.element.find('span.checkpoint_status');
+ if (!this._checkpoint_date) {
+ el.text('').attr('title', 'no checkpoint');
return;
}
var chkd = moment(this._checkpoint_date);
- var longdate = chkd.format('llll');
-
- var that = this;
- var recall = function(t){
- /**
- * recall slightly later (1s) as long timeout in js might be imprecise,
- * and you want to be call **after** the change of formatting should happend.
- */
- return setTimeout(
- $.proxy(that._regularly_update_checkpoint_date, that),
- t + 1000
- );
- };
- var tdelta = Math.ceil(new Date()-this._checkpoint_date);
-
- // update regularly for the first 6hours and show
- // ago
- if(tdelta < 6*3600*1000){
- recall(_next_timeago_update(tdelta));
- this._set_checkpoint_status(chkd.fromNow(), longdate);
- // otherwise update every hour and show
- // at hh,mm,ss
- } else {
- recall(1*3600*1000);
- this._set_checkpoint_status(chkd.calendar(), longdate);
+ var long_date = chkd.format('llll');
+ var human_date;
+ var tdelta = Math.ceil(new Date() - this._checkpoint_date);
+ if (tdelta < utils.time.milliseconds.d){
+ // less than 24 hours old, use relative date
+ human_date = chkd.fromNow();
+ } else {
+ // otherwise show calendar
+ // at hh,mm,ss
+ human_date = chkd.calendar();
}
+ el.text('Last Checkpoint: ' + human_date).attr('title', long_date);
};
- SaveWidget.prototype._set_last_checkpoint = function (checkpoint) {
- if (checkpoint) {
- this._checkpoint_date = new Date(checkpoint.last_modified);
- } else {
- this._checkpoint_date = null;
+
+ SaveWidget.prototype._schedule_render_checkpoint = function () {
+ /** schedule the next update to relative date
+
+ periodically updated, so short values like 'a few seconds ago' don't get stale.
+ */
+ if (!this._checkpoint_date) {
+ return;
}
- this._regularly_update_checkpoint_date();
-
+ if ((this._checkpoint_timeout)) {
+ clearTimeout(this._checkpoint_timeout);
+ }
+ var dt = Math.ceil(new Date() - this._checkpoint_date);
+ this._checkpoint_timeout = setTimeout(
+ $.proxy(this._render_checkpoint, this),
+ utils.time.timeout_from_dt(dt)
+ );
};
SaveWidget.prototype.set_autosaved = function (dirty) {