diff --git a/IPython/html/static/notebook/js/completer.js b/IPython/html/static/notebook/js/completer.js
index fd05a217d..fce043717 100644
--- a/IPython/html/static/notebook/js/completer.js
+++ b/IPython/html/static/notebook/js/completer.js
@@ -199,15 +199,32 @@ var IPython = (function (IPython) {
this.complete.attr('id', 'complete');
this.sel = $('').attr('multiple', 'true').attr('size', Math.min(10, this.raw_result.length));
- //var pos = this.editor.cursorCoords();
- var cur = this.editor.getCursor();
- cur.ch = cur.ch-matched_text.length;
- var pos = this.editor.cursorCoords(cur);
- this.complete.css('left', pos.left-3 + 'px');
- this.complete.css('top', pos.bottom+1 + 'px');
this.complete.append(this.sel);
-
$('body').append(this.complete);
+
+ // After everything is on the page compute the postion.
+ // We invert the completion list and put it above the code if it is too
+ // close to the bottom of the page.
+ var cur = this.editor.getCursor();
+ cur.ch = cur.ch-matched_text.length;
+ var pos = this.editor.cursorCoords(cur);
+ var invert = false;
+ var left = pos.left-3;
+ var top;
+ var cheight = this.complete.height();
+ var wheight = $(window).height();
+ console.log(pos.bottom, cheight, wheight)
+ if (pos.bottom+cheight+5 > wheight) {
+ invert = true;
+ top = pos.top-cheight-4;
+ } else {
+ invert = false;
+ top = pos.bottom+1;
+ }
+ this.complete.css('left', left + 'px');
+ this.complete.css('top', top + 'px');
+
+
//build the container
var that = this;
this.sel.dblclick(function () {
@@ -218,7 +235,7 @@ var IPython = (function (IPython) {
that.keydown(event);
});
- this.build_gui_list(this.raw_result);
+ this.build_gui_list(this.raw_result, invert);
this.sel.focus();
// Opera sometimes ignores focusing a freshly created node
@@ -232,13 +249,23 @@ var IPython = (function (IPython) {
this.editor.replaceRange(completion.str, completion.from, completion.to);
}
- Completer.prototype.build_gui_list = function (completions) {
- // Need to clear the all list
- for (var i = 0; i < completions.length; ++i) {
- var opt = $('').text(completions[i].str).addClass(completions[i].type);
- this.sel.append(opt);
+ Completer.prototype.build_gui_list = function (completions, invert) {
+ invert = invert || false;
+ if (!invert) {
+ for (var i = 0; i < completions.length; ++i) {
+ var opt = $('').text(completions[i].str).addClass(completions[i].type);
+ this.sel.append(opt);
+ }
+ this.sel.children().first().attr('selected', 'true');
+ this.sel.scrollTop(0);
+ } else {
+ for (var i = (completions.length-1); i > -1; --i) {
+ var opt = $('').text(completions[i].str).addClass(completions[i].type);
+ this.sel.append(opt);
+ }
+ this.sel.children().last().attr('selected', 'true');
+ this.sel.scrollTop(this.sel[0].scrollHeight);
}
- this.sel.children().first().attr('selected', 'true');
}
Completer.prototype.close = function () {