I have a custom grid and some cells have a cell editor , an Ext.form.TextField, in order to modify value of the cell.
Here is how is defined the TextField:
var labelTextEditor = new Ext.form.TextField({
allowBlank: false,
maxLength: 256,
id: "labelTextEditor",
maxLengthText: Label.conf.ui.javascript.TooLongText,
validateOnChange: true,
validator: function(value) {
console.log(value);
if (value == "" && value.trim() == "") {
return formatMessage(Label.conf.ui.supv.LabelMandatory);
} else
return true;
},
msgTarget: 'under',
listeners: {
focus( a, event, eOpts ){
var rowIndex = customFieldGrid.getSelectionModel().getCurrentPosition().row;
if(rowIndex !== undefined && rowIndex !== null){
a.setValue(view.listOfServiceDefinition[0].customFields[rowIndex].labels[userLanguagePrefix]);
}
},
blur(a, event, eOpts){
var cellValue = a.getValue();
if(cellValue !== undefined && cellValue !== null){
a.setValue(cellValue);
}else{
a.setValue("");
}
}
}
});
When I focus on the cell, it keeps me the value that was there before focusing on the cell, thanks to the focus listener. But when I lose focus, the cell displays nothing. When I click back on it, the value is displayed again and can be edited. So the problem is that when I lose focus, the value cannot be kept displayed on the cell. I've tried to blur event but didn't help...
Problem here is your blur event. As Per Documentation blur event Fires when this Component loses focus. So in your case when you loosing focus your blur event is firing. And As I can see in your blur event You are setting some other values, Therefor it is coming as empty.
This line is causing an issue in your code :
else{
a.setValue("");
}
I also created one fiddler to understand blur and focus.
Fiddle
Related
I have an input field with the name box. I can move forward after input by
box.addEventListener('input', function () {
if(!isNaN(parseInt(box.value))){
box.value = "";
}else if(box != null){
box.nextSibling.focus();
}
});
And it's working alright. I wish to move to the previous sibling of the input by backspace, and I am doing it by the previous sibling and kind of the same logic
box.addEventListener('keyup', function (e) {
if(e.key == 'Backspace' && box != null){
box.previousSibling.focus();
}
})
But doing this only works for the first backspace properly, for the rest of the inputs I need to backspace twice. I tried with the keydown event too and even that wasn't perfect.
The problem is that (in the browsers you and I are using) input events are processed before keyup events, so you press backspace on a non-empty box and a character is deleted, so input is processed then the next sibling is selected, then the keyup is processed and you move to the previous sibling, which looks like going nowhere.
You can fix this by storing the box where the value changed, then if that reference is not null on backspace keyup you can move to the previous sibling of the box where the keyup event fired, otherwise move to the previous sibling of the box where the input event fired.
const boxes = document.getElementById('boxes');
let inputInput = null;
for(let i = 0; i < 12; i++)
{
const box = document.createElement('input');
box.type="text"
box.addEventListener('input', function (e)
{
if(!isNaN(parseInt(box.value)))
{
box.value = "";
}
else if(box != null)
{
inputInput = box;
box.nextSibling.focus();
}
});
box.addEventListener('keyup', function (e)
{
if(e.key == 'Backspace' && box != null)
{
if(inputInput == null)
{
box.previousSibling.focus();
}
else
{
inputInput.previousSibling.focus();
inputInput = null;
}
}
});
boxes.appendChild(box);
}
<div id="boxes">
</div>
The problem with this solution is that event precedence is not part of the specification, so this is not necessarily cross browser compatible, i.e. in some browsers keyup might happen before input.
I have input text fields in jsp, and I use onChange="validation(this);" to check if null input and so on, but when I use tab key, cursor will be move to next field, how can keep cursor on validation field?
function validation(id) {
var obj = document.getElementById(id);
obj.value = obj.value.toUpperCase();
if(value == "") {
obj.focus();
obj.select();
}
}
You can add an event on 'blur'. There after check for the keyCode. For tab key it is 0. Using an setTimeout since the current element will loss focus as soon as the is a onblur event. Therefore providing a sufficient time gap before focusing back on the element
var obj = document.getElementById('inputField');
obj.addEventListener('blur', function(event) {
if (event.which === 0 && event.target.value == '') {
setTimeout(function(){
event.target.focus();
},1000)
}
})
<input id='inputField' onchange='validation(this.id)'>
Adding the validation with button instead onchange event in input box .And if(value == "") value is a undefined so change the if condition with !Obj.value.trim() its catch the false condition .trim() used for remove unwanted space
Updated
use with blur
event instead of onchange .Its only allow to next input only present input was filled.
function validation(obj) {
obj.value = obj.value.toUpperCase();
if(!obj.value.trim()) {
obj.focus();
//obj.select();
}
}
<input id="input" type="text" onblur="validation(this,event)">
<input id="input" type="text" onblur="validation(this,event)">
I have an input text and a button for checking the input text value.
When the web page is loaded, the input text has the focus and this value is empty by default.
So when you put the focus outside the input text (onblur), the check_input_value(event) function executes the alert("Your input value must not empty") one time when the input text value is empty.
This works perfectly in Firefox. But in Chrome, this alert is executed indefinitely instead of one time.
Here the code (you can try it (try it with Chrome) at https://jsfiddle.net/fcg86gyb/ ) :
<input type="text" id="input_text"> <input type="button" value="Check input value" onclick="check_input_value(event);">
<script type="text/javascript">
//Get the input text element :
input_text = document.getElementById("input_text");
//Put focus in input text :
input_text.focus();
/*Add event listener in the input text element.
On blur, if your input value is empty, then execute check_input_value(event) function
to check input text value :
*/
input_text.addEventListener('blur',
function(event)
{
var event = window.event || event;
check_input_value(event);
}
, false
);
//Function for checking input text value :
//if the input value is empty, display alert "Your input value must not empty", and put focus in input text.
function check_input_value(event)
{
var event = window.event || event;
if(input_text.value == "")
{
alert("Your input value must not empty");
input_text.focus();
return false;
}
}
</script>
So how to execute one time the alert instead of indefinitely in Chrome?
The chrome execute indefinitely instead of one time because your function always return the focus to the input text and always you change the focus your function will be call. In Firefox works well because the input text does not receive the focus in the end of the javascript function.
If you remove input_text.focus(); it is going to work.
Thanks for the link to jsfiddle. I tried working on it and found that the input_text.focus() was getting called recursively.
I commented that and it worked. I think you should call the input_text.focus() somewhere outside where the call may not be recursive.
This is the link where I tried: https://jsfiddle.net/fcg86gyb/1/
//Get the input text element :
input_text = document.getElementById("input_text");
//Put focus in input text :
input_text.focus();
/*Add event listener in the input text element.
On blur, if your input value is empty, then execute check_input_value(event) function :
*/
input_text.addEventListener('blur',
function(event)
{
var event = window.event || event;
check_input_value(event);
}
, false
);
//Function for checking input text value :
//if the input value is empty, display alert "Your input value must not empty", and put focus in input text.
function check_input_value(event)
{
var event = window.event || event;
if(input_text.value == "")
{
alert("Your input value must not empty");
//input_text.focus();
return false;
}
}
If you need to maintain the focus on the textbox after showing the alert box only once, you can make use of temporary variable as I stated in the comment and you can achieve the same as follows:
//Get the input text element :
input_text = document.getElementById("input_text");
//Put focus in input text :
input_text.focus();
var temp = 0;
/*Add event listener in the input text element.
On blur, if your input value is empty, then execute check_input_value(event) function :
*/
input_text.addEventListener('blur',
function(event)
{
var event = window.event || event;
if(temp == 0)
{
check_input_value(event);
}
else
{
button_focus();
}
}
, false);
//Function for checking input text value :
//if the input value is empty, display alert "Your input value must not empty", and put focus in input text.
function check_input_value(event)
{
var event = window.event || event;
if(input_text.value == "")
{
alert("Your input value must not empty");
input_text.focus();
temp = 1;
return false;
}
}
function button_focus()
{
if(input_text.value == "")
{
input_text.focus();
}
temp = 0;
return false;
}
Hope it helps.
This seems to be a bug in Chrome 52 (discussed here). A workaround that came up was to remove the blur event and reattach it in a timeout:
if(input_text.value == "")
{
alert("Your input value must not empty");
var tmpBlur = input_text.blur;
input_text.blur = null;
setTimeout(function() {
input_text.focus();
input_text.blur = tmpBlur;
}, 0);
return false;
}
https://jsfiddle.net/wpys5x75/3/
EDIT:
However it looks like you still get the same infinite loop when you click outside the window. Another work around would be to assign a different value and then reassign the value in the timeout:
if(input_text.value == "")
{
alert("Your input value must not empty");
input_text.value = ' ';
setTimeout(function() {
input_text.focus();
input_text.value = '';
}, 0);
return false;
}
https://jsfiddle.net/wpys5x75/5/
I too faced same issue; I solved it by calling the focus method using setTimeout method.
Code goes as below:
function check_input_value(event)
{
var event = window.event || event;
if(input_text.value == "")
{
alert("Your input value must not empty");
setTimeout (function(){input_text.focus()}, 0);
return false;
}
}
I have two fields. An autocomplete field and a simple textbox. When user selects an item from autocomplete field I want to set focus on the next field and call a function when enter key is pressed on it. Here is the code:
this.initPiecesAutocomplete = function (){
$('#product_autocomplete_input1')
.autocomplete('ajax_products_list.php', {
minChars: 1,
autoFill: true,
max:20,
matchContains: true,
mustMatch:true,
scroll:false,
cacheLength:0,
formatItem: function(item) {
return item[1]+' - '+item[0];
}
}).result(self.getCount);
this.getCount = function(event, data, formatted) {
if (data == null)
return false;
$('#pieceCount').focus();
$('#pieceCount').on('keypress', function(e) {
if (e.which == 13) {
self.addPiece(event, data, formatted)
}
});
}
After selecting an item from the autocomplete field (by pressing the enter key), instead of setting focus on the #pieceCountfield, self.addPiece() is called. What's wrong?
When a SlickGrid is set up with:
enableAddRow: false,
enableCellNavigation: true,
autoEdit: true
and the last column in that SlickGrid is configured with:
editor: null,
focusable: false,
selectable: false
When attempting to tab out of the SlickGrid by tabbing out of the second to last column in the last row, I would expect the focus to be moved to the next focusable element outside of the grid, but it does not.
See this example, and try to tab out of the grid from the last row. I would expect the focus to shift to the textboxes below the grid, but it does not and instead focus is lost while the active cell in the grid is not reset.
Is there a way to fix this? To ensure, when tabbing out of an editable cell that is followed by an uneditable unfocusable cell, that focus is moved out of the grid?
A workaround would be to make the last column focusable: true, but that is not an option since it breaks the user experience forcing the user to tab through an uneditable cell before reaching an editable cell.
Can you try below if it works for you.
yourGrid.onKeyDown.subscribe(function(event) {
if (event.keyCode === 9 && event.shiftKey === false) { // check its only tab not shift tab
if (yourGrid.getActiveCell().cell === lastCol) { // check if the current cell is the last editable column
$("#b").trigger('focus'); // this or below line should work for focus, "b" is your text input
document.getElementById("b").focus(); // either this or above line
event.stopImmediatePropagation();
}
}
});
UPDATE
Fixed it by changing the code in the plugin. The issue were coming and I think its a bug in the Slickgrid. After the change in below function your example is working in my local. Please replace the below function code and let me know if this is working for you.
function setActiveCellInternal(newCell, opt_editMode) {
var lastActiveCell = null;
var lastActiveRow = null;
if (activeCellNode !== null) {
makeActiveCellNormal();
$(activeCellNode).removeClass("active");
if (rowsCache[activeRow]) {
$(rowsCache[activeRow].rowNode).removeClass("active");
}
var lastActiveCell = getCellFromNode(activeCellNode); // my added
lastActiveRow = activeRow;
}
var activeCellChanged = (activeCellNode !== newCell);
activeCellNode = newCell;
if (activeCellNode != null) {
//alert('1-3')
activeRow = getRowFromNode(activeCellNode.parentNode);
activeCell = activePosX = getCellFromNode(activeCellNode);
if (opt_editMode == null) {
opt_editMode = (activeRow == getDataLength()) || options.autoEdit;
}
$(activeCellNode).addClass("active");
$(rowsCache[activeRow].rowNode).addClass("active");
//alert(options.editable +' - '+ opt_editMode);
if (options.editable && opt_editMode && isCellPotentiallyEditable(activeRow, activeCell) && ((lastActiveCell !== activeCell || lastActiveRow !== activeRow) ) ) { // not sure if need acheck on row also
clearTimeout(h_editorLoader);
if (options.asyncEditorLoading) {
h_editorLoader = setTimeout(function () {
makeActiveCellEditable();
}, options.asyncEditorLoadDelay);
} else {
makeActiveCellEditable();
}
//alert('1-4')
}
} else {
activeRow = activeCell = null;
//alert('1-5')
}
if (activeCellChanged) {
//alert('1-6')
trigger(self.onActiveCellChanged, getActiveCell());
}
}
See the link below.
https://github.com/mleibman/SlickGrid/issues/104
Since you cannot tab out of the last cell, you can try committing the change when you click on save changes
if (Slick.GlobalEditorLock.isActive() &&
!Slick.GlobalEditorLock.commitCurrentEdit()) return;
Will that work?
Can you try to replace the gotoRight function with below code in slick.grid.js file and try.
function gotoRight(row, cell, posX) {
if (cell >= columns.length) {
return null;
}
do {
cell += getColspan(row, cell);
}
while (cell < columns.length && !canCellBeActive(row, cell));
if(cell == columns.length && !canCellBeActive(row, cell)) {
setActiveCell(row,cell-1)
}
if (cell < columns.length) {
return {
"row": row,
"cell": cell,
"posX": cell
};
}
return null;
}