mirror of https://github.com/keeweb/keeweb.git
fix #67: field editing bugs
This commit is contained in:
parent
b5879a3793
commit
5ee7d3800b
|
@ -33,6 +33,10 @@ _.extend(Backbone.View.prototype, {
|
|||
});
|
||||
},
|
||||
|
||||
setTimeout: function(callback) {
|
||||
setTimeout(callback.bind(this), 0);
|
||||
},
|
||||
|
||||
requestAnimationFrame: function(callback) {
|
||||
requestAnimationFrame(callback.bind(this));
|
||||
},
|
||||
|
|
|
@ -466,8 +466,9 @@ var AppView = Backbone.View.extend({
|
|||
}
|
||||
},
|
||||
|
||||
bodyClick: function() {
|
||||
bodyClick: function(e) {
|
||||
IdleTracker.regUserAction();
|
||||
Backbone.trigger('click', e);
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -154,7 +154,7 @@ var DetailsView = Backbone.View.extend({
|
|||
}
|
||||
}
|
||||
}
|
||||
this.addNewFieldView = new FieldViewCustom({ model: { name: '', title: Locale.detAddField, newField: newFieldTitle,
|
||||
this.addNewFieldView = new FieldViewCustom({ model: { name: '$', title: Locale.detAddField, newField: newFieldTitle,
|
||||
value: function() { return ''; } } });
|
||||
this.fieldViews.push(this.addNewFieldView);
|
||||
|
||||
|
@ -166,13 +166,6 @@ var DetailsView = Backbone.View.extend({
|
|||
}, this);
|
||||
},
|
||||
|
||||
getEditedField: function() {
|
||||
var edited = _.find(this.fieldViews, function(fieldView) {
|
||||
return fieldView.editing;
|
||||
});
|
||||
return edited ? edited.model.name : undefined;
|
||||
},
|
||||
|
||||
setSelectedColor: function(color) {
|
||||
this.$el.find('.details__colors-popup > .details__colors-popup-item').removeClass('details__colors-popup-item--active');
|
||||
var colorEl = this.$el.find('.details__header-color')[0];
|
||||
|
@ -322,12 +315,20 @@ var DetailsView = Backbone.View.extend({
|
|||
if (e.field) {
|
||||
if (e.field[0] === '$') {
|
||||
var fieldName = e.field.substr(1);
|
||||
if (e.title) {
|
||||
this.model.setField(fieldName, undefined);
|
||||
this.model.setField(e.title, e.val);
|
||||
if (e.newField && e.newField !== fieldName) {
|
||||
if (fieldName) {
|
||||
this.model.setField(fieldName, undefined);
|
||||
}
|
||||
fieldName = e.newField;
|
||||
var i = 0;
|
||||
while (this.model.hasField(fieldName)) {
|
||||
i++;
|
||||
fieldName = e.newField + i;
|
||||
}
|
||||
this.model.setField(fieldName, e.val);
|
||||
this.entryUpdated();
|
||||
return;
|
||||
} else {
|
||||
} else if (fieldName) {
|
||||
this.model.setField(fieldName, e.val);
|
||||
}
|
||||
} else if (e.field === 'Tags') {
|
||||
|
@ -349,15 +350,6 @@ var DetailsView = Backbone.View.extend({
|
|||
fieldView.update();
|
||||
}
|
||||
}, this);
|
||||
} else if (e.newField && e.val) {
|
||||
var field = e.newField;
|
||||
var i = 0;
|
||||
while (this.model.hasField(field)) {
|
||||
i++;
|
||||
field = e.newField + i;
|
||||
}
|
||||
this.model.setField(field, e.val);
|
||||
this.entryUpdated();
|
||||
}
|
||||
if (e.tab) {
|
||||
this.focusNextField(e.tab);
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
var FieldViewText = require('./field-view-text'),
|
||||
var Backbone = require('backbone'),
|
||||
FieldViewText = require('./field-view-text'),
|
||||
FieldView = require('./field-view'),
|
||||
Keys = require('../../const/keys'),
|
||||
Locale = require('../../util/locale'),
|
||||
kdbxweb = require('kdbxweb');
|
||||
|
||||
var FieldViewCustom = FieldViewText.extend({
|
||||
|
@ -12,12 +14,12 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
|
||||
initialize: function() {
|
||||
_.extend(this.events, FieldViewText.prototype.events);
|
||||
this.model.newFieldInitial = this.model.newField;
|
||||
},
|
||||
|
||||
startEdit: function() {
|
||||
FieldViewText.prototype.startEdit.call(this);
|
||||
if (this.model.newField) {
|
||||
if (this.model.newField && this.model.title === Locale.detAddField) {
|
||||
this.model.title = this.model.newField;
|
||||
this.$el.find('.details__field-label').text(this.model.newField);
|
||||
}
|
||||
this.$el.addClass('details__field--can-edit-title');
|
||||
|
@ -31,20 +33,16 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
},
|
||||
|
||||
endEdit: function(newVal, extra) {
|
||||
if (this.model.newField && !newVal) {
|
||||
this.model.newField = this.model.newFieldInitial;
|
||||
this.$el.find('.details__field-label').text(this.model.title);
|
||||
this.$el.find('.details__field-value').text('');
|
||||
this.value = '';
|
||||
this.$el.removeClass('details__field--can-edit-title');
|
||||
extra = _.extend({}, extra);
|
||||
if (this.model.titleChanged || this.model.newField) {
|
||||
extra.newField = this.model.title;
|
||||
}
|
||||
if (!this.model.newField) {
|
||||
this.$el.removeClass('details__field--can-edit-title');
|
||||
}
|
||||
extra = _.extend({}, extra, { newField: this.model.newField });
|
||||
if (!this.editing) {
|
||||
return;
|
||||
}
|
||||
delete this.input;
|
||||
this.stopListening(Backbone, 'click', this.fieldValueBlur);
|
||||
if (typeof newVal === 'string') {
|
||||
newVal = $.trim(newVal);
|
||||
if (this.isProtected) {
|
||||
|
@ -52,16 +50,22 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
}
|
||||
}
|
||||
FieldView.prototype.endEdit.call(this, newVal, extra);
|
||||
if (!newVal && this.model.newField) {
|
||||
this.model.title = Locale.detAddField;
|
||||
this.$el.find('.details__field-label').text(this.model.title);
|
||||
}
|
||||
if (this.model.titleChanged) {
|
||||
delete this.model.titleChanged;
|
||||
}
|
||||
},
|
||||
|
||||
startEditTitle: function() {
|
||||
var text = this.model.newField ? this.model.newField !== this.model.newFieldInitial ? this.model.newField : '' : this.model.title;
|
||||
startEditTitle: function(emptyTitle) {
|
||||
var text = emptyTitle ? '' : this.model.title || '';
|
||||
this.labelInput = $('<input/>');
|
||||
this.labelEl.html('').append(this.labelInput);
|
||||
this.labelInput.attr({ autocomplete: 'off', spellcheck: 'false' })
|
||||
.val(text).focus()[0].setSelectionRange(text.length, text.length);
|
||||
this.labelInput.bind({
|
||||
blur: this.fieldLabelBlur.bind(this),
|
||||
input: this.fieldLabelInput.bind(this),
|
||||
keydown: this.fieldLabelKeydown.bind(this),
|
||||
keypress: this.fieldLabelInput.bind(this),
|
||||
|
@ -71,56 +75,42 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
},
|
||||
|
||||
endEditTitle: function(newTitle) {
|
||||
if (this.model.newField) {
|
||||
if (newTitle) {
|
||||
this.model.newField = newTitle;
|
||||
this.edit();
|
||||
} else {
|
||||
this.endEdit();
|
||||
}
|
||||
} else {
|
||||
this.$el.find('.details__field-label').text(this.model.title);
|
||||
this.endEdit();
|
||||
if (newTitle && newTitle !== this.model.title) {
|
||||
this.trigger('change', { field: this.model.name, title: newTitle, val: this.model.value() });
|
||||
}
|
||||
if (newTitle && newTitle !== this.model.title) {
|
||||
this.model.title = newTitle;
|
||||
this.model.titleChanged = true;
|
||||
}
|
||||
this.$el.find('.details__field-label').text(this.model.title);
|
||||
delete this.labelInput;
|
||||
if (this.editing && this.input) {
|
||||
this.input.focus();
|
||||
}
|
||||
},
|
||||
|
||||
fieldLabelClick: function(e) {
|
||||
e.stopImmediatePropagation();
|
||||
if (this.model.newField || this.editing) {
|
||||
if (this.editing) {
|
||||
this.startEditTitle();
|
||||
} else if (this.model.newField) {
|
||||
this.edit();
|
||||
this.startEditTitle(true);
|
||||
} else {
|
||||
FieldViewText.prototype.fieldLabelClick.call(this, e);
|
||||
}
|
||||
},
|
||||
|
||||
fieldLabelMousedown: function() {
|
||||
if (this.editing || this.model.newField) {
|
||||
if (this.editing) {
|
||||
this.editing = false;
|
||||
this.value = this.input.val();
|
||||
this.input.unbind('blur');
|
||||
delete this.input;
|
||||
this.valueEl.html(this.renderValue(this.value));
|
||||
this.$el.removeClass('details__field--edit');
|
||||
}
|
||||
_.delay(this.startEditTitle.bind(this));
|
||||
fieldLabelMousedown: function(e) {
|
||||
if (this.editing) {
|
||||
e.stopPropagation();
|
||||
}
|
||||
},
|
||||
|
||||
fieldValueBlur: function(e) {
|
||||
if (this.protectJustChanged) {
|
||||
this.protectJustChanged = false;
|
||||
e.target.focus();
|
||||
return;
|
||||
fieldValueBlur: function() {
|
||||
if (this.labelInput) {
|
||||
this.endEditTitle(this.labelInput.val());
|
||||
}
|
||||
if (this.input) {
|
||||
this.endEdit(this.input.val());
|
||||
}
|
||||
this.endEdit(e.target.value);
|
||||
},
|
||||
|
||||
fieldLabelBlur: function(e) {
|
||||
this.endEditTitle(e.target.value);
|
||||
},
|
||||
|
||||
fieldLabelInput: function(e) {
|
||||
|
@ -132,25 +122,33 @@ var FieldViewCustom = FieldViewText.extend({
|
|||
},
|
||||
|
||||
fieldLabelKeydown: function(e) {
|
||||
e.stopPropagation();
|
||||
var code = e.keyCode || e.which;
|
||||
if (code === Keys.DOM_VK_RETURN) {
|
||||
$(e.target).unbind('blur');
|
||||
this.endEditTitle(e.target.value);
|
||||
} else if (code === Keys.DOM_VK_ESCAPE) {
|
||||
$(e.target).unbind('blur');
|
||||
this.endEditTitle();
|
||||
} else if (code === Keys.DOM_VK_TAB) {
|
||||
e.preventDefault();
|
||||
$(e.target).unbind('blur');
|
||||
this.endEditTitle(e.target.value);
|
||||
}
|
||||
},
|
||||
|
||||
fieldValueInputClick: function() {
|
||||
if (this.labelInput) {
|
||||
this.endEditTitle(this.labelInput.val());
|
||||
}
|
||||
FieldViewText.prototype.fieldValueInputClick.call(this);
|
||||
},
|
||||
|
||||
protectBtnClick: function(e) {
|
||||
e.stopPropagation();
|
||||
this.isProtected = !this.isProtected;
|
||||
this.protectBtn.toggleClass('details__field-value-btn-protect--protected', this.isProtected);
|
||||
this.protectJustChanged = true;
|
||||
if (this.labelInput) {
|
||||
this.endEditTitle(this.labelInput.val());
|
||||
}
|
||||
this.setTimeout(function() { this.input.focus(); });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -22,25 +22,6 @@ var FieldViewTags = FieldViewText.extend({
|
|||
},
|
||||
|
||||
endEdit: function(newVal, extra) {
|
||||
if (this.selectedTag) {
|
||||
if (newVal) {
|
||||
var tags = this.valueToTags(newVal);
|
||||
var last = tags[tags.length - 1];
|
||||
var isLastPart = last && this.model.tags.indexOf(last) < 0;
|
||||
if (isLastPart) {
|
||||
newVal = newVal.substr(0, newVal.lastIndexOf(last)) + this.selectedTag;
|
||||
} else {
|
||||
newVal += ', ' + this.selectedTag;
|
||||
}
|
||||
} else {
|
||||
newVal = this.selectedTag;
|
||||
}
|
||||
this.input.val(newVal);
|
||||
this.input.focus();
|
||||
this.setTags();
|
||||
delete this.selectedTag;
|
||||
return;
|
||||
}
|
||||
if (newVal !== undefined) {
|
||||
newVal = this.valueToTags(newVal);
|
||||
}
|
||||
|
@ -91,8 +72,24 @@ var FieldViewTags = FieldViewText.extend({
|
|||
tagsAutocompleteClick: function(e) {
|
||||
e.stopPropagation();
|
||||
if (e.target.classList.contains('details__tags-autocomplete-tag')) {
|
||||
this.selectedTag = $(e.target).text();
|
||||
var selectedTag = $(e.target).text(), newVal = this.input.val();
|
||||
if (newVal) {
|
||||
var tags = this.valueToTags(newVal);
|
||||
var last = tags[tags.length - 1];
|
||||
var isLastPart = last && this.model.tags.indexOf(last) < 0;
|
||||
if (isLastPart) {
|
||||
newVal = newVal.substr(0, newVal.lastIndexOf(last)) + selectedTag;
|
||||
} else {
|
||||
newVal += ', ' + selectedTag;
|
||||
}
|
||||
} else {
|
||||
newVal = selectedTag;
|
||||
}
|
||||
this.input.val(newVal);
|
||||
this.input.focus();
|
||||
this.setTags();
|
||||
}
|
||||
this.afterPaint(function() { this.input.focus(); });
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
'use strict';
|
||||
|
||||
var FieldView = require('./field-view'),
|
||||
var Backbone = require('backbone'),
|
||||
FieldView = require('./field-view'),
|
||||
GeneratorView = require('../generator-view'),
|
||||
KeyHandler = require('../../comp/key-handler'),
|
||||
Keys = require('../../const/keys'),
|
||||
|
@ -24,12 +25,13 @@ var FieldViewText = FieldView.extend({
|
|||
this.input.attr({ autocomplete: 'off', spellcheck: 'false' })
|
||||
.val(text).focus()[0].setSelectionRange(text.length, text.length);
|
||||
this.input.bind({
|
||||
blur: this.fieldValueBlur.bind(this),
|
||||
input: this.fieldValueInput.bind(this),
|
||||
keydown: this.fieldValueKeydown.bind(this),
|
||||
keypress: this.fieldValueInput.bind(this),
|
||||
click: this.fieldValueInputClick.bind(this)
|
||||
click: this.fieldValueInputClick.bind(this),
|
||||
mousedown: this.fieldValueInputMouseDown.bind(this)
|
||||
});
|
||||
this.listenTo(Backbone, 'click', this.fieldValueBlur);
|
||||
if (this.model.multiline) {
|
||||
this.setInputHeight();
|
||||
}
|
||||
|
@ -92,9 +94,9 @@ var FieldViewText = FieldView.extend({
|
|||
this.input.height(newHeight);
|
||||
},
|
||||
|
||||
fieldValueBlur: function(e) {
|
||||
if (!this.gen) {
|
||||
this.endEdit(e.target.value);
|
||||
fieldValueBlur: function() {
|
||||
if (!this.gen && this.input) {
|
||||
this.endEdit(this.input.val());
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -111,21 +113,25 @@ var FieldViewText = FieldView.extend({
|
|||
}
|
||||
},
|
||||
|
||||
fieldValueInputMouseDown: function(e) {
|
||||
e.stopPropagation();
|
||||
},
|
||||
|
||||
fieldValueKeydown: function(e) {
|
||||
KeyHandler.reg();
|
||||
e.stopPropagation();
|
||||
var code = e.keyCode || e.which;
|
||||
if (code === Keys.DOM_VK_RETURN) {
|
||||
if (!this.model.multiline || (!e.altKey && !e.shiftKey)) {
|
||||
$(e.target).unbind('blur');
|
||||
this.stopListening(Backbone, 'click', this.fieldValueBlur);
|
||||
this.endEdit(e.target.value);
|
||||
}
|
||||
} else if (code === Keys.DOM_VK_ESCAPE) {
|
||||
$(e.target).unbind('blur');
|
||||
this.stopListening(Backbone, 'click', this.fieldValueBlur);
|
||||
this.endEdit();
|
||||
} else if (code === Keys.DOM_VK_TAB) {
|
||||
e.preventDefault();
|
||||
$(e.target).unbind('blur');
|
||||
this.stopListening(Backbone, 'click', this.fieldValueBlur);
|
||||
this.endEdit(e.target.value, { tab: { field: this.model.name, prev: e.shiftKey } });
|
||||
}
|
||||
},
|
||||
|
@ -138,6 +144,7 @@ var FieldViewText = FieldView.extend({
|
|||
return;
|
||||
}
|
||||
delete this.input;
|
||||
this.stopListening(Backbone, 'click', this.fieldValueBlur);
|
||||
if (typeof newVal === 'string' && this.value instanceof kdbxweb.ProtectedValue) {
|
||||
newVal = kdbxweb.ProtectedValue.fromString(newVal);
|
||||
}
|
||||
|
|
|
@ -12,9 +12,6 @@ var FieldView = Backbone.View.extend({
|
|||
'click .details__field-value': 'fieldValueClick'
|
||||
},
|
||||
|
||||
initialize: function () {
|
||||
},
|
||||
|
||||
render: function () {
|
||||
this.value = typeof this.model.value === 'function' ? this.model.value() : this.model.value;
|
||||
this.renderTemplate({ editable: !this.readonly, multiline: this.model.multiline, title: this.model.title,
|
||||
|
@ -93,8 +90,9 @@ var FieldView = Backbone.View.extend({
|
|||
var newValText = newVal && newVal.getText ? newVal.getText() : newVal;
|
||||
var textEqual = _.isEqual(newValText, oldValText);
|
||||
var protectedEqual = (newVal && typeof newVal.getText) === (this.value && typeof this.value.getText);
|
||||
var nameChanged = extra && extra.newField;
|
||||
var arg;
|
||||
if (newVal !== undefined && (!textEqual || !protectedEqual)) {
|
||||
if (newVal !== undefined && (!textEqual || !protectedEqual || nameChanged)) {
|
||||
arg = { val: newVal, field: this.model.name };
|
||||
if (extra) {
|
||||
_.extend(arg, extra);
|
||||
|
|
Loading…
Reference in New Issue