fix #67: field editing bugs

This commit is contained in:
Antelle 2016-01-16 15:35:34 +03:00
parent b5879a3793
commit 5ee7d3800b
7 changed files with 106 additions and 109 deletions

View File

@ -33,6 +33,10 @@ _.extend(Backbone.View.prototype, {
});
},
setTimeout: function(callback) {
setTimeout(callback.bind(this), 0);
},
requestAnimationFrame: function(callback) {
requestAnimationFrame(callback.bind(this));
},

View File

@ -466,8 +466,9 @@ var AppView = Backbone.View.extend({
}
},
bodyClick: function() {
bodyClick: function(e) {
IdleTracker.regUserAction();
Backbone.trigger('click', e);
}
});

View File

@ -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);

View File

@ -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(); });
}
});

View File

@ -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(); });
}
});

View File

@ -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);
}

View File

@ -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);