Merge pull request #5320 from jdfreder/focusbug_tt

Fix for Tooltip & completer click focus bug.
pull/37/head
Paul Ivanov 12 years ago
commit 997a9735f0

@ -147,10 +147,7 @@ var IPython = (function (IPython) {
}
if (this.code_mirror) {
this.code_mirror.on('blur', function(cm, change) {
// Check if this unfocus event is legit.
if (!that.should_cancel_blur()) {
$([IPython.events]).trigger('command_mode.Cell', {cell: that});
}
$([IPython.events]).trigger('command_mode.Cell', {cell: that});
});
}
};
@ -331,18 +328,7 @@ var IPython = (function (IPython) {
return false;
}
};
/**
* Determine whether or not the unfocus event should be aknowledged.
*
* @method should_cancel_blur
*
* @return results {bool} Whether or not to ignore the cell's blur event.
**/
Cell.prototype.should_cancel_blur = function () {
return false;
};
/**
* Focus the cell in the DOM sense
* @method focus_cell

@ -358,21 +358,6 @@ var IPython = (function (IPython) {
return false;
};
/**
* Determine whether or not the unfocus event should be aknowledged.
*
* @method should_cancel_blur
*
* @return results {bool} Whether or not to ignore the cell's blur event.
**/
CodeCell.prototype.should_cancel_blur = function () {
// Cancel this unfocus event if the base wants to cancel or the cell
// completer is open or the tooltip is open.
return IPython.Cell.prototype.should_cancel_blur.apply(this) ||
(this.completer && this.completer.is_visible()) ||
(IPython.tooltip && IPython.tooltip.is_visible());
};
CodeCell.prototype.select_all = function () {
var start = {line: 0, ch: 0};
var nlines = this.code_mirror.lineCount();
@ -508,6 +493,23 @@ var IPython = (function (IPython) {
return data;
};
/**
* handle cell level logic when a cell is unselected
* @method unselect
* @return is the action being taken
*/
CodeCell.prototype.unselect = function () {
var cont = IPython.Cell.prototype.unselect.apply(this);
if (cont) {
// When a code cell is usnelected, make sure that the corresponding
// tooltip and completer to that cell is closed.
IPython.tooltip.remove_and_cancel_tooltip(true);
if (this.completer !== null) {
this.completer.close();
}
}
return cont;
};
IPython.CodeCell = CodeCell;

@ -73,7 +73,6 @@ var IPython = (function (IPython) {
var Completer = function (cell) {
this._visible = false;
this.cell = cell;
this.editor = cell.code_mirror;
var that = this;
@ -85,15 +84,9 @@ var IPython = (function (IPython) {
});
};
Completer.prototype.is_visible = function () {
// Return whether or not the completer is visible.
return this._visible;
};
Completer.prototype.startCompletion = function () {
// call for a 'first' completion, that will set the editor and do some
// special behaviour like autopicking if only one completion availlable
//
// special behavior like autopicking if only one completion available.
if (this.editor.somethingSelected()) return;
this.done = false;
// use to get focus back on opera
@ -221,17 +214,37 @@ var IPython = (function (IPython) {
}
}
this.complete = $('<div/>').addClass('completions');
this.complete.attr('id', 'complete');
// Currently webkit doesn't use the size attr correctly. See:
// https://code.google.com/p/chromium/issues/detail?id=4579
this.sel = $('<select style="width: auto"/>')
.attr('multiple', 'true')
.attr('size', Math.min(10, this.raw_result.length));
this.complete.append(this.sel);
this._visible = true;
$('body').append(this.complete);
if (!this.visible) {
this.complete = $('<div/>').addClass('completions');
this.complete.attr('id', 'complete');
// Currently webkit doesn't use the size attr correctly. See:
// https://code.google.com/p/chromium/issues/detail?id=4579
this.sel = $('<select/>')
.attr('tabindex', -1)
.attr('multiple', 'true');
this.complete.append(this.sel);
this.visible = true;
$('body').append(this.complete);
//build the container
var that = this;
this.sel.dblclick(function () {
that.pick();
});
this.sel.focus(function () {
that.editor.focus();
});
this._handle_keydown = function (cm, event) {
that.keydown(event);
};
this.editor.on('keydown', this._handle_keydown);
this._handle_keypress = function (cm, event) {
that.keypress(event);
};
this.editor.on('keypress', this._handle_keypress);
}
this.sel.attr('size', Math.min(10, this.raw_result.length));
// After everything is on the page, compute the postion.
// We put it above the code if it is too close to the bottom of the page.
@ -249,28 +262,9 @@ var IPython = (function (IPython) {
this.complete.css('left', left + 'px');
this.complete.css('top', top + 'px');
//build the container
var that = this;
this.sel.dblclick(function () {
that.pick();
});
this.sel.blur(this.close);
this.sel.keydown(function (event) {
that.keydown(event);
});
this.sel.keypress(function (event) {
that.keypress(event);
});
// Clear and fill the list.
this.sel.text('');
this.build_gui_list(this.raw_result);
this.sel.focus();
IPython.keyboard_manager.disable();
// Opera sometimes ignores focusing a freshly created node
if (window.opera) setTimeout(function () {
if (!this.done) this.sel.focus();
}, 100);
return true;
};
@ -288,20 +282,16 @@ var IPython = (function (IPython) {
};
Completer.prototype.close = function () {
this._visible = false;
if (this.done) return;
this.done = true;
$('.completions').remove();
IPython.keyboard_manager.enable();
$('#complete').remove();
this.editor.off('keydown', this._handle_keydown);
this.editor.off('keypress', this._handle_keypress);
this.visible = false;
};
Completer.prototype.pick = function () {
this.insert(this.raw_result[this.sel[0].selectedIndex]);
this.close();
var that = this;
setTimeout(function () {
that.editor.focus();
}, 50);
};
Completer.prototype.keydown = function (event) {
@ -312,16 +302,10 @@ var IPython = (function (IPython) {
if (code == keycodes.enter) {
CodeMirror.e_stop(event);
this.pick();
}
// Escape or backspace
else if (code == keycodes.esc) {
} else if (code == keycodes.esc || code == keycodes.backspace) {
CodeMirror.e_stop(event);
this.close();
this.editor.focus();
} else if (code == keycodes.backspace) {
this.close();
this.editor.focus();
} else if (code == keycodes.tab) {
//all the fastforwarding operation,
//Check that shared start is not null which can append with prefixed completion
@ -332,8 +316,6 @@ var IPython = (function (IPython) {
this.insert(sh);
}
this.close();
CodeMirror.e_stop(event);
this.editor.focus();
//reinvoke self
setTimeout(function () {
that.carry_on_completion();
@ -341,10 +323,23 @@ var IPython = (function (IPython) {
} else if (code == keycodes.up || code == keycodes.down) {
// need to do that to be able to move the arrow
// when on the first or last line ofo a code cell
event.stopPropagation();
CodeMirror.e_stop(event);
var options = this.sel.find('option');
var index = this.sel[0].selectedIndex;
if (code == keycodes.up) {
index--;
}
if (code == keycodes.down) {
index++;
}
index = Math.min(Math.max(index, 0), options.length-1);
this.sel[0].selectedIndex = index;
} else if (code == keycodes.left || code == keycodes.right) {
this.close();
}
};
Completer.prototype.keypress = function (event) {
// FIXME: This is a band-aid.
// on keypress, trigger insertion of a single character.
@ -358,26 +353,16 @@ var IPython = (function (IPython) {
// don't handle keypress if it's not a character (arrows on FF)
// or ENTER/TAB
if (event.charCode === 0 ||
code == keycodes.enter ||
code == keycodes.tab
code == keycodes.tab ||
code == keycodes.enter
) return;
var cur = this.editor.getCursor();
var completion = {
str: String.fromCharCode(event.which),
type: "introspection",
from: cur,
to: cur,
};
this.insert(completion);
this.close();
this.editor.focus();
setTimeout(function () {
that.carry_on_completion();
}, 50);
};
IPython.Completer = Completer;
return IPython;

@ -17,6 +17,7 @@
font-family: @monoFontFamily;
font-size: 110%;
color: @textColor;
width: auto;
}
.completions select option.context {

@ -1,7 +1,3 @@
.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0}
.clearfix:after{clear:both}
.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}
.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}
article,aside,details,figcaption,figure,footer,header,hgroup,nav,section{display:block}
audio,canvas,video{display:inline-block;*display:inline;*zoom:1}
audio:not([controls]){display:none}
@ -856,6 +852,10 @@ a.label:hover,a.label:focus,a.badge:hover,a.badge:focus{color:#fff;text-decorati
.show{display:block}
.invisible{visibility:hidden}
.affix{position:fixed}
.clearfix{*zoom:1}.clearfix:before,.clearfix:after{display:table;content:"";line-height:0}
.clearfix:after{clear:both}
.hide-text{font:0/0 a;color:transparent;text-shadow:none;background-color:transparent;border:0}
.input-block-level{display:block;width:100%;min-height:30px;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}
@-ms-viewport{width:device-width}.hidden{display:none;visibility:hidden}
.visible-phone{display:none !important}
.visible-tablet{display:none !important}
@ -1497,7 +1497,7 @@ p{margin-bottom:0}
.celltoolbar input[type=checkbox]{margin:0;margin-left:4px;margin-right:4px}
.celltoolbar .ui-button{border:none;vertical-align:top;height:20px;min-width:30px}
.completions{position:absolute;z-index:10;overflow:hidden;border:1px solid #ababab;border-radius:4px;-webkit-box-shadow:0 6px 10px -1px #adadad;-moz-box-shadow:0 6px 10px -1px #adadad;box-shadow:0 6px 10px -1px #adadad}
.completions select{background:#fff;outline:none;border:none;padding:0;margin:0;overflow:auto;font-family:monospace;font-size:110%;color:#000}
.completions select{background:#fff;outline:none;border:none;padding:0;margin:0;overflow:auto;font-family:monospace;font-size:110%;color:#000;width:auto}
.completions select option.context{color:#0064cd}
#menubar .navbar-inner{min-height:28px;border-top:1px;border-radius:0 0 4px 4px}
#menubar .navbar{margin-bottom:8px}

Loading…
Cancel
Save