diff --git a/IPython/html/notebook/handlers.py b/IPython/html/notebook/handlers.py
index c3a8cfd..1fe0d08 100644
--- a/IPython/html/notebook/handlers.py
+++ b/IPython/html/notebook/handlers.py
@@ -58,7 +58,9 @@ class NamedNotebookHandler(IPythonHandler):
else:
project = self.project + '/' + path +'/'+ name
if not nbm.notebook_exists(notebook_path):
- raise web.HTTPError(404, u'Notebook does not exist: %s' % name)
+ raise web.HTTPError(404, u'Notebook does not exist: %s' % name)
+ path = nbm.url_encode(path)
+ name = nbm.url_encode(name)
self.write(self.render_template('notebook.html',
project=project,
notebook_path=path,
diff --git a/IPython/html/services/notebooks/handlers.py b/IPython/html/services/notebooks/handlers.py
index 1e2e92b..5c9175c 100644
--- a/IPython/html/services/notebooks/handlers.py
+++ b/IPython/html/services/notebooks/handlers.py
@@ -45,8 +45,8 @@ class NotebookRootHandler(IPythonHandler):
model = nbm.notebook_model(notebook_name)
self.set_header('Location', '{0}api/notebooks/{1}'.format(self.base_project_url, notebook_name))
self.finish(jsonapi.dumps(model))
-
-
+
+
class NotebookRootRedirect(IPythonHandler):
@authenticate_unless_readonly
diff --git a/IPython/html/services/notebooks/nbmanager.py b/IPython/html/services/notebooks/nbmanager.py
index d51e865..439c614 100644
--- a/IPython/html/services/notebooks/nbmanager.py
+++ b/IPython/html/services/notebooks/nbmanager.py
@@ -20,6 +20,7 @@ import os
import uuid
from tornado import web
+from urllib import quote, unquote
from IPython.config.configurable import LoggingConfigurable
from IPython.nbformat import current
@@ -62,7 +63,23 @@ class NotebookManager(LoggingConfigurable):
name = None
path = notebook_path+'/'
return name, path
-
+
+ def url_encode(self, path):
+ parts = path.split('/')
+ path=""
+ for part in parts:
+ part = quote(part)
+ path = os.path.join(path,part)
+ return path
+
+ def url_decode(self, path):
+ parts = path.split('/')
+ path=""
+ for part in parts:
+ part = unquote(part)
+ path = os.path.join(path,part)
+ return path
+
def _notebook_dir_changed(self, new):
"""do a bit of validation of the notebook dir"""
if not os.path.isabs(new):
@@ -114,7 +131,7 @@ class NotebookManager(LoggingConfigurable):
def notebook_exists(self, notebook_path):
"""Does a notebook exist?"""
-
+
def notebook_model(self, notebook_name, notebook_path=None, content=True):
""" Creates the standard notebook model """
last_modified, contents = self.read_notebook_object(notebook_name, notebook_path)
diff --git a/IPython/html/static/notebook/js/notebook.js b/IPython/html/static/notebook/js/notebook.js
index 6df07a2..cc8fac1 100644
--- a/IPython/html/static/notebook/js/notebook.js
+++ b/IPython/html/static/notebook/js/notebook.js
@@ -78,6 +78,11 @@ var IPython = (function (IPython) {
return this._baseProjectUrl || $('body').data('baseProjectUrl');
};
+ Notebook.prototype.notebookName = function() {
+ var name = $('body').data('notebookName');
+ return name;
+ };
+
Notebook.prototype.notebookPath = function() {
var path = $('body').data('notebookPath');
if (path != 'None') {
diff --git a/IPython/html/static/notebook/js/savewidget.js b/IPython/html/static/notebook/js/savewidget.js
index 1d99d08..c421457 100644
--- a/IPython/html/static/notebook/js/savewidget.js
+++ b/IPython/html/static/notebook/js/savewidget.js
@@ -47,6 +47,8 @@ var IPython = (function (IPython) {
that.update_document_title();
});
$([IPython.events]).on('notebook_renamed.Notebook', function () {
+ that.update_notebook_name();
+ that.update_document_title();
that.update_address_bar();
});
$([IPython.events]).on('notebook_save_failed.Notebook', function () {
@@ -126,7 +128,8 @@ var IPython = (function (IPython) {
SaveWidget.prototype.update_address_bar = function(){
var nbname = IPython.notebook.notebook_name;
var path = IPython.notebook.notebookPath();
- window.location = path + nbname;
+ var state = {"path": path+nbname}
+ window.history.pushState(state, "", "/notebook/" + path+nbname);
}
diff --git a/IPython/html/static/tree/js/notebooklist.js b/IPython/html/static/tree/js/notebooklist.js
index c7de4f7..257a78d 100644
--- a/IPython/html/static/tree/js/notebooklist.js
+++ b/IPython/html/static/tree/js/notebooklist.js
@@ -25,7 +25,7 @@ var IPython = (function (IPython) {
NotebookList.prototype.baseProjectUrl = function () {
return $('body').data('baseProjectUrl');
};
-
+
NotebookList.prototype.notebookPath = function() {
var path = $('body').data('notebookPath');
if (path != "") {
diff --git a/IPython/html/tree/handlers.py b/IPython/html/tree/handlers.py
index 0ceabad..4fb53cd 100644
--- a/IPython/html/tree/handlers.py
+++ b/IPython/html/tree/handlers.py
@@ -43,11 +43,9 @@ class ProjectPathDashboardHandler(IPythonHandler):
nbm = self.notebook_manager
name, path = nbm.named_notebook_path(notebook_path)
if name != None:
- if path == None:
- self.redirect(self.base_project_url + 'notebooks/' + quote(name))
- else:
- self.redirect(self.base_project_url + 'notebooks/' + path + quote(name))
+ self.redirect(self.base_project_url + 'notebooks/' + notebook_path)
else:
+ path = nbm.url_encode(path)
project = self.project + '/' + notebook_path
self.write(self.render_template('tree.html',
project=project,